Uh oh!
There was an error while loading. Please reload this page.
docs(api): correct the environment-routing scoping instructions for standalone os serve - #12487
Conversation
…tandalone `os serve` The "Server configuration" section told authors to enable environment-scoped routing by declaring `api.enableProjectScoping: true` in `objectstack.config.ts`, and the info Callout below it reinforced that promise. On the default `os serve` path neither is true: a bare `defineStack()` config is not host-shaped, so the CLI boots `createStandaloneStack()` and `mergeBootConfig` lets the boot result win those two scoping keys. The section now states the override, separates the two keys (one is contradicted, the other merely redundant), names the config shape in which the flag is actually live, and corrects the Callout's claim about when the CLI reads `config.api`. The `os:check` marker and the snippet under it are unchanged — the block is valid authoring, and it still type-checks. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjM2ia8Av1v5NqfqQEQmC6
yinlianghui
commented
Aug 26, 2026
PM review — You caught that the card's own suggested workaround was falseThis is the part I want on the record. My dispatch (Zone 2B) said the honest repair "names the actual conditions under which the flag is live — host-shaped config, or You read it, and one of the conditions I handed you does not exist. Verified independently:
Zone 2A — the Callout was the half I was most worried about, and you fixed itThe Zone 2D — you made the distinction I flagged and did not blur the two keysExactly right, and measured:
Verified: Zone 1 heldThe Landing condition
Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#12451
What was false
content/docs/api/environment-routing.mdxtold authors to enableenvironment-scoped routing by writing
api.enableProjectScoping: trueinobjectstack.config.ts, and the info Callout directly below the fencereinforced the promise ("The CLI reads the resolved value from the exported
config (
config.api) when registering the REST and dispatcher plugins"). Onthe default
os servepath both halves mislead:defineStack()config carries no instantiated plugins, soisHostConfigis false (packages/cli/src/utils/plugin-detection.ts:11-16).shouldBootWithLibrarytherefore returns true andserve.tsbootscreateStandaloneStack()(packages/cli/src/commands/serve.ts:1703-1751).mergeBootConfigmerges the boot result over the authored config per key,and the boot builder wins the two scoping keys
(
packages/cli/src/utils/merge-boot-config.ts:41-52).config.apiatserve.ts:3115— after that merge — andforwards it to both the REST and dispatcher plugins.
Per the card's routing note, the producer that is wrong is the docs page,
not the runtime: the override is deliberate, documented at its own seam, and
pinned by
packages/cli/src/utils/merge-boot-config.test.ts. No CLI source istouched here.
What the repair says now
The
## Server configurationsection leads with scoping being a host decision,then states the standalone override explicitly, and separates the two keys —
which the original section, and the card, treated as one:
enableProjectScoping: trueis contradicted. The standalone boot resultships
false(packages/runtime/src/standalone-stack.ts:786-793), so noscoped routes are registered.
projectResolution: 'auto'is redundant, not false. The boot builderpins the same
'auto', so the page's value happens to match. Any otherstrategy declared here is silently replaced.
The prose then names where the block is live (a host-shaped config, whose
pluginsarray carries instantiated plugin objects — the shape amulti-environment host assembles; this open-core CLI supports
standaloneonly), and the info Callout keeps its true half about
defineStackstrictparsing while its last sentence is corrected to say the CLI reads
config.apiafter the boot result is merged in.
The
{/* os:check */}marker and the snippet under it are unchanged. Theblock is valid authoring — it type-checks and
defineStackaccepts it — sothere was no reason to unmark it; the false claim was in the surrounding prose,
not in the code.
Two measurements that changed what got written
The card's own suggested remedy is not authorable. The card and the triage
comment both propose naming
bootMode: 'off'/OS_MODE=offas the escapehatch.
OS_MODE=offis real (an env var, read inplugin-detection.ts:49-50),but
bootModeis not a declared key onObjectStackDefinitionSchema, whichis a
strictObject. Measured against the built spec:Publishing
bootMode: 'off'as an authoring instruction would have replaced onefalse instruction with another. The page now names it accurately: it works only
on an exported config that did not go through
defineStack's strict parse, andit drops the CLI to its legacy lightweight assembler rather than producing a
scoped standalone host — so it is recorded, not recommended.
The census moved. The card cites #11473's figure of 22 sites for
enableProjectScoping: true. Re-measured onorigin/main@b6c96bcea5: 27sites across 15 files, and the conclusion holds — every one is a test, a doc
comment (
packages/cli/src/commands/serve.ts:3112,packages/client/src/index.ts:2112), or this page. Zero real in-repodeployments, so this page is still the only place a user is told to set it.
#11999 / PR #12444 has landed —
packages/runtime/src/standalone-stack.tsnow ships the declared
'auto'rather than the undeclared'none'. That iswhat makes
projectResolutionredundant rather than contradicted, and is whythe two keys get two sentences instead of one.
Verification
Gate union derived from the change set itself via
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack(nohand-written path list), re-run in full at
a1a0b5f65a— the final commit —with exit codes captured before any pipe. All 23 families green, including
check:doc-anchors,check:doc-authoring,check:doc-frontmatter,check:docs-single-h1,check-docs-section-name, and theos:checksurface:Two gates first returned
PREREQUISITE NOT MET — nothing was measured(
@objectstack/formula,@objectstack/lint,@objectstack/client-reactnotbuilt); the closures were built and both re-ran green. That refusal is recorded
here because it is not a finding and must not be read as one.
Repo-wide
pnpm lintis narrowed deliberately, and the narrowing is measuredrather than assumed: eslint's flat config declares
files:populations of**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}only, and runningeslint --no-inline-config --format jsonon the changed file returns 1 result,0 errors, with the message
File ignored because no matching configuration was supplied.Type-aware linting is not enabled anywhere in the config (noparserOptions.project), so an.mdx-only diff cannot move any verdict on anyuntouched file.
Docs-only: this PR releases nothing, so it carries
skip-changesetrather thana changeset.
Generated by Claude Code