You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
⚠️Scope grew on measurement — read the PM review (comment 5275779695) before implementing. Three rulings are settled there and are ⛔ not re-litigable: the fix is one PR carrying the hook, the datasource redactor, the read-exit application, the getMetaItemLayered exit and the saveMetaItem write-path carry-forward; the registry seam itself is split out to #8300 (packages/spec, another lane) and this card consumes it. Second, non-dependency gate: #8136 must land first (protocol.ts serialisation).
⛔ The read scrub may NOT ship alone. Measured, not argued: saveMetaItemaccepts a redacted datasource body and persists the credential away, so a read-path redaction without the write-path inverse converts today's loud 422 into silent credential deletion on an ordinary GET-edit-PUT round trip.
Split out of #8081 by the domain:services PM seat. The implementing dev hit this, stopped, and reported it rather than fixing it, per the dispatch order's STOP rule — the fix leaves the services lane. ⛔ Not graded by me; no domain:* label.
PR #8126 stopped DatasourceAdminService.getDatasource() serving stored credentials. One door over, the platform still does.
decorateMetadataItem returns {...item, _diagnostics} — the whole stored body. So after #8126:
GET /api/v1/datasources/:name → clean
GET /api/v1/meta/datasources → still serves the stored cleartext
#8078's own refusal text asserts this door exists, in as many words: "the datasource is persisted whole into sys_metadata, which is served back by the ordinary data API."
✅ Re-measured on origin/maina7e94e990 and CONFIRMED, on three exits, not one: a legacy datasource row is served with config.password: "hunter2"and the password embedded in config.url by getMetaItems (the door this card names), by getMetaItem, and by getMetaItemLayered in both its overlay and effective layers.
⚠️ This bounds what #8081 item 1 is allowed to claim
The honest statement after #8126 is: the datasource-admin read path no longer serves stored credentials. It is not "the surface is closed." The dev said so unprompted, which is the reason this card exists rather than a false sense of closure:
I would rather you hear that now than read "item 1 done" and believe the surface is closed.
Recording it prominently because this is the third time in this programme that a partially-closed credential surface read as fully closed — #7799 → #7986 (webhook headers), #7986 ①-a → #8118 (delivery rows), and now #8126 → this card. The pattern is the same each time: a fix lands on the door that was measured, and the reading generalises past what was measured.
Why it needs its own lane
The surface is packages/metadata-protocol / packages/rest, not service-datasource.
It needs a generic per-type redaction hook on the metadata read path — datasource is not the only type that could hold a secret, so a datasource-shaped patch here would be the narrow fix that leaves the next type exposed.
The blast radius is every metadata type, which is why it did not belong as a rider on a card scoped to one service.
Constraints for whoever takes it
⛔ Do not solve it by redacting datasource specifically. The hook is the deliverable; the datasource case is its first consumer.
⭐ Now measured, and it fixes the ordering: diagnostics MUST be computed on the raw stored body BEFORE redaction. Computing them after flips valid:false → valid:true and destroys the badge. Reverse-verified in the predicted direction.
Not yet measured, and owed by whoever implements: SysMetadataRepository.getByHash / restoreVersion. getMetaItemCached inherits the leak by construction (it delegates to getMetaItem) and needs no separate hook.
Provenance: #8081 dev report (comment 5269923121, "A residual this PR does NOT close — STOP, leaves the lane") and my ACCEPT receipt (#8081 comment 5270102954). Related: #7990, #8078, #8081, #8118, #8300.
Blocked-by: #8300
5275779695) before implementing. Three rulings are settled there and are ⛔ not re-litigable: the fix is one PR carrying the hook, the datasource redactor, the read-exit application, thegetMetaItemLayeredexit and thesaveMetaItemwrite-path carry-forward; the registry seam itself is split out to #8300 (packages/spec, another lane) and this card consumes it. Second, non-dependency gate: #8136 must land first (protocol.tsserialisation).⛔ The read scrub may NOT ship alone. Measured, not argued:
saveMetaItemaccepts a redacted datasource body and persists the credential away, so a read-path redaction without the write-path inverse converts today's loud422into silent credential deletion on an ordinary GET-edit-PUT round trip.Split out of #8081 by the
domain:servicesPM seat. The implementing dev hit this, stopped, and reported it rather than fixing it, per the dispatch order's STOP rule — the fix leaves the services lane. ⛔ Not graded by me; nodomain:*label.What is still open after PR #8126
PR #8126 stopped
DatasourceAdminService.getDatasource()serving stored credentials. One door over, the platform still does.decorateMetadataItemreturns{...item, _diagnostics}— the whole stored body. So after #8126:GET /api/v1/datasources/:name→ cleanGET /api/v1/meta/datasources→ still serves the stored cleartext#8078's own refusal text asserts this door exists, in as many words: "the datasource is persisted whole into
sys_metadata, which is served back by the ordinary data API."✅ Re-measured on
origin/maina7e94e990and CONFIRMED, on three exits, not one: a legacydatasourcerow is served withconfig.password: "hunter2"and the password embedded inconfig.urlbygetMetaItems(the door this card names), bygetMetaItem, and bygetMetaItemLayeredin both itsoverlayandeffectivelayers.The honest statement after #8126 is: the datasource-admin read path no longer serves stored credentials. It is not "the surface is closed." The dev said so unprompted, which is the reason this card exists rather than a false sense of closure:
Recording it prominently because this is the third time in this programme that a partially-closed credential surface read as fully closed — #7799 → #7986 (webhook headers), #7986 ①-a → #8118 (delivery rows), and now #8126 → this card. The pattern is the same each time: a fix lands on the door that was measured, and the reading generalises past what was measured.
Why it needs its own lane
packages/metadata-protocol/packages/rest, notservice-datasource.Constraints for whoever takes it
datasourcespecifically. The hook is the deliverable; the datasource case is its first consumer._diagnosticsis load-bearing for the migration story ([services half of #7990] Close the datasource/connector credential write/read paths: scrubgetDatasource().config, fix the false "credential-stripped" claim, and write the stored-cleartext-rows migration story #8081 item 3 uses thevalid:falsebadge as its free inventory of affected rows). A redaction that also strips or breaks_diagnosticswould remove the operator's only enumeration path.valid:false→valid:trueand destroys the badge. Reverse-verified in the predicted direction.updateDatasource. This was learned the expensive way on fix(service-datasource): stop serving stored credentials on the datasource read path, and fix the false "credential-stripped" claim (#8081) #8126 — do not rediscover it.config.urlmakes this unavoidable rather than a masking choice: the URL-embedded password is schema-accepted (feat(spec)!: refuse inline credentials at publish — driver config + connector authoring door (#7990, spec half) #8078 pinned that boundary as fact), so dropping it round-trips to deletion and masking it round-trips to storing the mask as the literal password.SysMetadataRepository.getByHash/restoreVersion.getMetaItemCachedinherits the leak by construction (it delegates togetMetaItem) and needs no separate hook.sys_metadataserves the same bytes on a plane no metadata-read-path hook can reach — that is [security]sys_metadata.metadatais a general cleartext sink: any authored artefact whose schema permits an inline credential lands it there (datasourceconfig.password, connectorauthentication) #7990's, verified open and correctly deduped. ⛔ Do not file it again.Provenance: #8081 dev report (comment 5269923121, "A residual this PR does NOT close — STOP, leaves the lane") and my ACCEPT receipt (#8081 comment 5270102954). Related: #7990, #8078, #8081, #8118, #8300.