Repository navigation
Description
Found by the #3587 tranche-2 audit (client-side sweep for PR #3609). Five client surface families build URLs that exist on no server surface — not the dispatcher, not @objectstack/rest, not the autonomous service mounts. Every call is a guaranteed 404. They are the SDK-side siblings of the disease #3595 just deleted server-side: each family is underwritten only by a spec DEFAULT_*_ROUTES table that nothing consumes.
The dead families (packages/client/src/index.ts)
| Surface | Methods | Client lines | Ghost spec table |
|---|---|---|---|
permissions |
check, getObjectPermissions, getEffectivePermissions (3) |
:2775, :2784, :2793 | DEFAULT_PERMISSION_ROUTES (plugin-rest-api.zod.ts:962-1012 — and its prefix is /api/v1/auth, so it wouldn't even match) |
realtime |
connect, disconnect, subscribe, unsubscribe, setPresence, getPresence (6) |
:2807-:2863 | DEFAULT_REALTIME_ROUTES; service-realtime registers zero HTTP routes; the dispatcher deliberately never advertises /realtime (http-dispatcher.ts:1128-1133) |
workflow |
getConfig, getState, transition (3) |
:2877-:2895 | DEFAULT_WORKFLOW_ROUTES |
views |
list, get, create, update, delete (5) |
:3024-:3066 | DEFAULT_VIEW_ROUTES — no /ui/views route anywhere (both surfaces serve only /ui/view/:object…); note the client even disagrees with its own ghost table (PUT vs the table's PATCH, plugin-rest-api.zod.ts:1077) |
notifications devices/prefs |
registerDevice, unregisterDevice, getPreferences, updatePreferences (4) |
:3082-:3114 | ADR-0012:376 describes the intended /notifications/devices server that was never built; dispatcher mounts only '', read, read/all |
(client.events is fine — it's an explicitly local in-memory buffer, no HTTP.)
Why now
A major/breaking train is loading (#3562, #3581, #3593, #3595 all shipped feat(…)! this window). Deleting these methods is client-breaking and will never be cheaper. Leaving them means the #3587 reverse-direction guard ("every client method's target route provably exists") must carry 21 permanent exemptions — the guard would be born lying.
Proposal
- Delete the five families from the client (+ their tests/README rows), changeset per the launch-window convention (
minor+feat(client)!). - Delete the four ghost
DEFAULT_*_ROUTEStables fromplugin-rest-api.zod.ts(same tombstone treatment asDEFAULT_DISPATCHER_ROUTES, feat(spec)!: delete DEFAULT_DISPATCHER_ROUTES + sweep last graphql fixture debris (#3586) #3595); regenerateapi-surface.json. - Where a product story exists (realtime per ADR; notification devices per ADR-0012), re-adding the surface comes back with its server and a ledger row — the guard then keeps it honest.
- Then land the reverse-direction guard with zero exemptions.
Alternative — implement the missing servers instead — is a per-family product decision (views CRUD, device registry, workflow FSM HTTP, realtime HTTP session protocol); nothing in the audit suggests these are imminent, and the guard shouldn't wait on them.
Acceptance
- No client method builds a URL that no server surface mounts (guard-enforced, no exemption list).
api-surface.jsonregenerated; docs sweep for the removed namespaces.
Activity
feat(client,spec)!: delete 21 dead SDK methods + the four ghost route…
docs(releases,nav): v17 follow-up — Console gap backfill, sidebar res…
fix(spec,rest,runtime): request bodies are checked against the schema…