Skip to content

21 client SDK methods target routes no server surface mounts — delete on the open major train, or build the servers (#3587 finding) #3612

Description

@os-zhuang

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)

SurfaceMethodsClient linesGhost spec table
permissionscheck, getObjectPermissions, getEffectivePermissions (3):2775, :2784, :2793DEFAULT_PERMISSION_ROUTES (plugin-rest-api.zod.ts:962-1012 — and its prefix is /api/v1/auth, so it wouldn't even match)
realtimeconnect, disconnect, subscribe, unsubscribe, setPresence, getPresence (6):2807-:2863DEFAULT_REALTIME_ROUTES; service-realtime registers zero HTTP routes; the dispatcher deliberately never advertises /realtime (http-dispatcher.ts:1128-1133)
workflowgetConfig, getState, transition (3):2877-:2895DEFAULT_WORKFLOW_ROUTES
viewslist, get, create, update, delete (5):3024-:3066DEFAULT_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/prefsregisterDevice, unregisterDevice, getPreferences, updatePreferences (4):3082-:3114ADR-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

  1. Delete the five families from the client (+ their tests/README rows), changeset per the launch-window convention (minor + feat(client)!).
  2. Delete the four ghost DEFAULT_*_ROUTES tables from plugin-rest-api.zod.ts (same tombstone treatment as DEFAULT_DISPATCHER_ROUTES, feat(spec)!: delete DEFAULT_DISPATCHER_ROUTES + sweep last graphql fixture debris (#3586) #3595); regenerate api-surface.json.
  3. 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.
  4. 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.json regenerated; docs sweep for the removed namespaces.

Refs: #3587, PR #3609; precedent #3595/#3586.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions