Repository navigation
fix(cli): the memory:// / mingo:// OS_DATABASE_URL refusal names the scheme, never the URL - #23840
Conversation
…e URL
inferDriverTypeFromUrl's retired in-memory engine arm built its refusal
from the whole OS_DATABASE_URL, so a user, password or token in a
memory:// or mingo:// URL was printed when `os serve` exited. The arm now
names the scheme in the runtime host's words ("An OS_DATABASE_URL with the
"memory://" scheme"), and carries the scheme, not the URL, as driverType.
Pins: a credentialed memory:// and mingo:// URL is refused naming the
scheme and the SQLite replacements and none of the placeholders; the same
tail under every other scheme classifies as before; both hosts refuse it
in the same words.
Claude-Session: https://claude.ai/code/session_018t6a5rvqPRvEDMCVVW9kYT
Co-authored-by: Claude <noreply@anthropic.com>
…i-memory-url-redact
📓 Docs Drift Check1 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 5adeeb3350473a9bc81ebc9a4fe14acf3127d7d0 && git checkout 5adeeb3350473a9bc81ebc9a4fe14acf3127d7d0
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 0cfd0c49bd2635da048fae96b35a38448141fa9d a1a28595ef615c20cdcedcc5adcd91db538586b2 && git checkout -B drift-repro 0cfd0c49bd2635da048fae96b35a38448141fa9d && git merge --no-ff a1a28595ef615c20cdcedcc5adcd91db538586b2
node scripts/docs-audit/affected-docs.mjs --json 0cfd0c49bd2635da048fae96b35a38448141fa9d |
席位核对ACCEPT · #23792 ·
Landing: once every check on the head is green or an expected skip, this seat flips the PR ready and arms auto-merge through the relay, then follows it to Generated by Claude Code |
Fixes #23792
Clause-②: no
What changes
inferDriverTypeFromUrlinpackages/cli/src/utils/storage-driver.tsrefuses amemory://ormingo://OS_DATABASE_URL(the retired in-memory engine). Its refusal was built from the whole URL,OS_DATABASE_URL "URL", andos serveprints that message as it exits 1. Both schemes accept anything after the//, so auser:password@and an?authToken=were printed to the console.The arm now names the scheme only, in the runtime host's words:
An OS_DATABASE_URL with the "memory://" scheme selects the in-memory (mingo) engine, .... The rest of the sentence (the SQLite replacements) comes from the sharedretiredMemoryEngineMessage, unchanged. TheUnsupportedDriverErrorit throws now carries the scheme asdriverType, not the URL, as the unrecognised-scheme arm below it already does.Landing: the
memory/mingoarm only, as the claim's file surface names it. No other arm, theOS_DATABASE_DRIVER/--database-driverarm,packages/runtimeand the scheme parsing are untouched.Why the words are mirrored, not imported
The runtime phrase is built inside
refuseRetiredMemoryEngineinpackages/runtime/src/standalone-stack.ts, and it is module-local:@objectstack/runtimeexportsretiredMemoryEngineMessage(the shared tail, already used here) but not the subject. The dispatch rules out a new export frompackages/runtimeon this card, so the CLI arm writes the subject out. A parity row indriver-vocabulary-parity.test.tsholds the two hosts' refusals equal for the same credentialed URL (the CLI's is the runtime's minus its[StandaloneStack]tag), so the copy cannot drift silently.Reproduction at the public door
Built CLI, run from
examples/app-todo, the URL carrying placeholder credentials only:memory://mingo://1ecb08a1ccPLACEHOLDER-USER/-SECRET/-TOKENprinted 1 / 1 / 1 time3ddd364ad)127.0.0.1:63990127.0.0.1:63990✗ OS_DATABASE_URL "memory://PLACEHOLDER-USER:PLACEHOLDER-SECRET@127.0.0.1:6399/0?authToken=PLACEHOLDER-TOKEN" selects the in-memory (mingo) engine, ...✗ An OS_DATABASE_URL with the "memory://" scheme selects the in-memory (mingo) engine, ...(and"mingo://"for the other scheme).Pins
packages/cli/src/utils/storage-driver.test.ts:memory://and amingo://URL carrying a placeholder user, password and token: the refusal is anUnsupportedDriverErrorwithrecognized: falseanddriverTypeequal to the scheme; its message names the scheme,--freshand:memory:; neither the message nordriverTypecontains any of the three placeholders (nor the host).postgres://,postgresql://,pg://,mysql://,mysql2://,mongodb://,mongodb+srv://,libsql://andwasm-sqlite://classifies as before. The existing "maps each recognized URL scheme" and unrecognised-scheme rows are unchanged and green.memory://ignored-host,MINGO://x). It now asserts the scheme ("memory://","MINGO://") anddriverType.packages/cli/src/utils/driver-vocabulary-parity.test.ts: for a credentialedmemory://andmingo://URL, both hosts refuse, name the scheme, print none of the placeholders, and the CLI's message equals the runtime's minus[StandaloneStack].Tests (local)
pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2ona1a28595e:Test Files 297 passed (297),Tests 4447 passed (4447), lockVERDICT command-exit 0. It ran longer than one foreground call on this shared box (13m53s under the lock), so it was started detached under the lock while the derived gates ran in the foreground; its result was read from the lock'sVERDICTline after it exited.--project unit(both are unit-tier):Test Files 2 passed (2),Tests 162 passed (162).pnpm --filter @objectstack/cli typecheckona1a28595e: exit 0;check:test-typecheck: OK(the test layer compiles undertsconfig.test.json).integrationtier: declared to CI. The diff touches no integration-tier file and no spawn entry.Ablation (one-time, nothing kept)
The tests import
./storage-driver.jsrelatively, so they read the source and no rebuild is involved. Each leg throughnode scripts/ablation-replace.mjs(anchor hit 1 to 0, blob changed, then restored to the HEAD blob74287da383withgit diff HEADempty):OS_DATABASE_URL "${u}": 6 failed / 156 passed. Red: the two placeholder pins, the two parity rows, and thememory://ignored-host/MINGO://xscheme rows, each on the "names the scheme" assertion.... "${retiredScheme}" scheme (${u})), so the placeholder assertions are the first to fail: 4 failed / 158 passed, all four onnot to contain 'PLACEHOLDER-USER'(both placeholder pins, both parity rows).driverTypeback to the URL (u): 4 failed / 158 passed, onexpected 'memory://PLACEHOLDER-USER:...' to be 'memory://'and the two scheme rows.Gates
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackona1a28595e(merge base43567a8fc, 4 paths, 121 changed lines): 64 commands. Reconciled with--ran:64 derived famil(ies) accounted for — 62 run, 2 NOT-MEASURED.check:dual-build-cjs-loadsandcheck:i18n-coverage, both exit 3PREREQUISITE NOT MET(packages outside the CLI's build closure have nodist/here). CI'sLint & Repo Gatesruns both.pnpm exec eslint --no-inline-configover the three edited.tsfiles: exit 0. The repo-wide lint is CI'sLint & Repo Gates.Acceptance notes
packages/cli/src(tests excluded) for the URL interpolated into athrow,console.*,logger.*orprint*line finds only this arm. The startup banner, the migration line andos start'sDatabaseline already pass the URL throughredactConnectionUrl.OS_DATABASE_DRIVER/--database-driverarm (it prints a driver name, not a URL),packages/runtime, and the scheme parsing; runtime(standalone host): an upper-caseFILE:database URL is classified as SQLite but its prefix is not stripped, soOS_DATABASE_URL=FILE:./app.dbcreates a directory literally namedFILE:.and a database inside it #23794 and cli(storage):OS_DATABASE_URL=file://NAMEopens//NAMEat the filesystem root on the CLI host, where the runtime host opens./NAME(thefile:twin of thesqlite://alias #23633 fixed) #23796 remain open.retiredMemoryEngineMessageinpackages/runtime/src/resolve-project-database.tsstill givesThe database URL "memory://"as an example subject. The runtime host now saysA database URL with the "memory://" scheme. Comment only; no behaviour reads it.The Tests section's account of the detached unit run was corrected by the
domain:cliseat 2 PM (sessionsession_018t6a5rvqPRvEDMCVVW9kYT) at review, from the dev report's deviation 1.