Repository navigation
fix(service-datasource): an unset env credential is a note after the driver's error, and a failed connect holds no claim on its variable (#28283) - #28325
Conversation
…driver's error, and a failed connect holds no claim on its variable Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5m1ywz2SChxvNGPb5U
📓 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 — 3 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 79ebeac547ffc2b13a203b46f4baa9cbd16b687a && git checkout 79ebeac547ffc2b13a203b46f4baa9cbd16b687a
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin b33946512c9f968432cb8b094961424220da4bc6 d3ceca42a2a5e84a77b3329e5a0ee6e800329d4d && git checkout -B drift-repro b33946512c9f968432cb8b094961424220da4bc6 && git merge --no-ff d3ceca42a2a5e84a77b3329e5a0ee6e800329d4d
node scripts/docs-audit/affected-docs.mjs --json b33946512c9f968432cb8b094961424220da4bc6 |
|
domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo 席位核对ACCEPT · The maintainer's standing authorisation for landing reviewed PRs, verbatim: 「按照 pm-dispatch 规则复核过的都授权」.
Generated by Claude Code |
Requested by Leehom · project thread
Fixes #28283
Clause-②: no — measured: the connect verdict's
reasontext changes shape and an internal owner map releases on failure. No schema, export, type, error code or status moves, nothing is newly refused or accepted, and no consumer outside this package's own pins reads the sentence (git grep "not set on this host"outsideservice-datasource: 0 hits).Metadata-protocol: none
维护者速读
OS_DATASOURCE_NAME_PASSWORD没设、连接又失败时,失败原因改为「驱动自己的错误 + 结尾的(note: …变量没设…)」,不再用破折号把变量说成失败的原因;另外,一次失败的连接会释放它登记的变量,之后另一个推导出同一变量的数据源不会再被误判为冲突。disconnect。datasource-connection-service.ts里 env 凭据槽的两处:原因文本的拼接,和失败路径上释放本次登记。两个都活着的同变量数据源仍被拒绝。回滚即 revert。packages/services/service-datasource/src/datasource-connection-service.ts(claimedVariable的登记与 catch 里的释放、(note: …)那一句);src/__tests__/datasource-env-credential.test.ts(两条新 pin)。pnpm --filter @objectstack/service-datasource exec vitest run --maxWorkers=2 src/__tests__/datasource-env-credential.test.ts,预期 26/26 通过。What changes
Both items are in
DatasourceConnectionService.connect()'s env-credential slot (#27687):DRIVER_ERROR — datasource 'x' is defined in code and reads its credential from OS_DATASOURCE_X_PASSWORD at connect, which is not set on this host. The base already led with the driver's error, so the order's hypothesis that the reason led with the variable did not hold as written. The dash joined the sentence on as the explanation, though, for every cause: an unreachable host, a missing driver module, a TLS failure. It now readsDRIVER_ERROR (note: datasource 'x' is defined in code and reads its credential from OS_DATASOURCE_X_PASSWORD at connect, which is not set on this host). The note stays for a login refusal, so that pin still names the variable to set. I did not take the card's other route, matching the driver's error for "reads as an authentication refusal": that needs a per-driver table of auth codes (pg28P01, mysql1045, mssqlELOGIN…) that would drift silently, and the note is true for every cause.claimedVariablerecords that THIS attempt made the claim, and thefailed-degradedcatch releases it beforehandleFailure, which may throw the fail-fast error. A connect of a name that already owned the variable claims nothing new and releases nothing. I kept the claim before the build, rather than recording it after the build succeeds, so that two overlapping connects of colliding names cannot both pass the check across the build's awaits.patchchangeset for@objectstack/service-datasource. The docs line inexternal-datasources.mdx("its reason names the variable to set") stays true and is not edited.Tests
src/__tests__/datasource-env-credential.test.ts, through the realDatasourceConnectionService:connect ECONNREFUSED 127.0.0.1:1(code: 'ECONNREFUSED'). The reason starts with the driver's error, the rest is exactly(note: … OS_DATASOURCE_WAREHOUSE_PASSWORD …), and the retained connection state carries the same reason.eu-salesfailsfailed-degraded(getaddrinfo ENOTFOUND), theneu_sales, which derives the sameOS_DATASOURCE_EU_SALES_PASSWORD, connects.Red first, green, and one ablation per pin
Tests 2 failed | 24 passed (26). S1:expected ' — datasource \'warehouse\' is define…' to match /^ \(note: …/. S2:expected 'failed-credentials' to be 'connected'.Tests 26 passed (26).scripts/ablation-replace.mjs, restores} — datasource '${name}' is defined. On disk: note-count 0, dash-count 1. Result: only the S1 pin fails (1 failed | 25 passed). Restored: blob == HEAD2753417323b5,git diff HEADempty.if (claimedVariable !== undefined) this.envCredentialOwners.delete(claimedVariable);. On disk: release-count 0. Result: only the S2 pin fails (1 failed | 25 passed). Restored: blob == HEAD,git diff HEADempty.../datasource-connection-service.jsfromsrc/, so nodist/rebuild sits in either leg.Package suite, typecheck, lint
pnpm --filter @objectstack/service-datasource test:Test Files 66 passed (66),Tests 1100 passed (1100), lock VERDICT command-exit 0.pnpm --filter @objectstack/service-datasource typecheck:tsc --noEmit, VERDICT command-exit 0.--listFilesincludes the test file.eslint src --no-inline-configin the package: exit 0.Acceptance notes
statusReason, the saved-datasource Test answer) and the fail-fast boot message. It is pinned only by this package's tests, and only bytoContainon the variable name, which still holds.packages/runtime'sdatasource-env-credential.test.tsreads this package fromdist/and asserts no reason text. No export changes, so per the local-verification scope it is left to CI's Test Core.Verification
Gates from
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackon this diff (60 commands), run on headd3ceca42with each exit code captured before any pipe: 59 exit 0.pnpm check:dual-build-cjs-loadsexits 3, PREREQUISITE NOT MET (a fresh worktree has not built every package'sdist), so it is NOT MEASURED locally and left to CI.check-plugin-teardown-shape.mjs --self-testfirst exited 3 on the shallow clone, and exits 0 after fetching its fixture commit.dispatch-gates --ran: "60 derived famil(ies) accounted for — 59 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3)".Human Minimum
packages/specholds no runtime logic. (packages/specuntouched.)pnpm lintpasses (scoped to the touched package).main, one pull request.packages/spectouched: n/a.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Generated by Claude Code