ops-mason/workplans/MASON-WP-0009-keycape-secrets-engine-openbao-client-custody.md
tegwick 401616bb0b MASON-WP-0009-T05: lane packaged as CCR-2026-0038, waits on founder apply
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
2026-10-09 00:33:51 +02:00

149 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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: wait
blocked_on: human
blocking_reason: "Founder applies CCR-2026-0038 (railiance-platform 0b2e7dd: mount auth/keycape-services, role secrets-engine-openbao, policy secrets-engine-login-self); then SECRETS-WP-0012-T03 login proof; then checks 1-3 and 6, invariant (ii) (expect deny on both guarded paths), pointer-only route."
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.