Four owner threads are each blocked on a fact only an authenticated read can establish: whether the legacy whynot-design npm path still exists, which field backs the authoritative lane, whether the two KeyCape approval policies match repo source after an activation that recorded policy_applied false, which netkingdom bound group claims already exist as input to CCR-2026-0019, and which fields the governed backup lane carries. Adds scripts/openbao_open_questions_session.py, which contains no mutating bao verb and emits only a mode-0600 metadata receipt, plus the run-book in docs/openbao-open-questions-session.md. Field-name resolution is a data read, so the runner returns sorted key names and no value reaches argv, disk or the receipt; that caveat is stated rather than glossed. Not run. The rapp-qonto rotation and the RPF-WP-0029 provider invalidation are explicitly out of scope. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WLUjpv3ssxNRAEPPgLFnEB Assistant: claude-code Assistant-Model: opus Assistant-Process: 1275505@bnt-lap001 Assistant-Session: 97265baa-f08f-4032-b290-a1e2965a69c5
103 lines
6 KiB
Markdown
103 lines
6 KiB
Markdown
# Attended OpenBao session — four open custody questions
|
|
|
|
One founder-attended session that settles the questions currently blocking four
|
|
owner threads. Everything in it is read-only against OpenBao. It provisions
|
|
nothing, approves nothing, and rotates nothing.
|
|
|
|
Prepared 2026-09-09 under RPF-WP-0035. Not yet run.
|
|
|
|
## Why a session rather than a reply
|
|
|
|
Four owner threads are each blocked on a fact that only an authenticated read can
|
|
establish, and each has been answered so far with "I will not guess":
|
|
|
|
| Question | Thread | What is undecidable from repo source |
|
|
| --- | --- | --- |
|
|
| Q1 | secrets-engine `546403e4` | Whether the legacy path `secret/coulomb/whynot-design/npm/publish` still exists and holds a real token |
|
|
| Q2 | secrets-engine `546403e4` | Which field backs the authoritative npm lane. My CCR says `NPM_AUTH_TOKEN`; secrets-engine says `npm_token`. Field names are not visible in KV v2 metadata |
|
|
| Q3 | internal | The 2026-09-09 activation receipt records `policy_applied: false` for both KeyCape approval lanes while `role_applied: true`. Reads verified, so the policies must exist — but existence and repo agreement were never confirmed |
|
|
| Q4 | CCR-2026-0019 | Which netkingdom OIDC roles and bound group claims already exist, as input to the operator group claim that lane is missing |
|
|
| Q5 | risk-nexus `ee702ac9` | Which fields the governed backup lane actually carries, as RPF-WP-0029-T02 context |
|
|
|
|
## Authority and containment
|
|
|
|
Authority is the governed `openbao-platform-admin-login` lane: `founder_required`,
|
|
attended OIDC through `bao login -method=oidc -path=netkingdom role=platform-admin`.
|
|
The owner command is never run directly.
|
|
|
|
```sh
|
|
scripts/openbao-attended-exec.py -- \
|
|
/usr/bin/python3 /home/worsch/railiance-platform/scripts/openbao_open_questions_session.py \
|
|
--receipt /tmp/<new-unique-name>.json
|
|
```
|
|
|
|
`scripts/openbao-attended-exec.py` supplies the WSL browser launcher and then
|
|
`exec`s into `warden access openbao-platform-admin-login --exec`, so Warden keeps
|
|
the envelope: it captures both streams, owns the temporary token helper and
|
|
self-revokes when the command returns. Use a receipt path that does not exist —
|
|
the writer opens it `O_EXCL` at mode 0600 and refuses to overwrite.
|
|
|
|
The runner prints nothing. Its entire output is the receipt.
|
|
|
|
## What the runner reads, and the one honest caveat
|
|
|
|
| Step | Call | Emitted |
|
|
| --- | --- | --- |
|
|
| Q1 | `secrets list`, then `kv metadata get` on the legacy path if the mount exists | mount present, path present, current version, created/updated time |
|
|
| Q2 | `kv get` on `platform/workloads/coulomb/whynot-design/npm-publish` | **sorted field names only**, plus KV version |
|
|
| Q3 | `policy read` for both KeyCape approval policies | present, matches-repo-source, sha256 of each normalized text |
|
|
| Q4 | `list auth/netkingdom/role`, then `read` each | role names, bound claims, groups/user claim, token policies, TTL |
|
|
| Q5 | `kv get` on `platform/workloads/railiance/backup/offsite-lane` | **sorted field names only**, plus KV version |
|
|
|
|
**The caveat, stated plainly:** Q2 and Q5 are data reads. Field names cannot be
|
|
obtained from KV v2 metadata, so the value transits the runner's memory. It is
|
|
never printed, never passed on argv, never written to disk, and never placed in
|
|
the receipt — `field_names()` returns key names and the values go out of scope
|
|
with the function. If that is not acceptable for the backup lane in particular,
|
|
drop Q5: it is context for RISK-F-0010, not a dependency of it.
|
|
|
|
For Q5 the receipt records `predecessor_material_recorded: false`, and no value,
|
|
fingerprint, length or shape of any predecessor credential is captured — which is
|
|
the constraint risk-nexus set.
|
|
|
|
## What each answer unblocks
|
|
|
|
- **Q1 + Q2 → secrets-engine.** A pointer plus a field name closes their custody
|
|
question. If Q2 returns `npm_token`, my CCR-2026-0001 is wrong about the field
|
|
and I correct it; if it returns `NPM_AUTH_TOKEN`, their catalog entry is the one
|
|
that moves, as a reviewed lane change carrying its own approval. If Q1 finds a
|
|
populated legacy path, that is a stale duplicate holding a real token and
|
|
becomes its own disposition item — do not delete it inside this session.
|
|
- **Q3 → internal.** Either the policies match the repo, and the activation's
|
|
`policy_applied: false` meant "no change needed", or they drift and that is a
|
|
finding to fix under RPF-WP-0035 before anyone treats the verifier lanes as
|
|
clean.
|
|
- **Q4 → CCR-2026-0019.** Existing bound claims show what the estate already uses
|
|
for operator lanes. This is **input, not confirmation** — the authorized group
|
|
claim is NetKingdom's and KeyCape's to state, and the receipt says so in-line so
|
|
a later reader cannot mistake the listing for an approval.
|
|
- **Q5 → risk-nexus.** Confirms the governed lane is populated with the expected
|
|
field names, supporting the fail-closed argument already made on that thread.
|
|
|
|
## Explicitly out of scope
|
|
|
|
- **The rapp-qonto KeyCape client rotation** (ops-warden `c1aafba4`). It is a
|
|
two-custodian CAS write with a service restart and needs its own reviewed
|
|
request first. Do not fold it into a read-only session because the operator
|
|
happens to be authenticated.
|
|
- **Predecessor share invalidation** for RPF-WP-0029-T02. That is a provider-side
|
|
action in the Nextcloud UI, not an OpenBao operation, and it needs the provider
|
|
owner. It can share the same sitting, but it is a separate step with a separate
|
|
receipt.
|
|
- **Any write, seed, rotation or policy apply.** The runner contains no mutating
|
|
verb; if a question turns out to need one, it comes back as a request.
|
|
- **Client-side reads for the approval clients.** CCR-2026-0019/0020 remain
|
|
in_flight; this session does not advance them beyond Q4's input.
|
|
|
|
## After the session
|
|
|
|
1. Store the receipt under `docs/evidence/` with the run date, values absent.
|
|
2. Reply to secrets-engine (Q1/Q2), risk-nexus (Q5) and, if Q3 drifts, record the
|
|
finding against RPF-WP-0035.
|
|
3. If Q1 finds a populated legacy path, open a disposition item for it rather
|
|
than acting on it in the moment.
|