Answer the exec-path question: the front door reads the ungoverned duplicate.

ops-warden and railiance-platform asked, independently, which OpenBao location
`secrets-engine exec --catalog whynot-design-npm-publish` reads. Answered from
this repository's own code and catalog with no OpenBao read and no value.

It reads `secret/coulomb/whynot-design/npm/publish` — the legacy, ungoverned
duplicate. `_fetch_value` concatenates the catalog's `mount` and `path` with no
override or fallback, so the proven pilot published from the duplicate and the
lowercase `npm_token` field is the field there. ops-warden's front door names
this repository as exec_owner, so it currently routes callers at a path no CCR
covers.

Recorded in SECRETS-WP-0006 with what a move to the governed lane requires, and
flagged that the duplicate must not be destroyed until the lane moves. Whether
the two locations hold the same value is a value comparison and is not answered
here.

Also records GH-DEC-2026-017 against SECRETS-WP-0008: INTENT.md governs, the
sidecar is derived, the vocabulary is case-insensitive so nothing is re-spelled,
and standard_version comes out of layer.yaml once ops-warden updates the
reference form this repository copied.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 63291@bnt-lap001
Assistant-Session: 8bd77868-ca68-4f49-bb1e-d539ecc0d703
This commit is contained in:
tegwick 2026-09-21 02:36:31 +02:00
parent e5672846ab
commit 550ba95a67
3 changed files with 162 additions and 1 deletions

View file

@ -17,10 +17,23 @@ prompts, workplans, or normal logs.
| Org/repo | `coulomb/whynot-design` |
| npm package | `@whynot/design` |
| npm registry | `https://forgejo.coulomb.social/api/packages/coulomb/npm/` |
| Catalog mount/path | `secret/coulomb/whynot-design/npm/publish` |
| Catalog mount/path | `secret/coulomb/whynot-design/npm/publish` **(ungoverned legacy — see below)** |
| Catalog field | `npm_token` |
| Injected env var | `NPM_AUTH_TOKEN` |
> **Governance status, 2026-09-21.** The catalog mount/path above is the
> location `secrets-engine exec` actually reads — confirmed from
> `exec_delivery._fetch_value`, which concatenates `entry.mount` and
> `entry.path` with no override — and it is the **ungoverned duplicate**. The
> governed lane is `platform/workloads/coulomb/whynot-design/npm-publish` under
> CCR-2026-0001, field `NPM_AUTH_TOKEN`. The lowercase `npm_token` in the table
> above is the field at the legacy path, which is why the two records disagreed
> without either being wrong. Moving to the governed path is a reviewed lane
> change with its own approval; the steps are recorded in
> `workplans/SECRETS-WP-0006-catalog-lane-adoption.md` (2026-09-21). Until that
> move completes and re-verifies, the legacy path must not be destroyed or
> wrapped — it is the live publish path.
The decision UUID above is resolved from State Hub in normal operation. A
UUID-named local fixture exists only as an offline fallback for throwaway demos.

View file

