Repository navigation
Route audit tranche 2: the @objectstack/rest surface (search / forms / reports / sharing / …) — #3563 follow-up #3587
Description
Activity
- added a commit that references this issue
on Jul 27, 2026 PR-1 merged: #3609 — every route
@objectstack/restmounts (89) now carries a reviewed disposition inpackages/rest/src/rest-route-ledger.ts(38 sdk / 43 gap, ratcheted / 3 server-only / 3 public / 2 mismatch), with real enumeration on both sources (RouteManager viagetRoutes(); the two bypassing registrars via captured mock-server registrations) and the client-method direction guarded package-side. All five guard directions were negative-tested.The issue's anticipated "no introspection seam" problem mostly didn't materialize —
RouteManager/getRoutes()already existed; only the 9 directly-mounted routes needed their own enumeration path.Findings split out per convention:
- POST /api/v1/packages is a publish-vs-install shape collision — REST registers first and shadows the dispatcher (#3587 finding) #3610 —
POST /api/v1/packagespublish-vs-install shape collision (REST registers first and shadows the dispatcher). - UI view route speaks two dialects — REST's path-param form is unreachable by the SDK's query-param form (#3587 finding) #3611 — UI view path-vs-query dialect split.
- 21 client SDK methods target routes no server surface mounts — delete on the open major train, or build the servers (#3587 finding) #3612 — 21 client methods target routes no surface mounts (+ the 4 ghost
DEFAULT_*_ROUTESspec tables) — in progress now, riding the open breaking-change window.
Remaining under this issue: gap-closure batches (43 → 0), the third surface (
service-storage/service-i18nautonomous mounts), and the reverse-direction guard.
Generated by Claude Code
- POST /api/v1/packages is a publish-vs-install shape collision — REST registers first and shadows the dispatcher (#3587 finding) #3610 —
- added 5 commits that reference this issue
on Jul 27, 2026 The REST-surface tranche is complete — the ledger now carries zero mismatches and zero gaps, both bounds CI-pinned.
The arc, PR by PR:
- feat(rest): REST route ledger + conformance guard — route audit tranche 2 PR-1 (#3587) #3609 — the audit itself:
rest-route-ledger.ts(109 routes, both registrar families), theRestServer.getRoutes()+ mock-server direct-mount enumeration seams, the two-sided conformance guard, and the honest starting state: 2mismatch, 43gap. - 21 client SDK methods target routes no server surface mounts — delete on the open major train, or build the servers (#3587 finding) #3612/feat(client,spec)!: delete 21 dead SDK methods + the four ghost route tables under them (#3612) #3616 — subtractive prelude: 21 dead client methods + the four ghost
DEFAULT_*_ROUTESspec tables deleted, so closure work built on a surface with no fiction in it. - fix(rest,client)!: reconcile the two REST↔client mismatches the audit ledgered (#3610, #3611) #3621 — both mismatches reconciled: marketplace publish moved off the bare
POST /packages(which install owns; closes POST /api/v1/packages is a publish-vs-install shape collision — REST registers first and shadows the dispatcher (#3587 finding) #3610),meta.getViewswitched to the path dialect both surfaces accept (closes UI view route speaks two dialects — REST's path-param form is unreachable by the SDK's query-param form (#3587 finding) #3611). Mismatches 2 → 0. - feat(client): close the 9 metadata-family REST gaps (#3587 batch 1/5) #3625 — metadata 9 (7 new
meta.*methods; the two compound-name rows turned out already expressible — the audit note claiming an encoding barrier was wrong, and the correction is now URL-pinned). 43 → 34. - feat(client): close the 8 reports-family REST gaps (#3587 batch 2/5) #3626 — reports 8 (new
reportsnamespace, 204-safe deletes). 34 → 26. - feat(client): close the approvals (6) + record-shares (3) REST gaps (#3587 batch 3/5) #3629 — approvals 6 + record-shares 3 (recall/revise/resubmit/remind/requestInfo/comment; new
sharesnamespace). 26 → 17. - feat(client): close the final 17 REST gaps — ratchet 17→0 (#3587 batches 4+5/5) #3633 — sharing-rules 5 + security-explain 2 + search 1 + data-actions 2 + email 1 + analytics 1 + external-datasource 5 (
shares.rules.*,security.explain,search,data.clone/data.export,email.send,analytics.queryDataset,datasources.external.*). 17 → 0.
Every closed gap = a client method speaking the handler's exact wire shape, a URL-pinning unit test, and a flipped ledger row the two-sided guard verifies (
@objectstack/client163 tests,@objectstack/rest394). The gap ratchet now rests at 0 and stays there — a newgaprow demands an explicit, reviewed decision.Still open under this issue (from the ledger's NOT-COVERED note): the third surface — services that autonomously mount routes on the host
IHttpServer(service-storage'sstorage-routes.ts, i.e. the SDK's whole storage surface, andservice-i18n). Those live outside@objectstack/restand need their own enumeration seam before they can be ledgered. Leaving the issue open for that tranche.
Generated by Claude Code
- feat(rest): REST route ledger + conformance guard — route audit tranche 2 PR-1 (#3587) #3609 — the audit itself:
Closing as completed — all three acceptance criteria are met and CI-pinned:
- Every REST-mounted route has a reviewed disposition — 109 routes across both registrar families in
rest-route-ledger.ts. - Ratchet wired into CI — mismatch bound 0 (fix(rest,client)!: reconcile the two REST↔client mismatches the audit ledgered (#3610, #3611) #3621), gap bound 0 (feat(client): close the 9 metadata-family REST gaps (#3587 batch 1/5) #3625 → feat(client): close the final 17 REST gaps — ratchet 17→0 (#3587 batches 4+5/5) #3633), both enforced by the two-sided conformance guard.
- Reverse direction closed — the 21 no-serving-surface client methods are deleted (21 client SDK methods target routes no server surface mounts — delete on the open major train, or build the servers (#3587 finding) #3612/feat(client,spec)!: delete 21 dead SDK methods + the four ghost route tables under them (#3612) #3616), the two wrong-shape ones reconciled (fix(rest,client)!: reconcile the two REST↔client mismatches the audit ledgered (#3610, #3611) #3621), and every ledger row naming a client method is verified to resolve.
The third surface noted in the ledger header (autonomously-mounted
service-storage/service-i18nroutes — 13 mounts, currently expressed by the SDK but backed by no ledger) is split to #3636, following the same close-and-split convention this issue got from #3563.
Generated by Claude Code
- Every REST-mounted route has a reviewed disposition — 109 routes across both registrar families in
- added a commit that references this issue
on Aug 17, 2026
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.