Repository navigation
fix(cli): os migrate finds the SQL driver on a wasm-sqlite:// database, so the ownership ceremony and os migrate plan run on it - #23671
Conversation
…esolver Claude-Session: https://claude.ai/code/session_01Q9PZ5Pzqcus4woVvTZwWNU Co-authored-by: Claude <noreply@anthropic.com>
…ce, through metadata-core's dialectOfDriver, and refuses an unresolved one before any statement Claude-Session: https://claude.ai/code/session_01Q9PZ5Pzqcus4woVvTZwWNU Co-authored-by: Claude <noreply@anthropic.com>
…emony change as measured The sweep is os migrate plan's, not the ceremony's, and the schema boot never plans SqliteWasmDriver, so the change had no reach there. Claude-Session: https://claude.ai/code/session_01Q9PZ5Pzqcus4woVvTZwWNU Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q9PZ5Pzqcus4woVvTZwWNU Co-authored-by: Claude <noreply@anthropic.com>
…107a7a9) into claude/issue-23648-sqlite-wasm-sql-driver This branch builds on PR #23647's dialectOfDriver, which resolves the wasm driver to sqlite once the schema boot finds it. The branch is merged as it stands, not rewritten. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FLwgbTSmGMrqsXkBDsiwfG
…mDriver SQL_DRIVER_SERVICES gains driver.com.objectstack.driver.sqlite-wasm, the service key a wasm-sqlite:// boot registers (measured). Every os migrate command found no SQL driver on such a database, so the organization-ownership ceremony refused it as driver-unsupported and os migrate plan answered no_sql_driver with exit 0. A non-SQL driver is still not found. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FLwgbTSmGMrqsXkBDsiwfG
… database's dialect
Once the schema boot finds SqliteWasmDriver, os migrate plan reaches the
unmanaged-table sweep, which read config.client as a string only. That
driver's client is a knex class, so every wasm-sqlite:// plan reported the
section unreadable ('unnamed client'). The sweep now resolves the dialect
through metadata-core's dialectOfDriver, dialectName first.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FLwgbTSmGMrqsXkBDsiwfG
… the lookup's controls The integration pin runs os migrate apply, os migrate plan and the organization-ownership ceremony's plan and apply through their real boots on a wasm-sqlite:// database. The unit pin holds the lookup to the measured service key, and its controls: a SQL driver under an unlisted key and a non-SQL driver under any key stay unfound, and the ceremony refuses both arms driver-unsupported on them. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FLwgbTSmGMrqsXkBDsiwfG
…ite database Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FLwgbTSmGMrqsXkBDsiwfG
…river PR #23647 has landed on main (c2bb302, from the same head 107a7a9 this branch merged), so after this merge the branch's diff against main is this card's alone. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FLwgbTSmGMrqsXkBDsiwfG
…river Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FLwgbTSmGMrqsXkBDsiwfG
📓 Docs Drift Check2 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run. What this run could not see
Coarse fallback — 28 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 5a045a4c9a8a2e09eac884330c55ab004171bc9d && git checkout 5a045a4c9a8a2e09eac884330c55ab004171bc9d
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 57994c311f4acc576e1a1eb9ad4162d191d15905 0e446f4bf4cf5de29f557d1bbc330a938b1ef65c && git checkout -B drift-repro 57994c311f4acc576e1a1eb9ad4162d191d15905 && git merge --no-ff 0e446f4bf4cf5de29f557d1bbc330a938b1ef65c
node scripts/docs-audit/affected-docs.mjs --json 57994c311f4acc576e1a1eb9ad4162d191d15905 |
✅ ACCEPT: PR #23671 at
|
Fixes #23648
Clause-②: no
On PR #23647. This card builds on PR #23647 (#23558), whose
dialectOfDriverresolves the wasm driver tosqliteonce it is found. As ruled, this branch first merged that PR's head107a7a923cas one merge commit, without rewriting it. PR #23647 has since landed onmain(c2bb302c8, from that same head). This branch then mergedmaintwice (286eb9ef3, then1ced0f82b), and its head is0e446f4bf. So the file diff againstmainis this card's alone: 5 files. The commit list still shows PR #23647's four commits, becausemainholds them as one squash commit.What changed
packages/cli/src/utils/schema-migrate.ts:SQL_DRIVER_SERVICESlistsdriver.com.objectstack.driver.sqlite-wasm, the key awasm-sqlite://boot was measured to register. It is one more name in a list, not adriver.*pattern. A driver without the schema-migration seam (detectManagedDriftandapplyMigrationEntries) is still not found under any key. A SQL driver under a key the list does not name is still not found either.packages/cli/src/utils/unmanaged-tables.ts:os migrate plan's unmanaged-table sweep resolves the dialect throughdialectOfDriver(dialectNamefirst), not fromconfig.clientas a string only. This is folded in because the change above makes it reachable. With only the list fix, everywasm-sqlite://plan reported the sectionunreadable("the connected dialect (unnamed client) is not one this sweep enumerates tables on"), since this driver's client is a knex client class. PR fix(cli): the organization-ownership ceremony reads its dialect once, through metadata-core's shared resolver, and refuses an unresolved one before any statement #23647's Acceptance notes recorded this reader as having "no reach today". This PR is what gives it reach.@objectstack/clipatch). No new export.Premise check
Read on
origin/main7cb33cfefwith PR #23647 merged in (60ae7a6a8).bootSchemaStackonwasm-sqlite://FILEand listed everydriver.*service. There is exactly one:driver.com.objectstack.driver.sqlite-wasm, an_SqliteWasmDriverwithdialectName: 'sqlite'and a class-valuedconfig.client.stack.driverwasnullanddbLabelwasunknown.DefaultDatasourcePluginregisters the default driver asdriver.followed by the driver'sname.SQL_DRIVER_SERVICESis read byfindSqlDriverVia, whichfindSqlDriverandfindSqlDriverForKernelcall.findSqlDriveris called bybootSchemaStack, the boot behind 19os migrate/os storage/os secretcommands.findSqlDriverForKernelis called byos serve's boot-time migration gate when an artifact is pinned withOS_ARTIFACT_URL.DeferSchemaDdlPlugin.inititerates the list too. It also arms everydriver.*service, so the wasm driver was already held to a dry run.findTelemetryDriveruses its own list (driver.telemetry) and is unchanged.os migrate planmeets the same lookup: it was measured (below) and is folded in.detectManagedDrift,applyMigrationEntries,setDeferredDdlandexecuteare functions, andrawis undefined.executeis the seamresolvePlannedDriverExectakes.SqliteWasmDriverextendsSqlDriver.wasm-sqlite://database. The apply step is handeddialect: 'sqlite'(unit pin). The plan's first statement is the SQLite catalog read.Before and after, at the doors
Fixture: a project with a compiled artifact that declares no object, plus
OS_AUTH_SECRET. The database was created onwasm-sqlite://byos migrate apply, and each door ran on its own copy. "Before" is the same copy run withschema-migrate.tsandunmanaged-tables.tsrestored from60ae7a6a8. The restore was trap-guarded, and afterwards each blob equalled HEAD andgit diff HEADwas empty. "After" was measured at030a6d826(the list fix) for the ceremony's--applyand foros migrate applyon a fresh file, and at525ecbe67(with the sweep fix) for the rest. Every command was run throughbin/run-dev.jswith--json.os migrate organization-ownership(plan)plan_refused/driver-unsupportedclient: null)… --apply --backup-taken --plan-fileapply_refused/driver-unsupporteddone, theadr-0131-organization-ownershipledger row persisted in the fileos migrate plan{"error":"no_sql_driver","changes":[]}unmanagedTables.status: read, 71 physical tables (the list fix alone:unreadable, "unnamed client")os migrate apply(fresh file){"error":"no_sql_driver"}, nothing createdos migrate multi-value-columnsno_sql_drivertargets: [](no conversion applies on SQLite)os migrate unmapped-columns --object sys_userno_sql_drivercolumns: []duplicates,account-issuer,meta --stored,audit-metadata-bodies,comment-reactions,security-catalog-overlays,os storage orphansdatabase: unknowndatabasenames the filerecorded-by,resume,os secret rewrap,os secret orphansvalue-shapes,files-to-references,summary-nullsfiles-to-references' driver read (planMediaColumnMove) was not reached. NOT MEASURED.os servewithOS_ARTIFACT_URL=file://…declaringstorage.notNullon a nullable columnThe
os serverow is the one behaviour change outsideos migrate. Its gate's own comment says "no SQL driver" is that gate's everything-is-fine answer. On awasm-sqlite://database the gate now runs as it does on every other SQL database. It was measured on its own fixture, seeded throughfile:and served throughwasm-sqlite://, ata4b58bf18. The before side had the new key removed throughscripts/ablation-replace.mjs, and afterwards the blob equalled HEAD.Tests
packages/cli/src/utils/schema-migrate.sql-driver-lookup.test.ts(new,unittier, 12 tests):driver.com.example.driver.sql-compatible,driver.telemetry,driver.default) stays unfound.bootSchemaStackreplaced by a stack whose driver is the real lookup's answer: both ceremony arms refusedriver-unsupportedon three refused shapes, with exit 1, no statement run, no plan file and the apply step never called. Both arms proceed on the wasm driver, and the apply step is handeddialect: 'sqlite'.packages/cli/src/commands/migrate/sqlite-wasm.integration.test.ts(new,integrationtier, 3 tests): the real boots on onewasm-sqlite://file, through each command'srun().os migrate applycreates the schema in the file (sys_migrationamong it, read back past the driver).os migrate planplans it, with the unmanaged-table sweepreadand its count equal to the file's tables.done, and the ledger row in the file.Runs, all under the shared verify lock:
0e446f4bf.unitproject, by path: the new lookup file,unmanaged-tables.test.ts, and the two published-subpath pins. 4 files, 82 tests passed.integrationproject, by path: the new file,unmanaged-tables,organization-ownership-plan,schema-migrate, and the fourplan.*integration suites. 8 files, 33 tests passed. This layer was run locally because the diff adds an integration-tier file and changes the sweep those suites read.1eb7378cd(the merge of286eb9ef3). The cli code is the same as the final head; the later merge brought only.claude/**andscripts/pm/**.unitlayer: 290 of 292 files and 4325 tests passed. The 2 failed files (test/published-subpath-console.pin.test.ts,test/published-subpath-hook-body.pin.test.ts) refused becausepackages/cliwas not built ("./dist/index.js is absent"). That is a missing prerequisite, not a measurement. Both passed on the final head once the cli was built (above).pnpm --filter @objectstack/cli typecheck(tsc --noEmitandcheck:test-typecheck): exit 0.Ablation
These are one-off proofs, run through
scripts/ablation-replace.mjsin WRAP mode with anEXIT INT TERMrestore trap, ata4b58bf18. Nodist/is involved: the subjects are clisrcfiles, imported relatively, and metadata-core is aliased tosrcin the cli vitest config.SQL_DRIVER_SERVICES. On disk, anchor 1 went to 0 and blobb1fcdf46db73becamea46e1ec56ca9.no_sql_driver, and the ceremony's exit 1).git diff HEADis empty.config.clientas a string only. On disk, anchor 1 went to 0 and the marker went to 1. Blobc647aec174bcbecamea2097e2e9892.os migrate plancase went red (unreadable).git diff HEADis empty.Gates
Local, on
0e446f4bf:node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 64 commands from merge base1ced0f82b, over the 5 changed paths. All 64 were run in sequence, each exit code captured before any pipe: 64 of 64 exit 0.--ran: "64 derived, 64 run, 0 NOT-MEASURED, 0 UNRUN", exit 0.check:dual-build-cjs-loads,check:i18n,check:i18n-coverageandcheck:i18n-walk-parityexited 3 (PREREQUISITE NOT MET) on the first pass, at1eb7378cd. So didcheck:type-check-debt, whose closure build queued past its lock budget. All five exited 0 at0e446f4bf, after a turbo build of the closures they name.check:type-check-coverageandcheck:type-check-debt: exit 0.eslint --no-inline-config packages/cliexited 0 with no output, and a JSON-format run over the four changed.tsfiles reported 0 errors and 0 warnings in each. The repo-widepnpm lintis CI's.Acceptance notes
os servekeeps a second list of driver service names (describeRegisteredDriverinserve.ts), and it also omitssqlite-wasm. Serve reads it only to label the banner when it resolved no driver label itself. It was not measured and is not changed here. Carrier: none.os migrate duplicatespassesString(config.client)as itsclient. For this driver that string is the client class's source text. It is read only to pick MySQL backtick quoting, so the SQLite quoting stays right. It is not echoed into the report: measured, the report on the wasm database matched the one before, apart from the database name, and no output carried the class text. Carrier: none.organization-ownership.dialect.test.ts(PR fix(cli): the organization-ownership ceremony reads its dialect once, through metadata-core's shared resolver, and refuses an unresolved one before any statement #23647's file, now onmain) says the command's boot "does not hand that driver over today". After this PR it does. The file is not edited here.Generated by Claude Code