Found while implementing #15488 (the dispatcher's scope-strip regex). ⛔ Filed unassigned and ungraded on purpose — grading and routing are triage's. Filed by the os-dev implementer on session session_01D47qPfEWVPmhguWgBZCi5N, branch claude/issue-15488-scope-strip-prefix.
⚠️ Title repaired after posting. The first title spelled the retired form with an angle-bracket id placeholder and GitHub's body sanitizer ate the bracketed span, leaving /projects//... — the documented failure, reproduced live. Every placeholder below is spelled :id for that reason.
The measurement
#15488 repaired HttpDispatcher.dispatch's scope strip: the regex matched the pre-ADR-0006 /projects/ prefix while its own comment, and extractEnvironmentIdFromPath next to it, said /environments/. Sweeping the repo for the same class of stale prose turned up two more sites, both in packages/rest/src/rest-server.ts, located by sentence rather than by line:
- The
environmentId === 'platform' docblock — "a reserved virtual id used by Studio to address the control plane through the regular project URL shape (/projects/platform/...)", and the sentence after it says "It is NOT a row in the projects table".
- The single-project default-fallback comment — "so bare
/api/v1/data/... URLs (no /projects/:id prefix, no hostname mapping, no header) resolve to the lone project's kernel".
Both name the retired spelling as the current one. The authority in the other direction is unambiguous and already published:
- ADR-0006 v4, second addendum (D2 executed 2026-08-28): the API surfaces are renamed to
environment / environments with no aliases, no dual-spelling interval.
content/docs/api/environment-routing.mdx, migration checklist: "Replace /api/v1/projects/:projectId/... with /api/v1/environments/:environmentId/...", and "there is no alias, so the old spelling does not resolve".
- The same file's own live code spells the scoped base
/environments/:environmentId in every one of its isScoped sites.
Why it is filed rather than fixed in that PR
Two reasons, and the second is the binding one.
Scope. #15488's card is the dispatcher's strip. These are a different package's prose.
The file is claimed. packages/rest/src/rest-server.ts is held by two open pull requests — #15673 and #15395 — measured before the sweep and re-checked after. A drive-by comment edit in a file two branches are rewriting is how a merge conflict gets manufactured out of a one-line prose fix, so the implementer stopped and reported instead of reaching in. Whoever takes this should coordinate with those two rather than race them.
Confidence, stated in both directions
✅ Certain: the two sentences exist, they name /projects/, and the ruling that retired that spelling is dated and published.
⚠️ This is prose only. Nothing here changes what rest-server.ts routes: its executable scoped-base construction already reads /environments/:environmentId. What is at stake is the reading, and #15488 is the record of what stale routing prose costs — there, the comment said /environments/ while the regex said /projects/, and the comment is what would have stopped a reader noticing the live 404. This is the same class with the halves swapped, which is why it is worth a card rather than a shrug.
⚠️ Not measured here: whether the 'platform' virtual id is itself still addressed the way that docblock describes, in any spelling. That question belongs to the cloud repository's host wiring — the same boundary #15256 and #15163 both hit — and it is a real fork in the disposition: if the shape is live the sentence needs its prefix corrected, and if it is not, the paragraph may want retiring rather than transliterating. ⛔ Do not size this before that answer.
Re-check
git grep -n "projects/platform" -- packages/rest/src/rest-server.ts
git grep -n "prefix, no hostname mapping" -- packages/rest/src/rest-server.ts
⚠️ Locate by the sentence, ⛔ not by line — every anchor in the #14503 / #15488 family had moved within two days.
Refs: #15488 (the card this was found under) · #15673 / #15395 (the two open PRs holding the file) · ADR-0006 v4, second addendum.
Found while implementing #15488 (the dispatcher's scope-strip regex). ⛔ Filed unassigned and ungraded on purpose — grading and routing are triage's. Filed by the
os-devimplementer on sessionsession_01D47qPfEWVPmhguWgBZCi5N, branchclaude/issue-15488-scope-strip-prefix./projects//...— the documented failure, reproduced live. Every placeholder below is spelled:idfor that reason.The measurement
#15488 repaired
HttpDispatcher.dispatch's scope strip: the regex matched the pre-ADR-0006/projects/prefix while its own comment, andextractEnvironmentIdFromPathnext to it, said/environments/. Sweeping the repo for the same class of stale prose turned up two more sites, both inpackages/rest/src/rest-server.ts, located by sentence rather than by line:environmentId === 'platform'docblock — "a reserved virtual id used by Studio to address the control plane through the regular project URL shape (/projects/platform/...)", and the sentence after it says "It is NOT a row in the projects table"./api/v1/data/...URLs (no/projects/:idprefix, no hostname mapping, no header) resolve to the lone project's kernel".Both name the retired spelling as the current one. The authority in the other direction is unambiguous and already published:
environment/environmentswith no aliases, no dual-spelling interval.content/docs/api/environment-routing.mdx, migration checklist: "Replace/api/v1/projects/:projectId/...with/api/v1/environments/:environmentId/...", and "there is no alias, so the old spelling does not resolve"./environments/:environmentIdin every one of itsisScopedsites.Why it is filed rather than fixed in that PR
Two reasons, and the second is the binding one.
Scope. #15488's card is the dispatcher's strip. These are a different package's prose.
The file is claimed.
packages/rest/src/rest-server.tsis held by two open pull requests — #15673 and #15395 — measured before the sweep and re-checked after. A drive-by comment edit in a file two branches are rewriting is how a merge conflict gets manufactured out of a one-line prose fix, so the implementer stopped and reported instead of reaching in. Whoever takes this should coordinate with those two rather than race them.Confidence, stated in both directions
✅ Certain: the two sentences exist, they name
/projects/, and the ruling that retired that spelling is dated and published.rest-server.tsroutes: its executable scoped-base construction already reads/environments/:environmentId. What is at stake is the reading, and #15488 is the record of what stale routing prose costs — there, the comment said/environments/while the regex said/projects/, and the comment is what would have stopped a reader noticing the live 404. This is the same class with the halves swapped, which is why it is worth a card rather than a shrug.'platform'virtual id is itself still addressed the way that docblock describes, in any spelling. That question belongs to the cloud repository's host wiring — the same boundary #15256 and #15163 both hit — and it is a real fork in the disposition: if the shape is live the sentence needs its prefix corrected, and if it is not, the paragraph may want retiring rather than transliterating. ⛔ Do not size this before that answer.Re-check
Refs: #15488 (the card this was found under) · #15673 / #15395 (the two open PRs holding the file) · ADR-0006 v4, second addendum.