docs(audit): the control-plane surface is guarded now — from the other side of the boundary (#3655) - #3707
Merged
Conversation
…r side of the boundary (#3655) §10's capstone exempts `/api/v1/cloud/*` because nothing in this repo serves those routes, and the comment said only "tracked separately (#3655)". The ledger now exists, in `cloud` — `packages/service-cloud/src/cloud-route-ledger.ts`, 90 routes with reviewed dispositions, plus a client half that drives THIS SDK with a recording fetch and matches every `projects.*` URL against it. It had to live there: cloud depends on this repo, never the reverse, so it is the only place the mounted route set and `@objectstack/client` are both in scope. The exemption stays — this suite still cannot see those routes — but it is now a statement about where the coverage lives, not that there is none. That guard immediately found `projects.listTemplates` building `/api/v1/cloud/templates`, which no registrar in either repo mounts (#3702): the sixth instance of the #3584 / #3611 / #3636 class, and the first one only a cross-repo guard could have seen. Adds §13 with the disposition counts, both findings, and the one consequence of pinning: cloud asserts against `.objectstack-sha`, so a `projects.*` change here is not verified against the control plane until that pin moves. Co-Authored-By: Claude <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 13 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
The Check Changeset gate requires every PR to add one; an empty-frontmatter changeset is its own sanctioned "this PR releases nothing" declaration, which is what a comment-and-docs change should say rather than minting a version bump for prose. Same form as .changeset/adr-0104-design-doc-only.md. Co-Authored-By: Claude <noreply@anthropic.com>
os-zhuang
marked this pull request as ready for review
July 27, 2026 15:29
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Companion to objectstack-ai/cloud#888, which closes #3655. Comments and docs only — no behaviour, no test logic changed.
Why
§10's capstone (
client-url-conformance.test.ts) exempts/api/v1/cloud/*because nothing in this repo serves those routes — the dispatcher actively refuses them. The comment said only "tracked separately (#3655)", which was accurate when written and is now stale in a way that matters: a reader has no way to tell whether the 23 exemptedprojects.*methods are guarded somewhere or simply unguarded.They are guarded, as of cloud#888. The ledger lives in
cloud(packages/service-cloud/src/cloud-route-ledger.ts) — 90 routes with reviewed dispositions, plus a client half that drives this SDK with a recordingfetchand matches everyprojects.*URL against it.It had to live there: cloud depends on this repo, never the reverse, so it is the only place the mounted route set and
@objectstack/clientare both in scope. The exemption stays, because this suite still cannot see those routes — but it is now a statement about where the coverage lives, not that there is none.What changed
client-url-conformance.test.ts— theCONTROL_PLANEcomment now names the file on the other side and why it can only live there.docs/audits/2026-07-dispatcher-client-route-coverage.md— new §13 with the disposition counts (22sdk/ 14gap/ 6mismatch/ 48server-only+public), both findings, and the follow-up list entry flipped from "needs a ledger" to done.What the cloud-side guard found immediately
client.projects.listTemplates()builds/api/v1/cloud/templates, which no registrar in either repo mounts — filed as #3702. The string occurs exactly once per repo: the call itself. Templates are real as data (sys_package_templates, a filteredsys_packageview) but never as a route.Sixth instance of the
the method exists ≠ the method can be calledclass, afteranalytics.explain/analytics.meta(#3584),meta.getView(#3611),i18n.getTranslations/getFieldLabels(#3636) — and the first that only a cross-repo guard could see, which is exactly the argument #3655 made when it was filed.Also found: a duplicate route registration on the cloud side whose "legacy alias" comment aliases nothing (cloud#887).
One consequence worth stating
Cloud pins the SDK by
.objectstack-sha, so its guard asserts against the framework revision cloud builds and ships against — the right revision to check. The consequence: aprojects.*change landing onmainhere is not verified against the control plane until that pin moves. Recorded in §13 rather than left implicit.Tests
client-url-conformance.test.ts— 3 passed (unchanged; comment-only edit, run to confirm the capstone still holds).🤖 Generated with Claude Code
https://claude.ai/code/session_01K35y3ovfWtCkBHYFCqUfAt
Generated by Claude Code