@ -328,3 +328,89 @@ routing/proxy retirement; SECRETS-WP-0007-T04/T07 retain general native readines
Do not reuse the consumed approvals or treat the temporary key-check overlay as
approval for a radar trial recipient. IR-WP-0005 owns radar delivery acceptance;
IR-WP-0006 owns the outstanding USD 0.023712 billing reservation.
### 2026-09-21 answered: the exec front door reads the ungoverned legacy path
ops-warden (`abf27efc`) and railiance-platform (RPF-WP-0035-T07, `09b719fe`)
asked the same location-only question. Answered from this repository's own code
and catalog, with no OpenBao read and no value of any kind.
**`secrets-engine exec --catalog whynot-design-npm-publish` reads
`secret/coulomb/whynot-design/npm/publish`.** That is the legacy, ungoverned
duplicate, not the governed lane.
Derivation, which is short because there is no indirection to hide in:
- `catalog/whynot-design-npm-publish.yaml` declares `mount: secret` and
`path: coulomb/whynot-design/npm/publish`.
- `exec_with_secret` delegates the read to `_fetch_value` in
`src/secrets_engine/exec_delivery.py`, which issues
`kv get -format=json {entry.mount}/{entry.path}` inside the lane's AppRole
session. The path is the catalog pointer, concatenated, with no override,
fallback, alias, or environment substitution anywhere on the exec path.
- `publication_policy.resolve` and `delivery_config.npm` decide the injected
env-var name and the npm registry. Neither touches the KV location. Nothing
in `routing.py`, `safe_paths.py`, or the policy layer rewrites mount or path.
So railiance-platform's straightforward reading was the right one. The proven
2026-07-03 `@whynot/design` pilot published by reading the legacy duplicate, and
the lowercase `npm_token` field this repository has consistently reported is the
field **there** — which is why it never appeared at the governed path and why
nobody's record was wrong. ops-warden's `NPM_AUTH_TOKEN` and this repository's
`npm_token` were each correct about the location each side was describing.
The consequence is the one ops-warden named and it should be stated plainly
rather than softened: ops-warden's routing catalog lists secrets-engine as
`exec_owner` and routes callers here as the primary front door, so that front
door currently points at a path no CCR covers, and CCR-2026-0001's acceptance
evidence describes a path its consumer does not use. That is a real governance
gap, not a bookkeeping mismatch.
**Not answerable here, and not attempted:** whether the two locations hold the
same value. That is a value comparison. This repository will not read, fetch,
fingerprint, or compare either value, and has not. It is custody's question and
needs no answer from us to proceed with the path move.
#### What it would take to move to the governed path
The move is a reviewed production lane change, not an edit. In order:
1. **Custody confirms the governed lane is consumable by this lane's identity.**
`platform/workloads/coulomb/whynot-design/npm-publish` under CCR-2026-0001
grants read to the workload policy; the AppRole this engine's delivery
session assumes must be admitted on `platform/data/...` and
`platform/metadata/...` of exactly that path. Without that, the edit produces
a lane that denies on read.
2. **Reconcile the field name in the same change.** The catalog declares
`npm_token`; the governed path was enumerated by railiance-platform on
2026-09-10 as holding exactly one field, `NPM_AUTH_TOKEN`. Moving the path
without moving `fields:` produces `field 'npm_token' absent in lane` from
`_fetch_value`. The injected env var is separately resolved and stays
`NPM_AUTH_TOKEN` while netkingdom is `maturity-build`; after the move the KV
field name and the injected env-var name coincide, which is a coincidence and
must be annotated as one so the category error corrected on 2026-09-09 is not
reintroduced.
3. **Carry an approval.** The lane's `approval.model` is `decision`; this is a
production lane pointer change and takes its own approved decision, not the
existing `e6381a56` pilot decision.
4. **Re-verify positive and negative.** The lane's declared expectations — the
approved consumer reads the field, an unrelated identity is denied — must be
re-run against the governed path before the old pointer is abandoned.
5. **Update the derived records:** `docs/whynot-design-real-publish-closeout.md`
pointer table, `docs/hardening-backlog.md` (which already names both
locations), and `docs/cli.md`.
6. **Only then is destruction of the duplicate safe.** RPF-WP-0035-T07 holds
destruction pending this confirmation, correctly. The confirmation it was
waiting for is now given, and it is the unwelcome one: the duplicate is the
live consumer path, so it must not be destroyed or wrapped until this lane
has moved and re-verified. Destroying it today breaks production publish.
Note also `scripts/demo-e2e.sh:66`, which grants a policy on
`secret/data/prod/coulomb/whynot-design/npm` — a third, demo-only spelling under
a `prod/` prefix. It is a throwaway demo fixture and not a consumer lane, but it
should be renamed away from `prod` when the lane moves so it cannot be mistaken
for a fourth location.
`SECRETS-WP-0006-T06` stays `wait`: this answer unblocks the question, not the
lane change, which needs custody's step 1 and its own approval.

