Also confirms the Forgejo ESO role is live as applied (WP-0010). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 327203@bnt-lap001 Assistant-Session: 55028ae3-4914-4bd1-8f5c-815f3527aef0
184 lines
8.2 KiB
Markdown
184 lines
8.2 KiB
Markdown
---
|
||
id: MASON-WP-0009
|
||
type: workplan
|
||
title: "Place the KeyCape secrets-engine-openbao client secret in OpenBao"
|
||
domain: infotech
|
||
repo: ops-mason
|
||
status: blocked
|
||
flavor: planning
|
||
owner: claude
|
||
topic_slug: netkingdom
|
||
created: "2026-10-06"
|
||
updated: "2026-10-07"
|
||
state_hub_workstream_id: "d9be08f5-a0f5-5cd1-8f87-0a6868661d77"
|
||
---
|
||
|
||
# MASON-WP-0009 — Place the KeyCape `secrets-engine-openbao` client secret in OpenBao
|
||
|
||
## Goal
|
||
|
||
Founder direction 2026-10-06: the client secret lives in OpenBao and ops-mason
|
||
decides where and how. Plan: `plans/keycape-secrets-engine-openbao-client-custody.md`
|
||
(`status: reviewed`). Location `platform/workloads/keycape/secrets-engine-openbao`
|
||
field `CLIENT_SECRET` (KV v2, `cas_required`, `max_versions=2`). Issuer reads it
|
||
through the existing sso-only ESO/Kubernetes reader. secrets-engine reads it in
|
||
memory per command through a new attended operator OIDC role (5m, 4 uses,
|
||
revoke-self). There is no consumer copy at rest. The design supersedes
|
||
secrets-engine D1–D4.
|
||
|
||
## Boundaries
|
||
|
||
- ops-mason designs, reviews and verifies (capabilities only) and proposes the
|
||
pointer-only route. It builds nothing here (no OIDC writer; MASON-IN-0004).
|
||
- railiance-platform applies all objects and owns generation/write via its CCR.
|
||
- secrets-engine owns the in-memory provider. KeyCape/NetKingdom own the
|
||
registration, the claim and the restart.
|
||
- No value enters Git, State Hub, logs or agent context.
|
||
|
||
## Design and review the lane
|
||
|
||
```task
|
||
id: MASON-WP-0009-T01
|
||
status: done
|
||
priority: high
|
||
state_hub_task_id: "67e6b80b-3d21-5d19-80e9-23afb2453d0a"
|
||
```
|
||
|
||
Plan written and reviewed from source state. The live `bao` survey is
|
||
deferred to T04 (no bao access in this task).
|
||
|
||
## Founder approval
|
||
|
||
```task
|
||
id: MASON-WP-0009-T02
|
||
status: done
|
||
priority: high
|
||
state_hub_task_id: "4329bcd1-d42f-56a3-92cb-63b36d79549e"
|
||
```
|
||
|
||
2026-10-08 (inbox sweep): given and acted on. key-cape reported 2026-10-07
|
||
(message `dc8b5d3b`) that the founder applied CCR-2026-0033 (amended under
|
||
decision `1fdd993b` with `token_self_lifecycle`) and CCR-2026-0034; the custody
|
||
location decision is `2ab717e1`; the client was registered under live go
|
||
`caafe4be`.
|
||
|
||
## Owner changes delivered
|
||
|
||
```task
|
||
id: MASON-WP-0009-T03
|
||
status: done
|
||
priority: high
|
||
state_hub_task_id: "f59fae58-397a-5bf5-9d1d-a33dc4aaa2ac"
|
||
```
|
||
|
||
2026-10-08 (inbox sweep): all three owners delivered. railiance-platform
|
||
revised CCR-2026-0033 (`4a284f0`, message `7e96e835`); secrets-engine replaced
|
||
the consumer file with an in-memory OpenBao read (`b8094f7`, message
|
||
`c84fb5ba`); key-cape confirmed `groups` and the `aal2` assurance binding
|
||
(`7d96ee4`, message `71a31d0d`). Live result (key-cape `e0b5fae`, KEY-WP-0037
|
||
finished 2026-10-07): ESO `sso/keycape-secrets-engine-openbao-client` synced,
|
||
verify-client 10/10 with excess scope and wrong secret refused, founder
|
||
operator OIDC login (net-kingdom-admins, aal2) and revoke-self worked.
|
||
Evidence: key-cape `docs/evidence/2026-10-07-secrets-engine-openbao-issuance.json`.
|
||
Only T05 (service-JWT lane proof, RPF-WP-0035-T02) remains.
|
||
|
||
## Verify and propose the route
|
||
|
||
```task
|
||
id: MASON-WP-0009-T04
|
||
status: done
|
||
priority: medium
|
||
state_hub_task_id: "01f55a4d-06de-5d48-a3db-a0746dcf9892"
|
||
```
|
||
|
||
After platform applies the objects: a live metadata-only survey and the
|
||
plan's six verification checks (capabilities and metadata only). Then a
|
||
pointer-only ops-warden entry for the operator lane (`resolvable: false`
|
||
until the checks pass).
|
||
|
||
Note (2026-10-07, MASON-IN-0004): the capability verification runs under the
|
||
read-only `ops-mason-survey` grant, which replaces `ops-mason-build`. Installing
|
||
that policy is a founder act (AGENTS.md, "Installing the survey policy");
|
||
ops-mason cannot install or widen it.
|
||
|
||
Done 2026-10-07 under grant `claude-MASON-WP-0009-T04` (`ops-mason-survey`,
|
||
revoked and shredded after use). Evidence, value-free:
|
||
`docs/evidence/2026-10-07-keycape-secrets-engine-openbao-capabilities.json`.
|
||
All five capability checks pass: both lane policies match the platform repo
|
||
files; both roles match CCR-2026-0033/0034 (retired redirect noted); KV metadata
|
||
is v1, `cas_required`, `max_versions=2`, `delete_version_after=0s`, custom
|
||
metadata as in plan 3.1; only the two lane policies plus `platform-admin`/root
|
||
reach the data path, no `auth/jwt` (or `keycape-services`) mount exists, the
|
||
ESO reader is on Kubernetes auth; the grant itself is `deny` on the data path
|
||
and read-only on `sys/policies/acl/*`. Not permitted by the survey grant:
|
||
`auth/keycape/role`. Owner observations (retired `ops-mason-build` still
|
||
installed; `secrets-engine-prod` can author `se-prod-*` policies; this path is
|
||
missing from `agent-high-risk-boundary`) are in the evidence file. Plan checks
|
||
1-3 and 6 need live lane tokens and the route proposal is still owed: T05.
|
||
|
||
Side finding, fixed: `scripts/bao-session.sh grant` reported "policy does not
|
||
exist yet" whenever `bao policy read` failed, including when the founder's
|
||
`~/.vault-token` session was expired or unauthorised. It now says "cannot read
|
||
(session expired or not permitted)" unless bao answers "No policy named"
|
||
(`tests/test_bao_session.py`).
|
||
|
||
## Live lane proof and pointer route
|
||
|
||
```task
|
||
id: MASON-WP-0009-T05
|
||
status: progress
|
||
blocked_on: human
|
||
blocking_reason: "ops-mason checks complete (policies, roles, invariant ii, login proof). Owner-run: live operator/ESO token capability checks and a non-member refusal; ops-warden activates the proposed pointer."
|
||
priority: medium
|
||
state_hub_task_id: "1b1a0566-add7-59c1-94b0-6bb81d2d1537"
|
||
```
|
||
|
||
Once the service-JWT lane exists: re-run invariant (ii) against its policy,
|
||
collect owner-run evidence for checks 1-3 and 6 (operator and ESO token
|
||
capabilities, non-member refusal, a secrets-engine `service-jwt` run), then
|
||
propose the pointer-only ops-warden entry for the operator lane
|
||
(`resolvable: false` until those pass).
|
||
|
||
2026-10-09: railiance-platform packaged the lane as CCR-2026-0038 (proposed,
|
||
`0b2e7dd`, message `029a6ee2`): isolated JWT mount `auth/keycape-services`,
|
||
role `secrets-engine-openbao` (KeyCape registration claims, 5m, 8 uses, no
|
||
default policy), policy `secrets-engine-login-self` (self endpoints only, with
|
||
explicit deny on `platform/data/` and `platform/metadata/` for
|
||
`workloads/keycape/secrets-engine-openbao`, so invariant (ii) holds by
|
||
construction). New `service-jwt-login` applier with read-back; 8 tests. Waits
|
||
on the founder's approve, confirm-binding and delegated apply.
|
||
|
||
2026-10-09: already applied. railiance-platform `1b36e14` records the founder's
|
||
approval, binding confirmation and delegated apply at 2026-10-08T22:42Z, with a
|
||
matching value-free readback (evidence in the CCR). RPF-WP-0035-T02 now waits
|
||
only on the login proof (SECRETS-WP-0012-T03).
|
||
|
||
2026-10-10: check 6 passed. The founder ran `secrets-engine service-auth
|
||
probe-openbao`: ok, auth provider service-jwt, secret source
|
||
openbao-oidc-in-memory, both revoke-self true (secrets-engine evidence
|
||
`docs/evidence/2026-10-10-keycape-openbao-probe.json`, `a963a77`; message
|
||
`6ed92390`). SECRETS-WP-0012 is finished.
|
||
|
||
2026-10-10 (grant `claude-MASON-WP-0009-T05`, revoked): invariant (ii) holds:
|
||
live `secrets-engine-login-self` equals the railiance-platform file and carries
|
||
`deny` on both `platform/data/` and `platform/metadata/` for
|
||
`workloads/keycape/secrets-engine-openbao`; the ESO and operator reader
|
||
policies equal their files; mount `keycape-services/` is type jwt. Reading the
|
||
role was refused: `ops-mason-survey` did not cover `auth/keycape-services/role/*`.
|
||
Added to `policies/ops-mason-survey.hcl`; the founder reinstalls it (AGENTS.md
|
||
command), then the role check runs.
|
||
|
||
2026-10-10 15:45Z: founder reinstalled `ops-mason-survey`; the installed policy's
|
||
sha256 equals the repo file's (`c845bc79…`, receipt
|
||
`~/.local/state/railiance/receipts/ops-mason-survey.sha256`). Role check runs
|
||
under the next grant.
|
||
|
||
2026-10-10 (grant `claude-MASON-WP-0009-T05`, revoked): role
|
||
`auth/keycape-services/role/secrets-engine-openbao` equals railiance-platform
|
||
`openbao/auth/secrets-engine-jwt-role.json` on every field compared (jwt,
|
||
`sub`, audience `secrets-engine-openbao`, subject `service:secrets-engine`,
|
||
claims principal_type/roles/scope/tenant, policy `secrets-engine-login-self`
|
||
only, 5m, 8 uses, no default policy). ops-mason's checks are complete. Pointer
|
||
entry proposed to ops-warden as draft, non-resolvable (message `8ad8ed4e`).
|
||
Left owner-run: capability checks with live operator and ESO tokens and a
|
||
non-member refusal.
|