Repository navigation
docs(rest): the 'platform' virtual-id docblock names the live /environments/ URL family - #18479
Conversation
…ents URL family `resolveProtocol`'s `environmentId === 'platform'` docblock described the reserved virtual id as being addressed "through the regular project URL shape (`/projects/platform/...`)" — the spelling ADR-0006 v4's second addendum (D2, executed 2026-08-28) retired with no alias and no grace period. The behaviour the paragraph describes is live on both sides of the seam, so this corrects the prefix rather than retiring the paragraph: the host enables environment scoping precisely so `/api/v1/environments/platform/...` resolves to the control-plane protocol, and this file's own `resolveProtocol` still short-circuits `environmentId === 'platform'` to `this.protocol`. Comment-only, line-count neutral (13,877 lines before and after). The sibling site that calls `/projects/:environmentId` "the retired spelling" is correct and deliberately untouched. Claude-Session: https://claude.ai/code/session_01DvvamiacK328idtBYJBxV3 Co-authored-by: Claude <noreply@anthropic.com>
…st-server-platform-url-spelling
… docblock The corrected docblock ships inside the published artifact — it is present in `dist/index.d.ts`, `dist/index.d.cts` and both bundles — so `skip-changeset` does not hold: measured against `files[]` (`dist`, `README.md`, `CHANGELOG.md`), `projects/platform` now returns zero hits across everything this package publishes, where it returned four before. Claude-Session: https://claude.ai/code/session_01DvvamiacK328idtBYJBxV3 Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): ⛔ 4 release-owned page(s) name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 15 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 75e72864293b8e7e2e931cb5749d10d137868777 && git checkout 75e72864293b8e7e2e931cb5749d10d137868777
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 85c6d76ec42a879f219436eaa58bda06c68298b2 3091b1615e49f6811ed97fcc8c737f4afa4289bf && git checkout -B drift-repro 85c6d76ec42a879f219436eaa58bda06c68298b2 && git merge --no-ff 3091b1615e49f6811ed97fcc8c737f4afa4289bf
node scripts/docs-audit/affected-docs.mjs --json 85c6d76ec42a879f219436eaa58bda06c68298b2
|
Fixes #15858
Clause-②: no
What this is
RestServer'senvironmentId === 'platform'docblock described the reserved virtual id as being addressed "through the regular project URL shape (/projects/platform/...)" — the spelling ADR-0006 v4's second addendum (D2, executed 2026-08-28) retired with no alias and no grace period. It now reads "through the regular environment URL shape (/environments/platform/...)".Comment-only. Two lines change; the file is line-count neutral at 13,877 lines before and after.
Why the prefix is corrected and the paragraph is NOT retired
The card opened an explicit fork — "if the shape is live the sentence needs its prefix corrected, and if it is not, the paragraph may want retiring rather than transliterating" — and held its second half behind a cross-repo reading. That reading came back (#15861, comment
5683109868): the shape is live, addressed under the/environments/spelling. The host enables environment scoping precisely so/api/v1/environments/platform/...resolves to the control-plane protocol; its kernel resolver returns no per-environment kernel for that id; a live pin drivesroutePath: '/environments/platform/meta'. Framework-side, this file's ownresolveProtocolstill short-circuitsenvironmentId === 'platform'to the control-plane protocol.So every behavioural claim in the paragraph is true today, on both sides of the seam. Only the URL spelling and the phrase "the regular project URL shape" were not — which is exactly the prefix-correction arm, the same shape as the half PR #16543 already landed.
What was measured, not assumed
How many sites are left, and by what predicate. Located by symbol, never by line — the line numbers in this card's family have drifted repeatedly (the reading seat named
:1788-1794/:4623; the PM measured:1841/:4674; both were right on their own day). Predicate: aprojectsURL-shaped path literal inpackages/rest/src/rest-server.ts— 2 hits, one of which is correct and stays. Widened topackages/rest(src + test) it is 3 hits; the third is the same correct sentence indiscovery-per-request-protocol.test.ts. Line-wrapping hides two of the card's own quoted phrases from a naive grep, so the sweep was re-run over comment text with the wrapping joined.Zero-hit control. A zero here is a trap this card has already sprung once: the literal token
projects/:idreturns 0 onorigin/mainwhile the real spellings are/projects/platform/...and/projects/:environmentId. Every zero below carries a same-subject control word known to be present:/environmentsoccurs 31 times in this file andprojectoccurs 101 times, so the grep can see this family.skip-changesetwas measured, not assumed.packages/restpublishesfiles: ["dist", "README.md", "CHANGELOG.md"]. The tsup DTS rollup preserves this docblock, so it ships: before the editprojects/platformappeared in 4 published files (dist/index.js,dist/index.cjs,dist/index.d.ts,dist/index.d.cts, atindex.d.ts:536); after it appears in 0, andenvironments/platformappears in the same 4. Published bytes move, so this takes apatchchangeset rather than the label.Acceptance notes — out of scope, noted and not filed here
resolveProtocolfrom a position where nothing binds it. Atrest-server.ts:1825-1846it is immediately followed by a second block comment (:1847-1853) that binds toresolveHostnameCached, so TSDoc attaches the nearer one and this paragraph documents no declaration at all.resolveProtocolhas its own, newer docblock at:1930-1948. That is very likely how the stale spelling survived a rename sweep: the text is invisible where a reader of the method would look for it, and it still ships indist/index.d.ts. ⛔ Not repaired here — re-attaching or deleting it is a different class from this card's spelling fix, and the card's own fork was decided for transliteration.resolveRequestEnvironmentIdnow tries the host-injectedRestRequestEnvResolverseam (ADR-0076 D11 step ④) first. The method's own bound docblock at:1863-1874states the current chain correctly. Same paragraph-position problem as note 1, and not a claim about the'platform'special case this card is graded on.packages/specconsistently names the cloud control plane's environment rowsys_environment(discovery.zod.ts:414,platform-object-names.ts:151), so the sentence is plausibly stale too — but the authority is the cloud repository, and this seat did not measure it there./projects/:environmentId"the retired spelling" are correct and untouched (rest-server.ts:4674,discovery-per-request-protocol.test.ts:359) — they document the repair that landed under [finding]registerDiscoveryEndpoints' auth branch strips only the retired/projects/:environmentId, so a scoped/discoveryadvertisesroutes.authstill scoped — and with an unsubstituted:environmentId#16538. Harmonising the two directions would have made the right one wrong.Verification
Everything below was run at
3091b1615, the head this PR ships — the whole gate union was re-run there afterorigin/mainwas merged in, so no reading predates the tree it describes.Gate derivation from the actual changed paths,
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, re-derived after the changeset existed and again after the merge (identical 56-command list each time), then reconciled with--rancarrying every exit code:pnpm check:cross-package-test-inputs— exit 1, pre-existing and not this diff's. It namespackages/cli/test/init-created-files-summary.e2e.test.tsdescendingpackages/spec/dist/; neither path is in this diff, and it reds wherever thatdist/is built. Filed as [finding] check:cross-package-test-inputs passes in CI and fails on a built tree — its verdict is a function of gitignored build state #18353 / [regression] check:cross-package-test-inputs 的裁决取决于被 gitignore 的空目录 packages/spec/dist 存不存在 —— 构建过的工作树一律红,CI 绿只因那一步跑在构建之前(#18340 引入) #18348, so no new card.pnpm check:dual-build-cjs-loads— first run exited 3 (PREREQUISITE NOT MET: it reads a realdist/for every published package and 43 had none). ⛔ A 3 is not a pass, so the repo was built (turbo run build --filter=!@objectstack/docs --concurrency=2, 73/73 tasks, 8m06s) and the gate re-run: exit 0 — 104 published require entry points across 67 packages load, 620 emitted CommonJS files parse.pnpm lint— repo-wide, exit 0. Run unconditionally: the derivation does not name this family, a standing blind spot in this lane. No.cache/objectui-*exists in this worktree, so the known false-positive family cannot be present.pnpm --filter @objectstack/rest typecheck— exit 0 (tsc --noEmitplus the test-layer check: 0 files / 0 errors / 0 pinned signatures).pnpm --filter @objectstack/rest test— exit 0, 192 files, 3215 passed, 1 skipped.pnpm --filter '@objectstack/rest^...' buildthenpnpm --filter @objectstack/rest build— exit 0 both; the second is what the published-artifact measurement above was read from.grep -naPfor control bytes over both changed files — no hits, andpnpm check:nul-bytesis green in the union above.Every exit code was captured by redirecting first and reading
$?before any pipe.Authored by the
domain:cliexecution seat's dev run, sessionsession_01DvvamiacK328idtBYJBxV3— durable attribution in prose, because a PR-body EDIT through REST appends its own footer block whatever footer the body already carries (measured on this PR: one session-URL footer sent, two footers stored).Generated by Claude Code