diff --git a/credential-change-requests/CCR-2026-0001-whynot-design-npm-publish.yaml b/credential-change-requests/CCR-2026-0001-whynot-design-npm-publish.yaml index 9c79317..4902b50 100644 --- a/credential-change-requests/CCR-2026-0001-whynot-design-npm-publish.yaml +++ b/credential-change-requests/CCR-2026-0001-whynot-design-npm-publish.yaml @@ -101,6 +101,25 @@ verification: - Secret value provisioned directly in OpenBao through approved operator custody. - Positive and negative verification recorded with non-secret audit ids or timestamps. evidence: + - at: '2026-09-10T07:00:55+00:00' + actor: bernd.worsch + kind: attended_field_name_resolution + result: passed + details: + - Attended founder session enumerated field names at platform/workloads/coulomb/whynot-design/npm-publish. + - The only field present is NPM_AUTH_TOKEN, at KV version 2. This request's + openbao.fields is correct and unchanged. + - secrets-engine reported a different, lowercase field name and ops-warden + changed their catalog and playbook on that statement; both name a field + absent from this path. The exact spelling is deliberately not repeated here + because the CCR secret-marker guard rejects it; see + docs/workload-kv-access-lanes.md. Reverting that catalog change is tracked + with the owners. + - Legacy path secret/coulomb/whynot-design/npm/publish exists at version 1, + created 2026-07-03T15:00:44Z, never updated, outside this request's policy. + Field names not enumerated. Disposition RPF-WP-0035-T07. + - Read-only; no value emitted, no mutation. Receipt + docs/evidence/2026-09-10-npm-lane-field-resolution.json. - at: '2026-06-28T10:37:42+00:00' actor: codex kind: non_secret_openbao_apply_check diff --git a/docs/evidence/2026-09-10-npm-lane-field-resolution.json b/docs/evidence/2026-09-10-npm-lane-field-resolution.json new file mode 100644 index 0000000..9f518ab --- /dev/null +++ b/docs/evidence/2026-09-10-npm-lane-field-resolution.json @@ -0,0 +1,30 @@ +{ + "schema": "platform.openbao-open-questions-session.v1", + "observed_at": "2026-09-10T07:00:55.690609+00:00", + "operation": "read-only observation", + "credential_values_emitted": false, + "openbao_mutations": 0, + "questions": [ + "Q1", + "Q2" + ], + "attended_identity": true, + "ambient_token_vars_present": [], + "q1_legacy_npm_path": { + "legacy_mount_present": true, + "legacy_path": "secret/coulomb/whynot-design/npm/publish", + "legacy_path_present": true, + "current_version": 1, + "created_time": "2026-07-03T15:00:44.99885594Z", + "updated_time": "2026-07-03T15:00:44.99885594Z" + }, + "q2_npm_lane": { + "path": "platform/workloads/coulomb/whynot-design/npm-publish", + "readable": true, + "field_names": [ + "NPM_AUTH_TOKEN" + ], + "kv_version": 2, + "values_recorded": false + } +} diff --git a/docs/workload-kv-access-lanes.md b/docs/workload-kv-access-lanes.md index 973b488..e8e6300 100644 --- a/docs/workload-kv-access-lanes.md +++ b/docs/workload-kv-access-lanes.md @@ -64,19 +64,22 @@ caller-scoped lane. The sibling lanes `issue-core-ingestion-api-key` and `openrouter-llm-connect` remain draft and are tracked separately by `RAILIANCE-WP-0009` and `RAILIANCE-WP-0010`. -> **Field name contested, 2026-09-09 — do not change this on either side yet.** -> secrets-engine states the KV field is `npm_token` and that `NPM_AUTH_TOKEN` is -> only the environment variable their publication-scope policy injects; -> ops-warden has already corrected their catalog and playbook on that statement. -> This repository holds two dated live receipts naming `NPM_AUTH_TOKEN` as the -> OpenBao **field**, in `CCR-2026-0001`: a field-presence check on -> 2026-06-28T10:37:42Z, and an attended fetch by the founder on -> 2026-06-28T15:22:29Z that exited successfully with output to `/dev/null` — a -> `-field=` fetch that exits zero means that field exists. Both records can be -> true if the path carries **both** fields. Q2 of the attended session -> (`docs/openbao-open-questions-session.md`) enumerates the actual field names -> and settles it. Until then this table stays as written, because it is the side -> backed by receipts. +> **Field name settled, 2026-09-10 — attended read, `NPM_AUTH_TOKEN` confirmed.** +> An attended founder session enumerated the field names at this path: the only +> field present is `NPM_AUTH_TOKEN`, at KV version 2. The table above is correct +> as written and needs no change. secrets-engine's `npm_token` and the +> ops-warden catalog change made on that statement both name a field that does +> not exist at this path, so that change must be reverted before the lane is +> next used. The "both fields exist" reconciliation is ruled out. +> Receipt: [2026-09-10 field resolution](evidence/2026-09-10-npm-lane-field-resolution.json) +> — field names only, no value emitted, `attended_identity: true`. +> +> **The same session found the legacy path is real.** +> `secret/coulomb/whynot-design/npm/publish` exists at version 1, created +> 2026-07-03T15:00:44Z and never updated — five days *after* this governed lane +> was verified. It sits outside this lane's exact-path policy and outside +> CCR-2026-0001. Its field names were not enumerated. Disposition is +> RPF-WP-0035-T07; do not read, copy or delete it outside that task. The fetch command returns the secret value to the authenticated caller. Run it only in an attended shell or through a process that consumes the value without diff --git a/workplans/RPF-WP-0035-credential-lane-implementation.md b/workplans/RPF-WP-0035-credential-lane-implementation.md index fd1e102..8e8319f 100644 --- a/workplans/RPF-WP-0035-credential-lane-implementation.md +++ b/workplans/RPF-WP-0035-credential-lane-implementation.md @@ -242,6 +242,45 @@ Neither Warden fetch selector is resolvable through these verifier-only CCRs. Do not re-request the completed two named reviews or reseed these paths. Rotation is a distinct, version-guarded operation. +## Dispose of the ungoverned whynot-design npm duplicate + +```task +id: RPF-WP-0035-T07 +status: todo +priority: high +``` + +Found by the attended session on 2026-09-10 while settling the npm field +question. `secret/coulomb/whynot-design/npm/publish` exists at version 1, +created 2026-07-03T15:00:44Z and never updated — five days after the governed +lane at `platform/workloads/coulomb/whynot-design/npm-publish` was verified +(CCR-2026-0001, 2026-06-28). It sits outside that lane's exact-path policy and +outside any CCR here. Receipt: +`docs/evidence/2026-09-10-npm-lane-field-resolution.json`. + +Only metadata was read. Its field names were not enumerated, its value was not +read, and nothing was deleted — a location holding real credential material is +disposed of deliberately, not tidied away in the session that found it. + +The likely explanation, unconfirmed: secrets-engine reports the lane's field +under a lowercase name that is absent from the governed path, and their catalog +declares this legacy location. If their proven pilot publish read from here, +then a working production lane has been running off an ungoverned duplicate, +and the governed lane's acceptance evidence describes a path the consumer does +not use. That is worth establishing before anything is removed. + +**Unblock:** secrets-engine confirms which location their publish actually reads +and whether the two hold the same value; the owner of the legacy path is +identified; and a metadata-or-field-name read of the legacy path is admitted so +the duplicate can be characterised without reading its value. + +**Done when:** the legacy path's provenance and consumer are established, the +governed lane is confirmed as the one in use or the consumer is moved to it as a +reviewed lane change, the duplicate is destroyed or brought under a CCR with an +owner, and the disposition is recorded. If the value proves to be live and +ungoverned, treat it as an exposure with the same custody rules as RPF-WP-0027: +never record the value, fingerprint, length or shape. + ## Admit the separate approval client-side readers ```task