Repository navigation
[security] Datasource read redaction misses a still-writable credential key under some accepted spellings of its driver — detail withheld pending maintainer #21955
Description
Activity
- addedbugSomething isn't workingSomething isn't working
on Oct 6, 2026 objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsPath: an API a customer can call — external data; secrets can be neither written in nor read out | integration-system.datasource-credential-refusal-matrix | P2
Triage: first grade —
bug·security·priority:p2·domain:spec·area:access·pm:queue(findingremoved). The read-side redaction resolves the driver the way its sibling helper does, in lockstep with every readerTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-06T05:54Z. ⛔ Not a claim, ⛔ not a dispatch. Classes and positions only, and the withheld detail stays withheld.Triage: lands in
packages/spec/src/data/datasource-credential-redaction.ts(the per-driver half ofredactableConfigKeys) ⇒domain:spec; rationale: the published write-only contract (drivers.mdx, "Secret-shaped keys with no binder slot") is broken on the read path for some accepted driver spellings.- Why p2: a write-only credential can be served back, which is the class of a data leak. Every read door involved requires the admin capability, and reach through a public door is not yet measured. So it is not p1, and not lower than p2.
- Direction:
- The redaction's driver lookup resolves identity the same way its sibling helper does, so every spelling the write door accepts as a driver is stripped as that driver.
- Lockstep:
service-datasource'srestoreRedactedConfigand the credential migration read the same list, and they move with it in the same PR. - The second symptom (a crafted driver id makes the read throw) gets a defined answer, either withholding or a clean refusal. It never serves, and never throws an unhandled error.
- Measure first: reach on the datasource admin read, then the fix.
- Pins:
- each accepted spelling of the driver is redacted on read;
- the save round-trip still restores the stored value, so redaction never turns a save into deletion;
- the crafted-id case answers as defined.
- Withheld detail goes to the claiming seat on the maintainer's word, as for security(forms): a public-form setting at one metadata layer can re-open intake that another layer withdrew — 17.7 regression, detail withheld pending maintainer #21835, security(sharing): share-link password handling falls short of the platform's credential rules (response shape, hashing strength, transport) — detail withheld pending maintainer #21839, security(datasource): credential-shaped values in some datasource configurations are stored and served without the platform's secret handling — detail withheld pending maintainer #21840, security(data): credential-class field values reach record-change consumers (event payloads and the records downstream features keep from them) unmasked — detail withheld pending maintainer #21830, security(auth): implicit account linking on social / OIDC sign-in is broader than the platform's account-ownership rules allow — detail withheld pending maintainer #21846 and security(search): a field-narrowed search still matches through the name field's pinyin companion #21880.
Generated by Claude Code
- addedarea:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsPermissions that actually hold — RLS/FLS, sharing model, write-path guardspriority:p2Medium: important, M3Medium: important, M3and removed
on Oct 6, 2026 objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsClaim: PM loop round 1 (this card, per triage's first grade
6010295609) · 2026-10-06T05:58Z
Session:session_01T9u38rswFp5Rw8DswRUReJ
Account:os-project-manager(the seat's linked user asGET /useranswers it; the card's assignee from this act)
Branch:claude/issue-21955-redaction-driver-identity
Worktree:objectstack-issue-21955
Domain:domain:spec
Seat:domain:spec#1(seat post #6017)
File surface (atorigin/maina3bd157730; stop on breach and explain in the report). Public terms only. The withheld detail stays withheld: neither this claim nor the dev's records restate it.-
Measure reach first on the datasource admin read: the item read and the list read of a datasource whose driver is written in an accepted spelling. Record whether the still-writable credential key is served back, then fix.
-
packages/spec/src/data/datasource-credential-redaction.ts: the per-driver half ofredactableConfigKeysresolves the driver's identity the same way its sibling helper does. So every spelling the write door accepts as a driver is stripped as that driver.- The crafted-driver-id symptom gets a defined answer: withheld or cleanly refused, never served, never an unhandled throw.
- One fix at one line where the measurement allows it.
- ⛔ No second identity resolver.
-
Its tests, in
packages/spec/src/data/datasource-credential-redaction.test.ts:- each accepted spelling is redacted;
- the crafted id answers as defined;
- a control: a canonical spelling is unchanged.
Prove the pin red with the fix reverted, then restore.
-
Lockstep readers in
domain:services:service-datasource'srestoreRedactedConfig(datasource-config-redaction.ts) and the credential migration (datasource-credential-migration.ts). Both callredactableConfigKeys, so the spec fix reaches them without a source change.- The PR may add pins in
service-datasource'ssrc/__tests__/datasource-config-redaction.test.ts,datasource-credential-migration.test.tsanddatasource-admin-service.test.ts. The save round-trip still restores the stored value, so redaction never turns a save into deletion, and the migration reads the same list. - Declared on [PM seat] domain:services — 🟢 zhuangjianguo · session_013j5gkUCpqQiti4GgPqqmnt #6021 in this act.
- A
service-datasourcesource line moves only if the measurement shows a reader does not reach the fix. If so: stop, report, and the seat revises this claim first.
- The PR may add pins in
-
Changeset:
@objectstack/specpatch(a redaction fix), and@objectstack/service-datasourcepatchonly if a source line moves. Measured, not assumed. -
No new id: no new test title, test string or runtime string carries a tracker id.
-
⛔ No other
domain:servicessource, no objectui file, nocontent/docs/releases/.
Container & model:M,mode:subagent,model: opus. The at-tier contract review follows delivery (path legdata/datasource-credential-redaction.ts; security family).
Clause-②: no (expected: a read-side redaction fix narrows what is served, not what the spec accepts; the dev states the measured answer)
Thread-read: 6010295609
Serial constraints cleared: none of the 4 open PRs touchesdata/datasource-credential-redaction.tsorservice-datasource's redaction / migration files (scan at this stamp).
-
objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 21955,
"status": "done",
"branch": "claude/issue-21955-redaction-driver-identity",
"pr": "#21963",
"session": "session_01T9u38rswFp5Rw8DswRUReJ",
"premise_still_valid": true,
"summary": "The per-driver half of redactableConfigKeys indexed its still-writable table by the raw driver value, while the sibling helper passthroughSecretPaths resolves identity through resolveDriverId. The fix replaces that one lookup line with the sibling's two-line shape; there is no second resolver. Reach was measured first at BASE 76fec88 on a unit harness of DatasourceAdminService. Every accepted spelling other than the canonical one was accepted by the write door and judged against the builtin contract, and then served the still-writable credential key on the admin item read (getDatasource) and on the metadata redactor, with redactedConfigKeys empty. The admin list read serves no config by contract, so it has no exposure. A crafted driver id was accepted on create, and then made getDatasource, the metadata redactor, restoreRedactedConfig and planCredentialMigration throw an unhandled TypeError. After the fix every accepted spelling is withheld and named, and a crafted id answers as a driver with no shipped contract: canonical credential spellings withheld, no throw. No service-datasource source line moves: every reader reaches the fix through the spec export. Changeset: @objectstack/spec patch only.",
"tests": "All at HEAD cbea114. (1) Spec: pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2 gave Test Files 619 passed (619), Tests 18476 passed | 1 todo. (2) service-datasource: pnpm --filter @objectstack/service-datasource exec vitest run --maxWorkers=2 gave Test Files 41 passed (41), Tests 748 passed (748). (3) metadata-protocol protocol.metadata-redaction.test.ts plus stored-metadata-body-family.pin.test.ts gave Tests 56 passed (56). (4) Typecheck: service-datasource and spec typecheck (including check:test-typecheck) both exit 0, and tsc --listFiles shows both edited service-datasource test files are in the program. (5) Spec-pin ablation: fix committed first, reverted with scripts/ablation-replace.mjs (anchor 1 to 0, blob b543590328ef to 2398f4fb2c7c), no build leg because the subject is imported relatively from src. Predicted 3 red; observed Tests 3 failed | 41 passed (44); premise and control stayed green. Restored: blob equals HEAD and git diff HEAD is empty. (6) service-datasource ablation, which resolves spec through dist: mutate leg rebuilt spec, and ablation-dist-preflight found the marker in 8 built files. Predicted 5 red; observed Tests 5 failed | 61 passed (66). Restore leg rebuilt spec; preflight --absent reported the marker absent from all 228 built files and the tree clean; then Tests 66 passed (66). (7) Lint, a proven narrowing: 4 touched .ts files, each resolved by eslint --print-config; eslint --no-inline-config --format json linted 4 files with 0 errors and 0 warnings; eslint.config.mjs has no type-aware linting, so untouched files cannot move. The repo-wide pnpm lint is declared to CI. (8) Gates: 87 derived, 86 exit 0, 1 NOT MEASURED, 0 unrun. CI on the PR is in_progress at report time.",
"mcp_calls": "0 — no MCP GitHub tool was called",
"api_writes": "3 — all through the fleet-write relay (each one POST /repos/objectstack-ai/objectstack/dispatches executed by the board workflow): (1) pr_create = POST /repos/objectstack-ai/objectstack/pulls (draft, PR 21963, body read back byte-identical); (2) label-write assign = POST /repos//issues/21963/assignees (os-project-manager, read back matches); (3) this os-dev-report = POST /repos//issues/21955/comments. Plus 4 git pushes (not REST). Reads used gh api GET only.",
"open_questions": [
{
"question": "The card body's own Dedupe paragraph (its MCP search query) spells terms the security-family disclosure rule withholds. Should it be edited?",
"options": [
"A: the filing seat edits that one query line to public terms",
"B: leave the card body as filed"
],
"recommendation": "A, because every other surface of this card, the PR and this report keep to the public terms, and that line is the one place the detail is restated. The edit belongs to the filing seat, not to this dev."
}
],
"out_of_scope_findings": [
"carrier: the at-tier contract review of PR 21963 · noted, not filed — STILL_WRITABLE_CREDENTIAL_KEYS and PASSTHROUGH_SECRET_PATHS are string-keyed records. Typing them by the builtin id union would make a raw-string index a tsc error and close this defect class at compile time. Not done, to keep the fix to the sibling's shape; recorded in the PR's Acceptance notes."
],
"gates": {
"node scripts/check-adr-0087-registration.mjs --base origin/main": 0,
"node scripts/check-adr-0087-registration.mjs --self-test": 0,
"node scripts/check-changeset-no-major.mjs --base origin/main": 0,
"node scripts/check-changeset-no-major.mjs --self-test": 0,
"node scripts/check-empty-changeset.mjs --base origin/main": 0,
"pnpm --filter @objectstack/spec run check:api-surface": 0,
"pnpm --filter @objectstack/spec run check:authorable-surface": 0,
"pnpm --filter @objectstack/spec run check:docs": 0,
"pnpm --filter @objectstack/spec run check:export-origins": 0,
"pnpm check:nul-bytes": 0,
"pnpm check:doc-authoring": 0,
"pnpm check:test-source-alias": 0,
"pnpm check:cross-package-test-inputs": 0,
"pnpm check:type-check-coverage": 0,
"pnpm check:type-check-debt": 0,
"pnpm check:dual-build-cjs-loads": "3 — NOT MEASURED: PREREQUISITE NOT MET (reads every package's dist; this worktree built only the closure it needed); declared to CI",
"the other 71 derived commands": "0 each (full list with exit codes in the dev's ran.list; --ran reconciliation: 87 derived, 86 run, 1 NOT-MEASURED derived from recorded exit 3, 0 UNRUN)"
},
"deviations": [
"Lockstep pins live in datasource-config-redaction.test.ts and datasource-credential-migration.test.ts; datasource-admin-service.test.ts (a may in the claim) is untouched, because the admin item read and the save round-trip are pinned through DatasourceAdminService in the first file.",
"Added a second ablation on the service-datasource pins (dist-resolved, with build and preflight legs), beyond the spec-pin ablation the dispatch required.",
"Commit trailers use the AGENTS.md model-free pair (Claude-Session + Co-authored-by: Claude), not the harness reminder's model-named Co-Authored-By line, per os-dev's precedence rule.",
"Gate batch 73-87 outran the tool's foreground window and the harness moved it to the background; the dev waited for it in-turn with tail --pid on the recorded PID, then read the recorded exit codes.",
"origin/main re-fetched before pr_create (80f9f7e). The 3 commits since BASE touch none of these files, so there was no merge."
],
"files_changed": [
".changeset/21955-spec-redaction-driver-identity.md",
"packages/services/service-datasource/src/tests/datasource-config-redaction.test.ts",
"packages/services/service-datasource/src/tests/datasource-credential-migration.test.ts",
"packages/spec/src/data/datasource-credential-redaction.test.ts",
"packages/spec/src/data/datasource-credential-redaction.ts"
],
"line_budget": "5 files changed, 236 insertions(+), 3 deletions(-)"
}
Generated by Claude Code
objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsContract review
Served-tier:
CONTRACT_REVIEW_TIER
Head-sha:cbea11408e36bb46b64f71d04cd367a442ef4777
Local-runs: noneInputs: card #21955 (body, triage
6010295609, claim6010337650, os-dev report6011189578), PR #21963 (body, file list, net diff against merge-base76fec88b16), and the check-runs on the head. Security family, public terms only: this record names no driver spelling, no key and no line.① Derived judgments
- The fix is the sibling's shape, and there is no second resolver. The per-driver half of
redactableConfigKeysnow readsresolveDriverId(driver)and indexesSTILL_WRITABLE_CREDENTIAL_KEYSby the resolved id, or takes an empty list when nothing resolves: the two-line shapepassthroughSecretPathsalready uses. Right. After the change every table index in the file goes throughresolveDriverId(passthroughSecretPaths,refusedPassthroughSecretPaths,redactableConfigKeys), and a repo-wide scan of non-test source finds no other raw driver index. - Accept-set alignment with the write door.
getDriverConfigSchema, and sovalidateDriverConfig(the write door's contract judgment), resolves through the sameresolveDriverId, whose domain is the alias table folded by trim and lower-case and matched by own property. So "every spelling the write door judges as a builtin" and "every spelling the read path redacts as that builtin" are now one function. The alias table carries each canonical id as a key of its own row, so a folded canonical spelling is covered too, by the fix and by the pins. Right. - The crafted-id answer.
resolveDriverIdis own-property guarded, so a crafted id resolves to nothing, andredactableConfigKeysthen answers the canonical credential spellings plus the former aliases: the posture this module already documents for a driver with no shipped contract, and the posture the write door already takes when it accepts such a row as an unknown plugin driver. Sound for every reader:getDatasourceand the built-in metadata redactor both callredactDatasourceConfig(storedDriver, config)and now serve without a throw;restoreRedactedConfigderives its restore set from that same call, so an untouched Save keeps the stored material;planCredentialMigrationreachesredactableConfigKeysthroughunbindableCredentialKeyswith no throw, and becausevalidateDriverConfig(...).knownis false a row holding credential-shaped residue takes the existing "no shipped contract" refusal while an empty row plansnone. Withheld, never served, never an unhandled throw, inside triage's "withholding or a clean refusal". Right. - Lockstep readers reach the fix with no source change.
datasource-config-redaction.tsimportsredactDatasourceConfigfrom@objectstack/spec/dataand re-exportsredactableConfigKeysfrom there;datasource-admin-service.tscallsredactDatasourceConfig(rec.driver, ...)on the item read andrestoreRedactedConfig(existing.driver, ...)on update;datasource-credential-migration.tsimportsredactableConfigKeysfrom@objectstack/spec/data;kernel/metadata-type-redaction.tscallsredactDatasourceConfig(item.driver, ...). Each passes the stored driver value raw, so identity is resolved once, in spec. Right, and noservice-datasourcesource line was needed. - Redaction never turns a save into a deletion.
restoreRedactedConfiggrafts every path inredactedPathsback wherever the patch still matches the served projection. Under an accepted spelling the still-writable key is now in that set, the patch lacks it and the served config lacks it, so the stored value is grafted. Pinned at the service door under every derived spelling. Right. - Measurement. The reach claim matches the code at the base: the item read handed the raw spelling to a table keyed by canonical id, so a non-canonical accepted spelling missed its row and the key was served with
redactedConfigKeysempty; the list read returnsDatasourceSummary, which has noconfigmember, so it carries no exposure. The ablation legs read right from the pin bodies: with the one line reverted, the spec block's byte-equal, withheld-key and crafted-id pins go red while its premise and control stay green (3 red of 5), and the service block's item-read, save-round-trip and crafted-id pins plus the planner's two pins go red (5 red); all are green on the fix. Not re-run here. - Public surface. No export added, removed or retyped, and no schema file touched;
check:api-surface,check:authorable-surfaceandcheck:export-originsexit 0 per the dev, andLint & Repo Gatesplus everyType Checkjob are green on the head. - Security family, public terms. Checked mechanically: no added diff line, no test title, no test string, no code comment, the changeset and the PR body carry either withheld term, and the crafted-id population in the pins is derived at run time rather than spelled. The PR's added text restates nothing beyond the card's public section and triage. Holds.
- No new id. No added test title, test string or runtime string carries a tracker id; the code comments and the changeset filename do, which is permitted. Holds.
- Check-runs on the head. 32 completed with
success;Console Pin Gate,Build DocsandPacked-tarball smoke (opt-in)skipped by path filter or opt-in; none failed and none died of runner loss. The dev's one NOT-MEASURED gate (check:dual-build-cjs-loads) was declared to CI, and CI is green throughout.
② Semver level
- Changeset
.changeset/21955-spec-redaction-driver-identity.md:@objectstack/specpatch, a bug fix in a released package, the right level. The diff narrows what the read path serves under accepted spellings and turns a throw into a defined answer; it adds, removes and retypes nothing exported. @objectstack/service-datasourcemoves two test files only, publishes nothing, and correctly carries no changeset (Check Changesetgreen on the head).- The PR's Clause-② declaration is
no, with no arm, and that holds: no schema file changes,DatasourceSchemaaccepts exactly what it accepted before, and the change is read-side only. The changeset carries the same declaration.
③ Boundary flags
- Dev open question, the card body's Dedupe search-query line. Answer: A. The card's own rule is that the withheld detail is never restated on a public surface, and a card body is one; the "Dedupe words" line beside it already shows the public-terms form, so the edit is one line and costs no dedupe reach. The act is the filing seat's (
domain:devxseat 2), prompted by the dispatching seat; it is not this PR's, and this record does not restate the line. The verdict on this PR does not turn on it. - Dev out-of-scope note, typing
STILL_WRITABLE_CREDENTIAL_KEYSandPASSTHROUGH_SECRET_PATHSby the builtin id union. An observation for a later card, not a defect this PR introduces: both tables were string-keyed before this PR, and after it both index sites take a resolved id, so a union-typed table would be a compile-time hardening with no behaviour change. Carried here for the spec seat to file or drop. - Dev deviations, each accepted:
datasource-admin-service.test.tsuntouched (a "may" in the claim) because the item read and the save round-trip are already pinned throughDatasourceAdminServiceindatasource-config-redaction.test.ts; a second, dist-resolved ablation on the service pins beyond what the claim required; model-free commit trailers as AGENTS.md prescribes;origin/mainre-fetched with no overlapping file, so no merge. - File surface: the five files are exactly the claim's surface: the one spec source file, its test, the two declared
service-datasourcetest files and the changeset. No otherdomain:servicessource, no objectui file, nocontent/docs/releases/. - Nothing escalated.
Implemented-by:
claude/issue-21955-redaction-driver-identity
Reviewed-by:session_01T9u38rswFp5Rw8DswRUReJVERDICT: PASS
- The fix is the sibling's shape, and there is no second resolver. The per-driver half of
objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsACCEPT — PR #21963 at
cbea11408e(#21955: the datasource read redaction resolves a driver's identity the way its sibling helper does)domain:specseat 1 ·os-project-manager· sessionsession_01T9u38rswFp5Rw8DswRUReJ· 2026-10-06T07:52Z. This is the review of record for the report6011189578, read with the claim6010337650and triage's grade6010295609. Public terms only: the withheld detail stays withheld, and this record restates none of it.The at-tier contract review is owed on the path leg (
packages/spec/src/data/datasource-credential-redaction.ts) and as a security-family review. Its record is PASS6011847094on this head.Checklist (read on GitHub, not from the report):
-
Form: draft, base
main, first lineFixes #21955.Clause-②: nostands in the body and the changeset. -
Scope: 5 files, +236 / −3, inside the claim:
- the one lookup line in
redactableConfigKeys, plus a docblock paragraph; - its spec pins;
- pins in two of the three declared
service-datasourcetest files (declared on [PM seat] domain:services — 🟢 zhuangjianguo · session_013j5gkUCpqQiti4GgPqqmnt #60216010344393); - one changeset.
No
service-datasourcesource line, no objectui file. - the one lookup line in
-
Changeset:
@objectstack/specpatch, a read-side redaction fix.service-datasourcemoves test files only, so it carries no changeset. -
Merge:
git merge-treeis clean ontomainat2a22177ae7and onto the three queue refs, with no file overlap.check-governed-merges: 0 of 5 paths.check-widening-tells --declaration no: no tell. -
Disclosure: the seat scanned every added diff line, the PR body, the changeset and the report for the withheld terms and found 0. The pins derive every spelling from the alias table and carry no literal.
-
No new id: no added test title, test string or runtime string carries a tracker id. Ids appear in code comments only.
What the review establishes:
-
One resolver, as the claim asked. The per-driver half of
redactableConfigKeysnow resolves throughresolveDriverIdand indexes by the resolved id, exactly aspassthroughSecretPathsdoes. The write door's contract lookup uses the same resolver, so the set of spellings accepted as a driver and the set redacted as that driver are now one function. No other raw driver index remains in source. -
Reach was measured first. At the base, the admin item read served the still-writable credential key under an accepted non-canonical spelling, and
redactedConfigKeyswas empty. The list read serves noconfigby contract. After the fix, every accepted spelling is withheld and named. -
The crafted id has a defined answer for every reader. It resolves to nothing, so it answers as a driver with no shipped contract: the canonical credential spellings and the former aliases are withheld, and nothing throws. This holds in
getDatasource, the metadata redactor,restoreRedactedConfigandplanCredentialMigration. -
Lockstep, with no source change.
service-datasource's readers call the spec export and reach the fix through it. An untouched Save still restores the stored value under every accepted spelling, so redaction never turns a save into a deletion. -
The pins go red on the defect. The two ablation legs went red as predicted:
- the spec pins: 3 failed, with the premise and the control green;
- the dist-resolved
service-datasourcepins: 5 failed, with a build and a marker preflight on both legs.
Both restored green, with the blob equal to the head.
-
Clause-②: noholds. No schema, export or type changes, and what the write door accepts is unchanged. The change only narrows what a read serves.
CI on
cbea11408e: complete, 35 check-runs: 32 success and 3 skipped, 0 failed.check-expected-skipsreads all three skips as in its roster.Deviations, accepted:
datasource-admin-service.test.tsuntouched, since the item read and the save round-trip are pinned throughDatasourceAdminServicein the first file;- the second, dist-resolved ablation beyond the dispatch;
check:dual-build-cjs-loadsNOT MEASURED locally and run by CI;- the model-free trailer pair.
The dev's open question: the card body's Dedupe search line spells terms that the card's own withholding rule keeps off public surfaces. The contract review answers it A: the filing seat (
domain:devxseat 2) edits that one line to public terms, in the form the "Dedupe words" line already shows. It is not this PR's act. The seat points the filing seat to it on its seat post, without restating the line.Out of scope, noted, not filed: the two per-driver tables are string-keyed records. Typing them by the builtin id union would make a raw-string index a compile error and close this class at compile time. It is a hardening observation with no defect and no reach of its own (filing gate). Carrier: none.
Landing: the seat flips it ready and arms auto-merge right after this record.
Fixes #21955closes the card on merge.-
objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsLanded: PR #21963 →
fb698251fe. The card is closedcompleteddomain:specseat 1 ·os-project-manager· sessionsession_01T9u38rswFp5Rw8DswRUReJ· 2026-10-06T08:24Z · holder of claim6010337650, which this act releases. Public terms only: the withheld detail stays withheld.- Landed: PR fix(spec): datasource read redaction resolves a driver's identity the way its sibling helper does #21963 merged through the merge queue at 2026-10-06T08:23Z as
fb698251fe. It has one parent (787104baa9) and is an ancestor oforigin/main.Fixes #21955closed the cardcompleted. - Content check: all 5 files on
origin/mainare blob-equal to the reviewed headcbea11408e(at-tier PASS6011847094, ACCEPT6011877054). - What now holds:
- The per-driver half of
redactableConfigKeysresolves a driver's identity throughresolveDriverId, the resolver its sibling helper and the write door's contract lookup already use. So every spelling the write door accepts as a builtin driver is redacted as that driver on the admin item read and on the metadata read, andredactedConfigKeysnames the withheld key. - A crafted driver id answers as a driver with no shipped contract: the canonical credential spellings and the former aliases are withheld, and the read succeeds.
service-datasource'srestoreRedactedConfigand the credential migration read the same list with no source change. An untouched Save still restores the stored value.- The release:
@objectstack/specpatch.
- The per-driver half of
- Pointed, not this seat's act: the card body's one Dedupe search line is the filing seat's to edit to public terms (
6011901473on [PM seat] domain:devx · seat 2 — ⏳ vacant #20163). - Not filed, noted in the ACCEPT: typing the two per-driver tables by the builtin id union, a hardening with no defect of its own. Carrier: none.
- Hot file released:
packages/spec/src/data/datasource-credential-redaction.tsand the twoservice-datasourcetest files.
This act removes
pm:dispatchedand the assignee.- Landed: PR fix(spec): datasource read redaction resolves a driver's identity the way its sibling helper does #21963 merged through the merge queue at 2026-10-06T08:23Z as
- added a commit that references this issue
on Oct 7, 2026
Filing gate: ① a reproducible defect with a named landing site — under the "may leak data" exception.
reach:NOT yet measured through a public door. A function-level reproduction exists atorigin/main3c7785d4, so the fix's first act is to measure reach on the datasource admin read. Filed bydomain:devxseat 2 (seat post #20163,session_01VF48aw8RPG6wzDnMgp6rtw), from the os-dev's out-of-scope finding on #21950 (PR #21953). #21950 is docs-only, so the defect is not fixed there. ⛔ Not graded or routed here. ⛔ Not a claim.What is known publicly
content/docs/data-modeling/drivers.mdx, "Secret-shaped keys with no binder slot", lists a still-writable credential key that is accepted on write and stored as plain text, and states that "every one of them is stripped before a datasource record is ever served back over the admin API or shown in the Setup UI".Detail withheld pending maintainer: the spelling, the key and the line are with the maintainer in the filing seat's session chat. ⛔ Not restated on a public surface (the services-lane disclosure rule for security-family cards).
Landing site
packages/spec/src/data/datasource-credential-redaction.ts, the per-driver half ofredactableConfigKeys. Its readers must stay in lockstep:service-datasource'srestoreRedactedConfigand the credential migration. The direction is one fix at one line, aligning the lookup with how its sibling helper resolves the driver. The owning lane decides.Reader who acts
Triage grades it and routes it. The landing site is
packages/spec, so it is spec-seat work.Dedupe: MCP
search_issues, repo-scoped, open and closed: a semantic query on datasource read redaction of a still-writable credential key under a driver alias (exact query with the maintainer; public terms in the Dedupe words line) gave 16 hits. None names this path. The same family, all closed: #13405 (nested position), #13602 (mongo CSFLE paths), #21086 (a third read path) and #21840 / #21921 (plugin drivers with no contract, ruled docs-only).Dedupe words:
redactableConfigKeys still-writable driver spelling·datasource redaction alias resolve·admin read still-writable credential servedGenerated by Claude Code