10 KiB
| id | type | title | domain | repo | status | owner | topic_slug | created | updated | state_hub_workstream_id |
|---|---|---|---|---|---|---|---|---|---|---|
| SECRETS-WP-0004 | workplan | Provision a scoped warden-sign token lane (ops-warden / FLEX-WP-0007 T4) | infotech | secrets-engine | active | codex | custodian | 2026-06-29 | 2026-06-29 | eb1bdff7-909c-4391-8b95-6baf1feb3a54 |
SECRETS-WP-0004 - Provision a scoped warden-sign token lane
Goal
Give ops-warden a scoped OpenBao credential that can run warden sign over the
HTTP API, minted and custodied by secrets-engine. Model it as a first-class
secrets-engine auth-capability lane (an OpenBao policy + AppRole granting a
narrow capability), not a KV value. Post the non-secret pointers to State Hub and
hand the token/secret_id to the operator out-of-band.
This unblocks FLEX-WP-0007 T4 (the joint OpenBao + policy-gate production smoke),
after which policy.enabled: true can go live on CoulombCore.
Context
ops-warden raised this on State Hub (msg 077ac90d, 2026-06-28). warden's vault
backend signs over the HTTP API (X-Vault-Token) and holds no standing OpenBao
token (conduit-not-broker), so token custody/minting is squarely secrets-engine's
lane. The operator cannot mint one interactively: the bao CLI is not installed
on CoulombCore and bao login -method=oidc is therefore unavailable — hence the
preference for an AppRole the operator can use non-interactively.
Target backend is the production OpenBao at https://bao.coulomb.social,
mount ssh. Actors in scope: agt-state-hub-bridge (primary),
agt-codex-interhub-bootstrap, adm-example, atm-backup-daily. The signing
roles are agt-role, adm-role, atm-role.
This is the first non-KV, non-npm lane and the first lane that touches production OpenBao, so it also exercises parts of the engine the npm pilot did not.
Design Constraints
- No token value or AppRole
secret_idin Git, State Hub, chat, prompts, workplans, or normal logs — pointers only on the hub, value out-of-band. - The
warden-signpolicy must be narrow:updateonssh/sign/<role>for the allowlisted roles only. No broaderssh/*, nosys/,auth/token/,identity/, no root/sudo. - Production apply uses a mode-0600 bootstrap token outside any repo, revocable,
recorded in
docs/hardening-backlog.mdH0. - ops-warden takes no custody; secrets-engine owns minting and revocation.
Tasks
T01 - Extend the catalog for auth-capability (non-KV) lanes
id: SECRETS-WP-0004-T01
status: done
priority: high
state_hub_task_id: "278e9a20-eaa6-47a8-9dd7-62952961d520"
2026-06-29: Implemented kind: auth-capability catalog support, fieldless
non-KV validation, KV provisioning bypass/rejection, route semantics, and dry-run
plan/apply handling while preserving the existing KV/npm lane behavior.
Add a lane kind that represents an OpenBao auth credential (AppRole + policy)
granting a capability on a mount, rather than a KV value. The current schema
assumes a KV mount/path/fields value and provision --from-file; an
auth-capability lane has no stored value — the deliverable is the minted token /
secret_id.
Acceptance:
- The schema validates a
warden-signauth-capability lane (kind explicit). - KV-only assumptions (
kv_data_path, from-file provisioning, value verification) are bypassed for this kind without weakening the npm KV path. plan/applyproduce a policy + AppRole for the lane.
T02 - Define the warden-sign policy and AppRole
id: SECRETS-WP-0004-T02
status: done
priority: high
state_hub_task_id: "f4b209e5-c900-4f5e-bb0c-f0c5b27b70c2"
2026-06-29: Added catalog/warden-sign.yaml, exact warden-sign policy/AppRole
planning, guard coverage rejecting broad ssh/*, sys/, auth/token/,
identity/, wildcard, root-like, and non-update grants, plus tests for the
allowlist and denial probes. Production stage policy now has exact
warden-sign policy/AppRole management exceptions only.
Author the warden-sign ACL policy and AppRole. Policy: update on
ssh/sign/agt-role (plus adm-role, atm-role) on the ssh mount; nothing
else. AppRole warden-sign bound to that policy with a short token TTL, usable
non-interactively via role_id + secret_id (no bao CLI needed).
Acceptance:
- The policy lists exact allowed/denied paths; the guards in
roles.pyrefuse any broader variant (ssh/*,sys/,auth/token/,identity/, wildcards, root). - Negative check: a token from this AppRole can
signonly the allowlisted roles and is denied elsewhere on thesshmount. - The AppRole issues a scoped token carrying only the sign capability.
T03 - Apply against production OpenBao via bootstrap token
id: SECRETS-WP-0004-T03
status: wait
priority: high
state_hub_task_id: "4b414788-d670-496b-9c57-074464a012c4"
2026-06-29: Source apply path is implemented and dry-run verified. Live apply is
waiting on an approved SECRETS-WP-0004 decision/workplan gate plus a mode-0600
production bootstrap token outside any repo. The pending token path/revocation
row is recorded in docs/hardening-backlog.md H0.
2026-06-29: Attended ops-warden follow-up message
92de2614-061f-4241-aa13-a3ce72ad41d5. Production OpenBao is unsealed and the
dry-run apply plan is valid for exact update grants on ssh/sign/agt-role,
ssh/sign/adm-role, and ssh/sign/atm-role. Live apply remains blocked because
secrets-engine route warden-sign --json reports decision_status: missing
for SECRETS-WP-0004, and the documented lane bootstrap token file
~/.secrets-engine/bootstrap/prod-warden-sign.token is absent. A broader
platform-admin token file exists with mode 600; it was not used to bypass the
missing lane decision or the documented bootstrap handoff.
2026-06-30: Approval mirror .decisions/SECRETS-WP-0004.yaml is now present
and secrets-engine route warden-sign --json reports decision_status: resolved for canonical decision 4589dcb7-c0df-4073-9a0b-4f80a0fcdb93.
Readiness remains false because the OpenBao warden-sign policy/AppRole has
not been applied (metadata_applied: false), and the documented lane bootstrap
token file is still absent. Live apply and handoff were not executed.
Apply the policy + AppRole on https://bao.coulomb.social using a mode-0600
bootstrap token stored outside any repo. Idempotent re-apply.
Acceptance:
- The
warden-signpolicy and AppRole exist on the production OpenBao. - The bootstrap token file is recorded in
docs/hardening-backlog.mdH0 with an explicit revocation task and TTL. - Apply evidence is non-secret (policy/role names, mount, addr, status — no value).
T04 - Out-of-band handoff and non-secret pointers
id: SECRETS-WP-0004-T04
status: wait
priority: high
state_hub_task_id: "52b5cf88-029f-4f4b-8fe9-0a8dc30378b5"
2026-06-29: Added secrets-engine handoff and
docs/warden-sign-auth-capability.md. Handoff writes role_id and a fresh
single-use secret_id to caller-chosen mode-0600 files outside Git worktrees and
records only non-secret file paths/TTL metadata. Execution is waiting on live
apply and attended out-of-band operator delivery.
2026-06-29: ops-warden follow-up message f5b276a3-b90f-454f-b883-83eee7c69616
asked for the OIDC login pointer instead of AppRole handoff because Bernd can
mint the scoped token on his workstation. Added the non-secret pointer:
bao login -method=oidc -path=netkingdom role=warden-sign, role path
auth/netkingdom/role/warden-sign, bound to groups=["net-kingdom-admins"]
and attaching only policy warden-sign. Replied to ops-warden in State Hub
message 0bce1e08-58c2-4db4-b06c-f86cf8142273; no token value, role_id,
secret_id, or token accessor was included.
2026-06-29: ops-warden follow-up message
92de2614-061f-4241-aa13-a3ce72ad41d5 requested the AppRole handoff as the
preferred end-state. Handoff was not executed because live apply is still gated
by the missing approved decision and missing lane bootstrap token. Once those
blockers clear, the intended handoff remains single-use AppRole material written
to mode-0600 files outside any Git worktree and delivered to Bernd out-of-band.
2026-06-30: The decision gate is now resolved by the offline approval mirror,
so handoff is waiting on live OpenBao apply plus an attended, out-of-band
bootstrap path. No role_id, secret_id, token value, token accessor, or
smoke output was written to Git or State Hub.
Define and execute the handoff: mint a fresh secret_id, deliver it (with the
role_id) to the operator out-of-band; warden does approle login to obtain a
VAULT_TOKEN. Post the non-secret pointers on the ops-warden thread (policy name,
AppRole name, mount ssh, addr https://bao.coulomb.social, token TTL, status).
Acceptance:
- Pointers are posted to State Hub; no token value or
secret_idappears there or in Git/logs. - The operator can run, on CoulombCore:
FLEX_AUTH_EXTERNAL=1 SMOKE_VAULT=1 VAULT_TOKEN=<scoped> ~/ops-warden/scripts/policy_gate_production_smoke.sh.
T05 - Confirm the joint smoke and signal ops-warden
id: SECRETS-WP-0004-T05
status: wait
priority: medium
state_hub_task_id: "aa0f281e-976d-4fcd-b8a3-78582117f86f"
2026-06-29: Offline tests pass (59 passed, 2 skipped) and route/dry-run CLI
checks produce non-secret pointers. Joint production smoke and ops-warden signal
remain waiting on live OpenBao apply, handoff, and operator-run smoke evidence.
Confirm the unblock end to end, then reply to ops-warden (msg 077ac90d) with the pointers and runbook alignment. The reply is the explicit "we will signal ops-warden when done" step.
Acceptance:
- Allow path resolves to
backend: vault+ apolicy_decision_id; deny path (ttl 999) is rejected by flex-auth before OpenBao. - ops-warden is replied to on State Hub with the non-secret pointers.
- A revocation/rotation task exists for the minted credential.
Exit Criteria
- A narrow
warden-signpolicy + AppRole exist on production OpenBao, minted and custodied by secrets-engine, granting onlyssh/sign/<allowlisted-role>update. - The operator can obtain a scoped
VAULT_TOKENnon-interactively withoutbao. - FLEX-WP-0007 T4 joint smoke is unblocked (or blocked only on an explicit external condition).
- ops-warden has the non-secret pointers; no secret value crossed State Hub.
- The bootstrap token and the minted credential have revocation tasks.