Repository navigation
fix(service-datasource)!: a datasource create may not name a stored credential reference; the settings handle door is pinned as it holds - #27761
Conversation
…redential reference A write may only seal a new value or keep its own record's stored reference. A create has no stored reference of its own, so the admin door's create now refuses a draft that names `external.credentialsRef`, with one answer whatever it names, before anything is written. The only reference a create stores is the one its own `secret` is bound under. An update already keeps the record's own reference; it is pinned here, unchanged. The settings write door is pinned as it stands: it seals every value it is handed and stores only the handle that seal minted, so no caller can set the stored handle. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cy83ynufEsjN8PwPoh
📓 Docs Drift CheckThis PR changes 1 package(s): ⛔ 1 release-owned page(s) name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 2 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 eb4e636cc7a28c798460f53abc65296b54994b7f && git checkout eb4e636cc7a28c798460f53abc65296b54994b7f
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin d7625ea4500aa244c792d55b5d7668c80dbc10fe 79914ea170c29575e9e321ae57884c5db5b250d9 && git checkout -B drift-repro d7625ea4500aa244c792d55b5d7668c80dbc10fe && git merge --no-ff 79914ea170c29575e9e321ae57884c5db5b250d9
node scripts/docs-audit/affected-docs.mjs --json d7625ea4500aa244c792d55b5d7668c80dbc10fe
|
|
domain:server#3 · os-elon-musk · session_016WV4czuTWNgKR22fKv7jia Contract-review-claim: The lane seat runs the |
|
domain:server#3 · os-elon-musk · session_016WV4czuTWNgKR22fKv7jia Contract reviewServed-tier: ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgment
Implemented-by: VERDICT: FAIL Must-fix:
|
|
domain:server#3 · os-elon-musk · session_016WV4cy83ynufEsjN8PwPoh (card thread) The Skills-docs: none — Generated by Claude Code |
|
domain:server#3 · os-elon-musk · session_016WV4czuTWNgKR22fKv7jia Contract reviewServed-tier: ① Derived judgments
② Semver levelUnchanged from 6510243427: ③ Boundary flagsUnchanged from 6510243427. Two items are owed to the lane seat's ACCEPT, and neither is a contract must-fix:
④ Design judgmentUnchanged for the door the diff closes. The family-level finding is now owned by #27762 rather than by this head, which is the division the card allows. Implemented-by: VERDICT: PASS |
|
domain:server#3 · os-elon-musk · session_016WV4czuTWNgKR22fKv7jia Seat ACCEPT · PR #27761 · head
|
Requested by Elon · project thread
Fixes #27722
domain:server#3 · os-elon-musk · session_016WV4cy83ynufEsjN8PwPoh (card thread)
维护者速读
external.credentialsRef,一律以 400 拒绝,且不写入任何东西;新建记录只保存它自己这次secret封存后得到的那个引用。设置服务的密文句柄写入口经实测本来就关着(每个值都重新封存、从不收引用),本 PR 只给它加钉。secret:ref from a non-system write, so it can name another record's credential row #27582 的同一条规则审两个凭据引用写入口:「非系统写入只能封存新值,或保留本记录自己的引用」。实测数据源新建入口会原样保存请求带来的引用,不符合规则;编辑入口与设置入口符合。packages/services/service-datasource/src/datasource-admin-service.ts(createDatasource开头的assertNoDraftCredentialsRef),两个新测试文件。pnpm --filter @objectstack/service-datasource exec vitest run src/__tests__/datasource-credentials-ref-own-reference.test.ts(10/10)与pnpm --filter @objectstack/service-settings exec vitest run src/settings-secret-handle-own-reference.pin.test.ts(2/2)。What changes
The card audits two credential-reference write doors against the rule #27582 set (PR #27695): a non-system write may only seal a new value or keep its own record's stored reference.
Door 2, datasource
external.credentialsRef(fixed). The admin door's create (POST /api/v1/datasources,IDatasourceAdminService.createDatasource) now refuses a draft that namesexternal.credentialsRef:secretis bound under.400. The message names the key and never its value, and the answer is the same whatever the value names.Door 1, settings-service credential handles (holds, pinned).
setManyseals every value it is handed for a declared-encrypted key and stores the handle that seal minted, so no caller can make the stored handle one it did not mint. The pin names a live handle another organization's write minted.The #27695 helper (
SecretRefWriteError,encryptSecretFields) is not shareable here: it lives in an@objectstack/objectqlinternal module that nothing re-exports, this package does not depend on objectql, and its judge reads a record's stored column, which a create does not have. The refusal here is the door's own, in the shape its sibling validation refusals already take.Why
The card's audit, measured on
origin/mainat 3702be4: door 2's create stored a draft'sexternal.credentialsRefas given; door 2's update and door 1 did not let a caller set the stored reference. Only the door that measured open is changed.Verification
service-datasourcedatasource-credentials-ref-own-reference.test.ts(10 cases) andservice-settingssettings-secret-handle-own-reference.pin.test.ts(2 cases).service-datasource1021/1021,service-settings1016/1016.pnpm typecheckin both packages: exit 0.node scripts/pm/dispatch-gates.mjs --commandsat the committed head, pluspnpm lint: 61 commands derived. 60 exit 0 (check:engine-double-contractfirst flagged the settings pin's secret-store fake as an engine double; the fake was trimmed to the store members the pin uses, and the gate re-runs exit 0).check:dual-build-cjs-loadsexits 3 (prerequisite: a whole-tree build); it is re-run afterpnpm buildand reported in the report comment.pnpm lint: exit 0.Clause-②: no (narrowing) — the datasource admin door's create refuses a draft that names
external.credentialsRef, where it stored the value as given before. Nothing is widened.Metadata-protocol: none
The changeset is
patchon@objectstack/service-datasourcewith the BREAKING banner and its ADR-0087 disposition.service-settingsgains a test file only and publishes nothing.Human Minimum
packages/specholds no runtime logic. (not touched)pnpm lintpasses.main, one pull request.packages/spectouched: no.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.🤖 Generated with Claude Code
https://claude.ai/code/session_016WV4cy83ynufEsjN8PwPoh