You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Split from #3563. The dispatcher tranche is complete (gap ratchet 27→0, #3569#3571#3575#3577#3579), but the dispatcher is not the only server surface: @objectstack/rest mounts a second, larger route set the client also reaches — and it has never been audited with the same rigor.
Known zero-expression routes (from the PR-1 sweep, rest-server.ts line refs in the audit doc)
Route family
Routes
GET /search?q&objects&limit&perObject
1
POST /email/send
1
forms/:slug (get / submit / lookup)
3
Record shares GET/POST/DELETE /data/:object/:id/shares[/:shareId]
Plus the reverse direction that tranche 1 deliberately left out of scope: client surfaces that target REST-only routes (views CRUD, permissions, workflow, approvals, realtime, notification devices/preferences, presigned storage, import jobs) — currently expressed but with no ledger row anywhere asserting their server side exists.
Proposed method — same as tranche 1, one new problem to solve
Enumerate the REST mounts (rest-server.ts is large; the mounts are server.<verb>() calls — scriptable).
Extend the ledger (or add a sibling rest-route-ledger.ts in packages/rest) with per-route dispositions.
New problem tranche 1 didn't have: REST route registration is method calls, not a registry with .list(). Either add an introspection seam to the REST server (preferred — mirrors DomainHandlerRegistry.list()), or pin the mount list the way LEGACY_CHAIN_PREFIXES pins the if-chain.
Acceptance
Every REST-mounted route has a reviewed disposition.
A ratchet equivalent to tranche 1's, wired into CI.
The reverse direction closed: every client method's target route provably exists on some server surface.
Split from #3563. The dispatcher tranche is complete (gap ratchet 27→0, #3569 #3571 #3575 #3577 #3579), but the dispatcher is not the only server surface:
@objectstack/restmounts a second, larger route set the client also reaches — and it has never been audited with the same rigor.Known zero-expression routes (from the PR-1 sweep,
rest-server.tsline refs in the audit doc)GET /search?q&objects&limit&perObjectPOST /email/sendforms/:slug(get / submit / lookup)GET/POST/DELETE /data/:object/:id/shares[/:shareId]POST /data/:object/:id/clonePOST /analytics/dataset/querysharing/rules(incl./evaluate)reports(incl./run,/schedule,/schedules)external-datasource/*(external-datasource-routes.ts)Plus the reverse direction that tranche 1 deliberately left out of scope: client surfaces that target REST-only routes (
viewsCRUD,permissions,workflow,approvals,realtime, notification devices/preferences, presigned storage, import jobs) — currently expressed but with no ledger row anywhere asserting their server side exists.Proposed method — same as tranche 1, one new problem to solve
server.<verb>()calls — scriptable).rest-route-ledger.tsinpackages/rest) with per-route dispositions..list(). Either add an introspection seam to the REST server (preferred — mirrorsDomainHandlerRegistry.list()), or pin the mount list the wayLEGACY_CHAIN_PREFIXESpins the if-chain.Acceptance
Refs: audit doc
docs/audits/2026-07-dispatcher-client-route-coverage.md§8; ledger scope note atpackages/runtime/src/route-ledger.tsheader.