Skip to content

The projects.* SDK namespace targets the control plane, which no in-repo ledger can vouch for #3655

Description

@os-zhuang

Surfaced by the capstone URL-conformance guard (#3642). Not a bug — a documented hole, filed so it doesn't read as "audited and fine."

What the sweep found

The guard drives every ObjectStackClient method and matches the URL it builds against the union of all four in-repo ledgers. 196 of ~219 methods matched. Every single unmatched one was in projects.* — 23 methods, all targeting /api/v1/cloud/*:

projects.list → GET /api/v1/cloud/environments
projects.create → POST /api/v1/cloud/environments
projects.get → GET /api/v1/cloud/environments/:id
projects.packages.* → …/environments/:id/packages…
…23 in total

Why they legitimately match nothing here

/api/v1/cloud/* is the control plane, served by the sibling cloud repo. This repo not only doesn't mount those routes, it actively refuses them — packages/runtime/src/http-dispatcher.ts:

// Guard against matching control-plane routes like /cloud/environments.if(path.includes('/cloud/environments/'))returnundefined;

So no ledger in this repository can honestly carry a row for them, and the guard exempts the /api/v1/cloud/ prefix.

Why it still deserves tracking

This is the same posture the whole #3563 audit exists to eliminate — 23 SDK methods that are expressed, presumably working, and guarded by nothing. The audit just cannot reach them from this side of the repo boundary. projects.updateVisibility could be renamed on the cloud side tomorrow and nothing here would notice.

The exemption is bounded from both ends in the guard so it can't quietly widen: only projects.* may use the prefix (a non-projects method reaching /cloud/ fails the suite), and the sweep asserts the namespace is still reaching it at all.

Options

  1. A ledger in the cloud repo, mirroring the tranche-1/2/3 shape, with its client half importing @objectstack/client and asserting the same URL conformance from that side. Correct, and the only option that actually closes it.
  2. A published route manifest from cloud that this repo can pin against — weaker (a manifest can drift from the routes it describes) but cheap, and it would at least catch a rename.
  3. Leave it exempt and accept that the control-plane SDK surface is unguarded.

Recommendation: option 1, scoped as its own tranche in the cloud repo, since that is where the routes are declared and the tranche-1 lesson (each package verifies its own half) applies across the repo boundary the same way.

Refs: #3642 (the guard), #3563 / #3587 / #3636 (the three in-repo tranches).

Metadata

Metadata

Assignees

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