feat: add auth-capability lanes and pilot closeout

Add the warden-sign auth-capability lane, AppRole handoff, verification guards, docs, and tests.

Point the whynot-design pilot at the canonical decision and add the real publish closeout preflight/runbook.
This commit is contained in:
tegwick 2026-06-29 16:58:16 +02:00
parent a621fbaffd
commit 6382139890
27 changed files with 1455 additions and 107 deletions

View file

@ -4,7 +4,7 @@ type: workplan
title: "Close out the whynot-design npm publish pilot (real)"
domain: infotech
repo: secrets-engine
status: proposed
status: active
owner: codex
topic_slug: custodian
created: "2026-06-29"
@ -52,17 +52,40 @@ not change that gate.
auth replaces bootstrap files (hardening backlog H1).
- Every minted token gets a revocation task in `docs/hardening-backlog.md` (H0).
## 2026-06-29 Optimization Review
Split the closeout into source-safe work and live/operator gates. Source-safe work
can complete in this repo: point the lane at the canonical State Hub decision,
keep only a UUID-named offline fallback fixture for demos, document the real
publish runbook, provide a non-secret preflight, and hand ops-warden a route
pointer. Live work remains gated because it requires Gitea admin/package rights,
an operator-minted bot token, OpenBao bootstrap authority, a coordinated
`whynot-design` version bump, and a real publish.
Existing State Hub evidence for CCR-2026-0001 confirms the corrected approval
`e6381a56-6b04-4fd5-b2de-f3ef59cde888` and related OpenBao/OIDC verification,
but that CCR path is not the same as this repo's original MVP catalog path, so
it is approval context rather than proof that `secrets-engine exec` has already
published `@whynot/design`.
## Tasks
## T01 - Record the canonical State Hub decision for the lane
```task
id: SECRETS-WP-0003-T01
status: todo
status: done
priority: high
state_hub_task_id: "11586d9d-c6bb-4455-8560-32da75cb06d4"
```
2026-06-29: Reused the canonical approved State Hub decision
`e6381a56-6b04-4fd5-b2de-f3ef59cde888`, updated
`catalog/whynot-design-npm-publish.yaml` to reference that UUID, and replaced
the slug-named local decision fixture with a UUID-named offline fallback only.
`decision inspect` resolves from `source: hub` when State Hub is reachable.
Record a real State Hub decision approving establishment of the whynot-design npm
publish lane, then point `catalog/whynot-design-npm-publish.yaml`
`approval.decision_ref` at that decision's UUID. Retire the local fixture (keep it
@ -79,11 +102,16 @@ Acceptance:
```task
id: SECRETS-WP-0003-T02
status: todo
status: wait
priority: high
state_hub_task_id: "13a34d32-ab4b-4cf5-a1fb-e3e920649a23"
```
2026-06-29: Added bot-account evidence requirements to
`docs/whynot-design-real-publish-closeout.md`. This remains an operator/Gitea
admin gate; no repo-side command can create or prove the scoped bot without
Gitea admin credentials and package-permission evidence.
Create a dedicated Gitea bot account (e.g. `se-whynot-design`) whose package
publish rights are limited to `coulomb/whynot-design` / the `@whynot` scope, so
the repo-scope grant is enforced at the backend rather than only signalled by the
@ -101,11 +129,17 @@ Acceptance:
```task
id: SECRETS-WP-0003-T03
status: todo
status: wait
priority: high
state_hub_task_id: "746b5e7f-cc10-43e4-b6d3-7d792d95dfeb"
```
2026-06-29: Documented the safe apply/provision/verify sequence and added
revocation tracking rows for the production OpenBao bootstrap token and
whynot-design Gitea bot package token. Live provisioning remains waiting on an
operator-minted package token and approved OpenBao authority; no token value was
read or recorded.
Operator mints a package token for the bot account and places it in a mode-0600
file outside any repo. Provision it with
`secrets-engine provision whynot-design-npm-publish --stage prod --field npm_token
@ -123,11 +157,16 @@ Acceptance:
```task
id: SECRETS-WP-0003-T04
status: todo
status: wait
priority: high
state_hub_task_id: "36b925c2-0670-4481-95d9-1f23dcc96575"
```
2026-06-29: Added the real publish runbook and non-secret source-side preflight.
A real publish is still waiting on T02/T03 plus a coordinated version bump in the
external `whynot-design` repo and operator confirmation of the published package
version.
Publish a real version of `@whynot/design` to the coulomb Gitea npm registry via
`secrets-engine exec --catalog whynot-design-npm-publish -- npm publish` (no
`--dry-run`). Coordinate the version bump with the whynot-design repo.
@ -144,11 +183,17 @@ Acceptance:
```task
id: SECRETS-WP-0003-T05
status: todo
status: progress
priority: medium
state_hub_task_id: "461a7854-6229-4bc1-8d94-f6e2c4e5fa79"
```
2026-06-29: Updated `docs/ops-warden-routing-contract.md` with the canonical
whynot-design pointer payload and sent State Hub message
`765a03f0-0b1a-4da4-a244-04de468cadba` to `ops-warden`. Completion remains
waiting on ops-warden updating/confirming its own routing catalog so
`warden route find "npm publish whynot-design"` resolves here.
Coordinate with the ops-warden repo so `warden route find` points npm publish
credential needs at secrets-engine, returning the `secrets-engine route` pointer
rather than a value. This is a handoff/coordination task; the route catalog entry

View file

@ -4,7 +4,7 @@ type: workplan
title: "Provision a scoped warden-sign token lane (ops-warden / FLEX-WP-0007 T4)"
domain: infotech
repo: secrets-engine
status: proposed
status: active
owner: codex
topic_slug: custodian
created: "2026-06-29"
@ -59,11 +59,15 @@ OpenBao, so it also exercises parts of the engine the npm pilot did not.
```task
id: SECRETS-WP-0004-T01
status: todo
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
@ -81,11 +85,17 @@ Acceptance:
```task
id: SECRETS-WP-0004-T02
status: todo
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
@ -103,11 +113,16 @@ Acceptance:
```task
id: SECRETS-WP-0004-T03
status: todo
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.
Apply the policy + AppRole on `https://bao.coulomb.social` using a mode-0600
bootstrap token stored outside any repo. Idempotent re-apply.
@ -122,11 +137,17 @@ Acceptance:
```task
id: SECRETS-WP-0004-T04
status: todo
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.
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,
@ -143,11 +164,15 @@ Acceptance:
```task
id: SECRETS-WP-0004-T05
status: todo
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.