railiance-platform e82bb289 recorded against SECRETS-WP-0006-T05 (explicit wait on T04 serving; CCR-2026-0003 is provenance only). 29cccf8a recorded against SECRETS-WP-0008-T06, including the open tenant:coulomb vs tenant:platform question for the service JWT, left for an owner session. railiance-clock's review request opened as SECRETS-IN-0003. The intelligence-radar messages are superseded by SECRETS-WP-0010-T03 (done 2026-09-16) and answered by pointer. 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
426 lines
21 KiB
Markdown
426 lines
21 KiB
Markdown
---
|
|
id: SECRETS-WP-0006
|
|
type: workplan
|
|
title: "Adopt concrete OpenBao credential lanes from ops-warden"
|
|
domain: infotech
|
|
repo: secrets-engine
|
|
status: active
|
|
flavor: implementation
|
|
owner: codex
|
|
topic_slug: custodian
|
|
created: "2026-08-21"
|
|
updated: "2026-09-06"
|
|
state_hub_workstream_id: "31f7f8ea-7f73-516c-8877-f03a13f1db82"
|
|
---
|
|
|
|
# SECRETS-WP-0006 - Adopt concrete OpenBao credential lanes from ops-warden
|
|
|
|
## Goal
|
|
|
|
Move concrete, OpenBao-backed credential workflows from ops-warden's interim
|
|
proxy into the secrets-engine catalog and operating surface without moving
|
|
secret custody out of OpenBao or misassigning generic routing and identity
|
|
capabilities to this repo.
|
|
|
|
The intake originates in ops-warden message
|
|
`cbd312f8-347e-44cc-933b-9712e2036646` after earlier requests on 2026-08-11 and
|
|
2026-08-15.
|
|
|
|
## Scope decision
|
|
|
|
Accept these concrete OpenBao KV lanes for catalog admission and staged
|
|
operation:
|
|
|
|
- `issue-core-ingestion-api-key`;
|
|
- `reuse-surface-hub-write-token`;
|
|
- `openrouter-llm-connect`;
|
|
- `forgejo-admin-api-token`;
|
|
- `email-connect-transactional`.
|
|
|
|
Do not create catalog entries for these generic or non-owned routes:
|
|
|
|
- `openbao-api-key` remains a generic credential-routing template. Concrete
|
|
workload credentials beneath it may become catalog lanes, but the template is
|
|
not itself a secret lane.
|
|
- `key-cape-oidc-login` remains owned by key-cape/Keycloak. secrets-engine may
|
|
consume OIDC identity for OpenBao authentication, but it does not own login,
|
|
MFA, or identity-token issuance.
|
|
|
|
The current implementation is generic at the catalog level for KV
|
|
`mount`/`path`/`fields`, and `secrets-engine exec` supports `exec-env` plus the
|
|
npm-specific `npm-config` adapter. The remaining delivery-mode names are not all
|
|
exec adapters: `read-check` is verification, `approle-login` is auth-capability
|
|
handoff. `exec-file` is implemented by `exec`; `wrapped` operator handoff is
|
|
`secrets-engine wrap`, not an exec adapter.
|
|
|
|
## Design constraints
|
|
|
|
- OpenBao remains the custody, policy, lease, and audit backend.
|
|
- No raw value, token, password, wrapped token, AppRole material, or accessor is
|
|
written to Git, State Hub, chat, prompts, workplans, or normal logs.
|
|
- Catalog adoption does not by itself authorize production mutation or value
|
|
access. Each production lane needs a resolved approval and a reviewed live
|
|
apply/verification plan.
|
|
- Existing workload delivery must not be displaced. ESO/Kubernetes delivery and
|
|
provider-side rotation remain owned by their current runtime and provider
|
|
owners until an explicit migration is approved.
|
|
- High-risk lanes must retain exact consumer, field, rotation-owner, denial, and
|
|
revocation metadata.
|
|
- The production stage role currently manages owner-scoped paths on the
|
|
`secret` mount, while these lanes use the existing `platform` mount. Admission
|
|
must not silently broaden the stage role or attempt to create that mount.
|
|
|
|
## Confirm capability and ownership with ops-warden
|
|
|
|
```task
|
|
id: SECRETS-WP-0006-T01
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "94d54df8-4088-5475-992b-7fe838c7c7d7"
|
|
```
|
|
|
|
Completed 2026-08-21. Replied in the existing thread with State Hub message
|
|
`7fb0c2ce-be41-4a1d-95b0-e2cdd97d5718`, marked the inbound message read, and
|
|
recorded decision `ae676382-1826-4e04-aa4e-bb77990c7a0d`. The reply accepted
|
|
the five concrete KV lanes, declined the generic OpenBao route and key-cape
|
|
login route, corrected the six-delivery-mode interpretation, and kept interim
|
|
proxies in place pending per-lane verification.
|
|
|
|
Reply in the existing State Hub thread with the accepted five-lane scope, the
|
|
two declined generic/non-owned routes, and the delivery-mode correction. Accept
|
|
ops-warden's offer of a PR-shaped non-secret metadata contribution for the five
|
|
concrete lanes.
|
|
|
|
Done when the reply is posted, the inbound message is marked read, and this
|
|
decision is recorded as non-secret State Hub evidence.
|
|
|
|
## Define admission contract for existing production lanes
|
|
|
|
```task
|
|
id: SECRETS-WP-0006-T02
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "1a04ee82-ff61-55bc-bae8-62e1229d9dcc"
|
|
```
|
|
|
|
Completed 2026-08-21. Added explicit `mount_management`, `delivery_auth`, and
|
|
`workload_delivery` semantics, with the operating contract documented in
|
|
`docs/catalog-admission.md`. Existing mounts and externally managed delivery
|
|
auth now render non-mutating checks; apply cannot create or rewrite them.
|
|
Existing workload delivery remains independent metadata, while an optional
|
|
engine-managed AppRole is a separate approval-gated native delivery surface.
|
|
|
|
Define how a catalog entry represents a lane whose KV mount already exists and
|
|
whose workload delivery is ESO/Kubernetes rather than a secrets-engine-created
|
|
AppRole. Separate these concepts where needed:
|
|
|
|
- existing-mount versus engine-managed mount;
|
|
- workload delivery versus agent/operator exec delivery;
|
|
- catalog/verification metadata versus engine-managed consumer auth;
|
|
- provider-side rotation owner versus OpenBao value update workflow.
|
|
|
|
Acceptance:
|
|
|
|
- Dry-run cannot propose creating or broadening the shared `platform` mount.
|
|
- A lane can retain its existing workload auth/delivery while optionally
|
|
exposing an approved exec-time adapter.
|
|
- The production stage role is not broadened by implication.
|
|
|
|
## Review and import the five catalog entries
|
|
|
|
```task
|
|
id: SECRETS-WP-0006-T03
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "b595f38e-bb31-513b-bc73-796cec76a2aa"
|
|
```
|
|
|
|
Completed 2026-08-21. The offered contribution did not arrive, so drafted all
|
|
five entries from ops-warden playbooks and the authoritative railiance-platform
|
|
CCRs, then requested line-by-line review in message
|
|
`ceace632-2332-46d8-a2b3-1714fbfa7e2c`. Ops-warden confirmed the mounts, paths,
|
|
field sets, CCR references, consumers, lifecycle owners, existing workload
|
|
delivery, proposed exact-path AppRole surface, both route rejections, and the
|
|
delivery-mode correction in messages `26df37c5-2756-49b8-8f9c-c1bb2bab1b4b`
|
|
and `3f875d90-6f88-4f44-961b-6f6fbd15b01d`. The follow-up retracted the only
|
|
apparent metadata concern: `REUSE_SURFACE_FORGEJO_WEBHOOK_SECRET` is explicitly
|
|
present in CCR-2026-0005, so both reuse-surface and issue-core remain correctly
|
|
classified `high`. Interim proxy ownership remains unchanged until T05.
|
|
|
|
Review ops-warden's proposed entries line by line against the schema, canonical
|
|
security boundary, live route metadata, and owning workload documentation.
|
|
Correct field lists, mount/path, consumers, delivery modes, approval references,
|
|
rotation owners, and negative checks before merging.
|
|
|
|
Acceptance:
|
|
|
|
- All five files contain non-secret metadata only.
|
|
- Generic `openbao-api-key` and `key-cape-oidc-login` entries are absent.
|
|
- Each entry names an exact lane rather than a provider-wide wildcard.
|
|
- Each high-risk lane has explicit rotation and deactivation expectations.
|
|
|
|
## Implement guards and offline verification
|
|
|
|
```task
|
|
id: SECRETS-WP-0006-T04
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "b2ca67ec-48e0-5f85-b4d8-94eb601206c5"
|
|
```
|
|
|
|
Completed 2026-08-21: implemented non-mutating existing-mount/auth planning and
|
|
apply behavior, workload-delivery validation, exact field guards for exec and
|
|
verification, safe policy/role overrides, route guidance, and focused tests.
|
|
All five admitted entries load and render `kv-mount-check` plus an exact-path
|
|
policy and bounded AppRole plan. Generic/wildcard entries and undeclared fields
|
|
are negatively covered. Privileged provision, verify, exec, handoff, and live
|
|
revoke operations now fail closed without a resolved approval. Full verification
|
|
passes 82 tests.
|
|
|
|
Implement only the schema/planning/delivery changes required by the admitted
|
|
entries. Add tests for shared existing mounts, auth/delivery separation,
|
|
multi-field selection, exact exec-env injection, and rejection of wildcard or
|
|
generic provider-wide entries.
|
|
|
|
Acceptance:
|
|
|
|
- The complete catalog loads and validates.
|
|
- Each admitted lane renders a non-mutating guarded plan.
|
|
- Negative tests prove no wildcard path, broad policy, undeclared field, or
|
|
unsupported delivery mode is accepted.
|
|
- `uv run pytest` and `git diff --check` pass.
|
|
|
|
## Stage live apply and verification
|
|
|
|
```task
|
|
id: SECRETS-WP-0006-T05
|
|
status: wait
|
|
priority: high
|
|
state_hub_task_id: "fb103f1e-2ff7-5de5-9a2c-191a19c43542"
|
|
```
|
|
|
|
Inbox triage 2026-09-21. railiance-platform `e82bb289` (2026-09-09) answered
|
|
the openrouter-llm-connect first-lane request with an explicit **wait on T04
|
|
serving**: no approval object path and no scoped attended authority yet, because
|
|
the canonical `action=apply` ActionAuthorization does not exist and llm-connect
|
|
has not confirmed ESO health. It accepts the apply shape and rollback
|
|
containment in principle, confirms CCR-2026-0003 is provenance and not
|
|
executable authorization for a native AppRole, and will name the approval path
|
|
and attended window together once T04 serves and llm-connect confirms. Keep
|
|
`forgejo-admin-api-token` last. Nothing changes here; T05 stays `wait`.
|
|
|
|
Progress 2026-09-03. Re-rendered guarded plans on the post-hardening engine.
|
|
Every admitted lane is still `kv-mount-check` + exact-path read policy +
|
|
bounded AppRole. First live candidate is `openrouter-llm-connect` (narrowest
|
|
consumer/field set). Procedure: `docs/native-lane-cutover.md`. Coordinated:
|
|
railiance-platform `0190c9b3` (AppRole-only apply, no KV/ESO mutation),
|
|
ops-warden `c2c01262` (keep all five proxies), llm-connect `6f9b460a` (ESO
|
|
stays theirs). Live apply still wait on T04 serving plus a canonical
|
|
`action=apply` approval and scoped attended authority. CCR-2026-0003 remains
|
|
provenance, not that approval. Proxies stay until T06 per lane.
|
|
|
|
Readiness update 2026-08-21: rendered non-mutating production dry-runs for all
|
|
five lanes. Every plan checks the externally managed `platform` mount without
|
|
mutation, writes one exact-path read policy, and proposes the reviewed bounded
|
|
AppRole (15-minute token TTL, 30-minute maximum TTL, 15-minute single-use
|
|
Secret ID, and eight token uses). OpenBao is reachable and unsealed, but route
|
|
status remains `ready: false`: the original CCR references approve the existing
|
|
workload lanes and are not resolvable State Hub approvals for the new native
|
|
AppRoles. This session also has no production OpenBao token or bootstrap file.
|
|
Requested per-lane approval references and scoped attended/apply authority from
|
|
railiance-platform in message `3db3da86-2f3f-4301-8be6-74b507ea66a0`. No value
|
|
was read and no OpenBao mutation was attempted.
|
|
|
|
Hardening dependency 2026-08-23: `SECRETS-WP-0007` now owns the engine-level
|
|
provisioning, lifecycle, approval-binding, delivery-session, verification, and
|
|
evidence gaps found during scope assessment. T05 must not provision or revoke
|
|
the existing shared paths through the current commands. Native live adoption
|
|
resumes through `SECRETS-WP-0007-T07` after its T01-T06 safety gates; this task
|
|
continues to own the per-lane production evidence and acceptance outcome.
|
|
|
|
For each lane, obtain the required decision/operator approval before any live
|
|
OpenBao policy, auth-role, provisioning, rotation, or delivery change. Start
|
|
with metadata/capability-safe checks and preserve the current ops-warden proxy
|
|
until native positive and negative verification succeeds.
|
|
|
|
Acceptance per lane:
|
|
|
|
- Approval is resolved and linked.
|
|
- Existing workload delivery remains healthy.
|
|
- Positive access and unrelated-consumer denial are proven without reading a
|
|
value into evidence.
|
|
- Rollback/revocation steps are recorded.
|
|
|
|
## Reconcile routing ownership and retire interim proxies
|
|
|
|
```task
|
|
id: SECRETS-WP-0006-T06
|
|
status: wait
|
|
priority: medium
|
|
state_hub_task_id: "1431edae-5791-5892-8c4b-829419b537d2"
|
|
```
|
|
|
|
After a lane is natively ready, update the ops-warden delegation register and
|
|
safe next action for that lane. Retire interim proxy operation lane by lane,
|
|
not as a seven-lane batch.
|
|
|
|
Acceptance:
|
|
|
|
- Native readiness is evidenced before the proxy is retired.
|
|
- ops-warden remains the routing front door and does not vend non-SSH secrets.
|
|
- The generic OpenBao route and key-cape login route retain their correct
|
|
owners.
|
|
|
|
Discrepancy report 2026-09-06 (ops-warden `fc898979`, WARDEN-WP-0037-T01).
|
|
ops-warden reports the authoritative whynot-design npm concrete pointer as
|
|
`platform/workloads/coulomb/whynot-design/npm-publish`, field `NPM_AUTH_TOKEN`,
|
|
endpoint `https://forgejo.coulomb.social/api/packages/coulomb/npm/`. Reviewed
|
|
here without any OpenBao read or mutation:
|
|
|
|
- Endpoint agrees. `catalog/whynot-design-npm-publish.yaml` already carries the
|
|
Forgejo registry in `delivery_config.npm.registry`.
|
|
- The field claim is a category error, not a repo defect. `NPM_AUTH_TOKEN` is
|
|
the resolved *injection env var* from `publication_policy.resolve` (default
|
|
template, repo-clamped while netkingdom is `maturity-build`), not a KV field
|
|
name. The declared KV field is `npm_token`. `docs/whynot-design-real-publish-closeout.md`
|
|
lists both rows separately. Renaming the catalog field to `NPM_AUTH_TOKEN`
|
|
would break the proven pilot lane.
|
|
- The path claim is credible and unresolved here. `docs/hardening-backlog.md`
|
|
already records the value against *both* `whynot-design-npm-publish` and
|
|
`platform/workloads/coulomb/whynot-design/npm-publish`, and every other
|
|
admitted lane uses the `platform/workloads/...` convention. Which location is
|
|
authoritative for reads is custody state owned by railiance-platform; this
|
|
repo cannot confirm it without lane read authority, and production live
|
|
commands remain fail-closed pending `SECRETS-WP-0007-T04`.
|
|
|
|
The catalog mount/path is therefore left unchanged pending a custody-side
|
|
confirmation from railiance-platform. Rewriting a proven production lane pointer
|
|
from an inbox claim is exactly the unverified custody mutation this task must
|
|
not make. `ready: false` observed by ops-warden is the expected fail-closed
|
|
result and is not evidence of a wrong path.
|
|
|
|
Next: obtain from railiance-platform a non-secret confirmation of which KV
|
|
location backs this lane. If the platform path is authoritative, the catalog
|
|
mount/path move is a reviewed lane change carrying its own approval, and the
|
|
declared field stays `npm_token` unless custody says otherwise.
|
|
|
|
Asked 2026-09-07 (hub message `546403e4` to `railiance-platform`). The question
|
|
is narrowed to the path alone, since the endpoint agrees and the
|
|
`NPM_AUTH_TOKEN` claim was resolved here as a category error rather than a
|
|
discrepancy. Also asked whether the current `secret/...` location still exists
|
|
if the platform path is authoritative — a stale duplicate holding a real token
|
|
is worth knowing about independently of this lane. Flagged to them that
|
|
ops-warden's `ready: false` is our expected fail-closed posture and must not be
|
|
read as corroborating the platform path. Awaiting reply; the catalog is
|
|
unchanged.
|
|
|
|
|
|
## Exit criteria
|
|
|
|
- The five concrete OpenBao lanes have reviewed catalog entries and guarded
|
|
offline plans.
|
|
- Live ownership moves only for lanes that pass approved positive/negative
|
|
verification.
|
|
- The two generic/non-owned routes are not mislabeled as secrets-engine lanes.
|
|
- No secret material is recorded in repository or coordination evidence.
|
|
|
|
|
|
### Native OpenRouter handoff from SECRETS-WP-0010 — 2026-09-16
|
|
|
|
SECRETS-WP-0010-T03 completed the exact read-only key-check recipient: native
|
|
apply and verify, distinct human-approved CAS consumption for all three actions,
|
|
OpenRouter GET /api/v1/key HTTP 200, unrelated identity/path denials, explicit
|
|
revoked-token HTTP 403, and unchanged llm-connect/ESO health. Evidence:
|
|
`docs/evidence/2026-09-16-t03-completion.json`. No inference was performed.
|
|
This supplies one lane's evidence; this workplan retains its existing broader
|
|
live adoption tasks. SECRETS-WP-0006-T05/T06 own other-lane acceptance and
|
|
routing/proxy retirement; SECRETS-WP-0007-T04/T07 retain general native readiness.
|
|
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.
|