Repository navigation
feat(spec)!: a stack's datasources collection refuses a datasource named default, the host-reserved name - #23757
Conversation
…th its two controls Claude-Session: https://claude.ai/code/session_01UvyD7nLUx7XGKKQVF37FY9 Co-authored-by: Claude <noreply@anthropic.com>
…ment in the dropped-refinements ledger Claude-Session: https://claude.ai/code/session_01UvyD7nLUx7XGKKQVF37FY9 Co-authored-by: Claude <noreply@anthropic.com>
…rved datasource name refusal Claude-Session: https://claude.ai/code/session_01UvyD7nLUx7XGKKQVF37FY9 Co-authored-by: Claude <noreply@anthropic.com>
…ult, with its control Claude-Session: https://claude.ai/code/session_01UvyD7nLUx7XGKKQVF37FY9 Co-authored-by: Claude <noreply@anthropic.com>
…s four new sites Claude-Session: https://claude.ai/code/session_01UvyD7nLUx7XGKKQVF37FY9 Co-authored-by: Claude <noreply@anthropic.com>
… line, where the stack-collection census reads it Claude-Session: https://claude.ai/code/session_01UvyD7nLUx7XGKKQVF37FY9 Co-authored-by: Claude <noreply@anthropic.com>
…ack-datasource-default-refused
📓 Docs Drift Check4 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. What this run could not see
Coarse fallback — 142 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 ce1a746bfdf5dc51cebc686f6312f65982c966ec && git checkout ce1a746bfdf5dc51cebc686f6312f65982c966ec
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 140238a47b892ef9234052e44267ec3739fa79c2 a6f3e6e812fc97a0bc664b54004f394713f074fe && git checkout -B drift-repro 140238a47b892ef9234052e44267ec3739fa79c2 && git merge --no-ff a6f3e6e812fc97a0bc664b54004f394713f074fe
node scripts/docs-audit/affected-docs.mjs --json 140238a47b892ef9234052e44267ec3739fa79c2 |
Contract reviewServed-tier: Inputs: card #23634 (body and all eight comments — the proxy ruling A ① Derived judgmentsEvery accept-set or public-surface change the diff implies, each judged:
② Semver level
③ Boundary flagsDev deviations (report
Dev
Dev out-of-scope finding (the published JSON Schema stays wider than the parse at these four sites) — answered: recorded in the ledger (① item 6); closing it is a projection-arm decision for the spec lane, not this card. Reviewer's own flags:
Implemented-by: VERDICT: PASS |
席位核对 — ACCEPT · objectstack
|
Fixes #23634
Clause-②: no
What
A stack's
datasourcescollection now refuses an entry nameddefaultat authoring:defineStack,os validateand publish. This is triage's proxy ruling A (issue comment 6189356908).defaultis the host's primary datasource. The runtime declares and connects it itself (DefaultDatasourcePlugin), andAppPlugin.start()refuses a stack that declares it in every boot posture. The authoring doors accepted the same stack, so its author met the refusal only after the boot's earlier plugins had started.superRefineon the stack'sdatasourcescollection (STACK_DEFINITION_COLLECTIONS_SHAPEinpackages/spec/src/stack.zod.ts). It is ⛔ not onDatasourceSchema, whose documents include the host's owndefaultrow. The issue is located atdatasources.N.name, codecustom. The map formdatasources: { default: { … } }is refused the same way, because the key normalizes tonamebefore the parse.name === 'default', exactly asapp-plugin.tscompares it. Every other spelling (Default,' default', …) is already refused byDatasourceSchema.name's snake_case pattern, never by this rule.OS_DATABASE_URLand omit the entry, or declare the datasource under another name and route objects to it (an object'sdatasource, or adatasourceMappingrule).stack-datasource-host-reserved-name-refused. The changeset.changeset/23634-stack-datasource-default-refused.mdis a BREAKINGminor(pre mode) with theregistereddisposition, the FROM → TO table and the one-line fix.z.toJSONSchema()has no arm for a refinement, so the published JSON Schema stays wider than the parse at the four installed-packagemanifest.datasourcessites. These are recorded inpackages/spec/dropped-refinements.baseline.json(+4 sites, total 759 → 763), as the build requires. No arm of the closedrefinement-projection.tslist fits ("an element'snameis not X"). Adding one is a public-contract decision, so it is not made here.Untouched, as the ruling and the claim require:
DatasourceSchema(packages/spec/src/data/datasource.zod.ts),packages/cli/src/commands/serve.ts(PR #23631's remedy line stays as written),skills/**, andcontent/docs/releases/.Fallback clause: no config that boots today is newly refused
I re-measured this on this branch, using the source CLI (
bin/run-dev.js serve) on a host config that declaresdatasources: [{ name: 'default', driver: 'sqlite', … }]. The fixture usesdefineStack(…, { strict: false })so that the boot is what judges it.OS_DATABASE_URL=file:…: exit 1,[AppPlugin] app 'com.example.fx' declares a datasource named 'default' — that name is reserved for the host's primary datasource. …--dev: exit 1, the same refusal.These agree with the readings dev's M2, M3 and M4 and with production M1 (PR #23631's no-storage refusal), all in the report on #23634. In-repo producers of the shape: none. The candidates
git grepfound are a runtime pin that feeds a raw bundle toAppPlugin(still green, 12/12), REST/metadata-door tests of the host's own row, and engine driver maps. None of them goes through the stack collection.Pins
packages/spec/src/stack-datasource-host-reserved-name.test.ts(7 tests):defineStackrefuses the array form and the map form withSTACK_SCHEMA_INVALID/ 422, one issue atdatasources.N.name;ObjectStackDefinitionSchemaparse refuses it;fx_primarypasses;defaultrow parses throughDatasourceSchema.packages/cli/test/stack-datasource-default-validate-door.test.ts(integration tier, 2 spawns):os validate --jsonexits 1 with exactly one error,customatdatasources.0.name, carrying the sentence andOS_DATABASE_URL. CONTROL: the same stack withfx_primaryexits 0 withvalid: true.Verification
Measured on head
a6f3e6e8, which is this branch merged withorigin/maina869ea63throughscripts/pm/os-regen-merge.sh. Pre-merge readings are ona085cc9b.pnpm --filter @objectstack/spec build: exit 0.check:generated: all 14 artifacts up to date.scripts/dropped-refinements.test.tsandsrc/migrations/migrations.test.ts: 212/212.pnpm --filter @objectstack/spec teston the pre-merge tree: 679 files passed. The one red was the ledger's header total, fixed in109c9e90and then 27/27.typecheck: exit 0.vitest run --project unit: 295 files. 293 passed in the first run; the other 2 readpackages/cli/dist, which was not built yet, and passed (29/29) afterpnpm --filter @objectstack/cli build.typecheck: exit 0.src/default-datasource-plugin.test.ts12/12. TheAppPluginrefusal is unchanged.if ((globalThis as any).__ablation23634 === undefined) return;, viascripts/ablation-replace.mjs):ablation-dist-preflightfound the marker in 12 dist files. The spec pins went 4 failed / 3 passed: the four refusals red, the three controls green. The CLI door went 1 failed / 1 passed: the refusal red, the control green.git diff HEADwas empty and the hash matched HEAD. The rebuild exited 0, and the preflight--absentwas clean in all 232 files. Spec pins 7/7, CLI door 2/2..superRefinefailed the mutated build on the dropped-refinements ledger, sodist/stayed unmutated (the preflight caught it).dist/(the preflightplantedcheck read absent).node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 90 families for the 6 changed paths. Ona085cc9ball 90 exit 0, and--ranreconciled 90 derived / 90 run / 0 NOT-MEASURED, a derived zero with every exit code recorded.check-plugin-teardown-shape --self-testfirst exited 3 on the shallow clone and passed after fetching its pinned fixture commit.check:stack-collection-mapswas red on a multi-linez\n.array(that hiddatasourcesfrom its census. It was fixed ina085cc9bby keepingz.array(DatasourceSchema)on one line.a6f3e6e8: the same 90 families, all exit 0.--ranreconciled 90 / 90 / 0 NOT-MEASURED, a derived zero.check:adr-0087-registration: ✓,registered stack-datasource-host-reserved-name-refused (new here).check:dev-prereqs: exit 0.Acceptance notes
skills/objectstack-data/rules/datasources.md:4-6reads: "Objects route to one via theirdatasourcefield (default:'default'). Most apps need only thedefaultdatasource; declare more to read/write a separate or external database." "Declare more" implies thatdefaultis declared too, so it reads as an invitation. Suggested rewording: "Most apps need only the host'sdefaultdatasource, which the host connects fromOS_DATABASE_URL; never declare a datasource nameddefault(the name is host-reserved and refused). Declare a datasource under its own name only to read/write a separate or external database."app-plugin.ts), the admin door (datasource-admin-service.ts) and this one are synonymous, not shared. The shared text could be exported from spec and reused by the runtime, but that needs apackages/runtimeedit, which is outside this claim. It is reported, not done.Generated by Claude Code