View file

@ -354,6 +354,68 @@ Acceptance:
- No fallback from JWT/service-auth failure into bootstrap or AppRole.
- Issued delivery sessions continue to self-revoke as in WP-0007-T05.
### 2026-09-21 GH-DEC-2026-017 — section 11 layer declaration ruled
Read from `gate-house/decisions/decisions.md`, not from message text.
`secrets-engine` is a named affected repository and carries both permitted
forms, so all four parts apply here. State Hub decision id
`82dd0fea-fabb-4940-92d5-d6e2ea9985f5`.
What the ruling settles for this repository:
1. **`INTENT.md` governs.** Our declaration is the `layer: Engine` key in
`INTENT.md` frontmatter. `layer.yaml` is a **derived artifact**: it must be
marked as derived, must name `INTENT.md` as what it derives from, and must
agree with it. Our `layer.yaml` already carries `declared_by: INTENT.md` and
a `Voice: INTENT.md (this repository's own declaration, §11)` header comment,
so we are among the repositories already treating the sidecar as derived in
substance. What is missing is the explicit derived marking the ruling now
requires as a field rather than a comment.
2. **The §3 vocabulary is case-insensitive and comparison must ASCII case-fold.**
Our `INTENT.md` says `Engine` and our `layer.yaml` says `engine`. Under §2 of
the ruling that is **conforming**, it was never a disagreement about a layer,
and **nothing here is re-spelled**. flex-auth withdrew the casing finding
itself (message `962bf395`) and its validator is the thing that changes. We
do not touch either file's spelling, and we do not "align" them.
3. **The vocabulary is closed with four tokens**`Taxonomy`, `Tooling`,
`Engine`, `Staff`. `Engine` is in it; no action.
4. **`standard_version` comes out of the declaration.** Our `layer.yaml` carries
`standard_version: "0.7"`. A declaration asserts a standing property and must
not carry a standard version; version-scoped state belongs in the derived
conformance record, which must name what it derives from and the version or
commit it was derived at.
**Deliberately not done in this session.** The ruling states that
`standard_version` is not one repository's habit but **ops-warden's reference
form**, which this repository copied along with seven others, and that ops-warden
is asked to make the change there rather than each adopter deciding independently.
ops-warden is updating that reference form in a parallel session. Inventing our
own sidecar shape ahead of it would produce exactly the divergence the ruling
exists to close, so we record the requirement and wait for the reference form.
What `secrets-engine` will need, once the reference form lands:
- Adopt the reference form's derived-artifact marking in `layer.yaml`, keeping
`declared_by: INTENT.md` or whatever field the reference form names for it.
- Remove `standard_version: "0.7"` from `layer.yaml`.
- Move the version the conformance run was derived at into our derived
conformance record, per the reference form's field for it. Our conformance
checker is `scripts/check_layer_conformance.py`; it reads `layer.yaml` today
and will need to read `INTENT.md` as the governing form, read the sidecar as
well, and **report a disagreement between them as a finding** rather than
resolve it by precedence. A casing-only difference is not such a disagreement.
- Keep `framework:`, `layer:`, `role:` and the substantive §3/§5/§6/§9.6
content unchanged. `role:` is explicitly not ruled and stays as it is.
- The `Framework:` header comment in `layer.yaml` cites
`security-layer-model_v0.7.md` while the ruling is issued against `v0.8`.
That is a citation in a comment, not a declaration version, so it is out of
scope for part 4 — but it should be refreshed in the same commit so the two
are not confused for each other.
No task is opened here by hand. This is a note against the workplan that already
owns `layer.yaml` / `pep-stance.yaml` / INTENT frontmatter staying in one voice;
the work lands under that exit criterion when ops-warden's form is published.
## Exit criteria
- The published PEP stance is the shipped default and stance application is