RPF-WP-0066: OpenBao durable audit shipping, scheduled snapshots, live conformance (NK-WP-0055-T11/T12)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4515@bnt-lap001
Assistant-Session: 0bf96127-6e04-41be-bfda-d11717c3f354
This commit is contained in:
codex 2026-10-27 22:31:57 +01:00
parent 4583b22fd6
commit 87a488cc66
3 changed files with 204 additions and 0 deletions

View file

@ -45,6 +45,7 @@
| workplan | RPF-WP-0063 | finished | — | workplans/RPF-WP-0063-wave2-resource-right-sizing.md |
| workplan | RPF-WP-0064 | active | — | workplans/RPF-WP-0064-isolated-original-openbao-restore.md |
| workplan | RPF-WP-0065 | proposed | — | workplans/RPF-WP-0065-netkingdom-role-claim-bindings.md |
| workplan | RPF-WP-0066 | proposed | — | workplans/RPF-WP-0066-openbao-durable-audit-snapshots-conformance.md |
| task | RPF-WP-ADHOC-2026-10-10-T01 | done | — | workplans/ADHOC-2026-10-10.md |
| task | RPF-WP-ADHOC-2026-10-11-T01 | done | — | workplans/ADHOC-2026-10-11.md |
| task | RPF-WP-ADHOC-2026-10-11-T02 | done | — | workplans/ADHOC-2026-10-11.md |
@ -208,6 +209,12 @@
| task | RPF-WP-0065-T03 | done | — | workplans/RPF-WP-0065-netkingdom-role-claim-bindings.md |
| task | RPF-WP-0065-T04 | wait | — | workplans/RPF-WP-0065-netkingdom-role-claim-bindings.md |
| task | RPF-WP-0065-T05 | wait | — | workplans/RPF-WP-0065-netkingdom-role-claim-bindings.md |
| task | RPF-WP-0066-T01 | todo | — | workplans/RPF-WP-0066-openbao-durable-audit-snapshots-conformance.md |
| task | RPF-WP-0066-T02 | wait | — | workplans/RPF-WP-0066-openbao-durable-audit-snapshots-conformance.md |
| task | RPF-WP-0066-T03 | todo | — | workplans/RPF-WP-0066-openbao-durable-audit-snapshots-conformance.md |
| task | RPF-WP-0066-T04 | wait | — | workplans/RPF-WP-0066-openbao-durable-audit-snapshots-conformance.md |
| task | RPF-WP-0066-T05 | wait | — | workplans/RPF-WP-0066-openbao-durable-audit-snapshots-conformance.md |
| task | RPF-WP-0066-T06 | todo | — | workplans/RPF-WP-0066-openbao-durable-audit-snapshots-conformance.md |
| intake | RPF-IN-0001 | closed | — | intakes/intakes.md |
| intake | RPF-IN-0002 | open | — | intakes/intakes.md |
| intake | RPF-IN-0003 | open | — | intakes/intakes.md |

View file

@ -71,6 +71,9 @@ priority: high
state_hub_task_id: "d64446fb-870b-5ae9-9628-f1fb9d06c5a4"
```
2026-10-27: the OpenBao Raft snapshot schedule slice is tracked as RPF-WP-0066-T05
for NetKingdom NK-WP-0055; this task keeps the cross-service scope.
2026-10-11: requalified after founder decision D2 (ArgoCD owns production) resolved — see the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md.
2026-10-11 dependency audit: D2 resolved the scheduling-role decision. The

View file

@ -0,0 +1,194 @@
---
id: RPF-WP-0066
type: workplan
title: "OpenBao durable audit shipping, scheduled Raft snapshots and live conformance receipt"
domain: financials
repo: railiance-platform
status: proposed
flavor: implementation
owner: claude
created: "2026-10-27"
updated: "2026-10-27"
related:
- NK-WP-0055
- RPF-WP-0036
- RPF-WP-0064
- AUDIT-WP-0013
- AUDIT-WP-0015
- ACTIVITY-WP-0042
---
# RPF-WP-0066 — OpenBao durable audit, scheduled snapshots, live conformance
Receiving workplan for NetKingdom NK-WP-0055-T11 (audit sink) and the OpenBao part of
NK-WP-0055-T12 (live conformance receipts). Source: net-kingdom
`docs/evidence/2026-10-27-production-readiness-ledger.md` sections 4 (OpenBao) and 9
(Audit sink).
## Evidence
- The declarative `audit "file" "file"` stanza in `helm/openbao-values.yaml` writes
`/openbao/audit/openbao-audit.log` on the audit PVC. `docs/openbao.md` states the PVC
"is not a durable audit sink". Durable shipping was deferred when RAIL-PL-WP-0002
closed, and no live workplan owned it until now.
- `make openbao-reboot-snapshot` is an attended Raft snapshot -> age -> verify -> offsite
path with a receipt. RPF-WP-0064-T07/T08 proved one isolated original restore. Neither
is a schedule. RPF-WP-0036-T03 owns recurring backup and restore evidence for all S3
data services and waits on ACTIVITY-WP-0042 (bounded scheduler).
- `make openbao-verify-authenticated` already runs non-mutating checks of audit devices,
`platform/`, and the `kubernetes/`, `netkingdom/`, `keycape/` auth mounts. It does not
compare the live state to `openbao/policies/` and does not write a dated receipt.
## Constraints
- Source preparation only. Every live step (Helm rollout, enabling an audit device,
installing a schedule, the drills) is founder-run, with a guarded helper and the exact
command, and keeps its own execution gate.
- Audit records leave OpenBao with its default HMAC-SHA256 hashing of secret-bearing
request and response fields. No `log_raw`, and no `hmac_accessor=false`. Any
`audit_non_hmac_*_keys` tuning on a mount needs a separate reviewed change. The shipper
never logs record bodies and never holds an OpenBao token.
- OpenBao blocks requests when every enabled audit device fails. The file device stays
enabled as the local, blocking device. Shipping must be asynchronous, so a sink
outage cannot stop OpenBao.
## Choose the OpenBao audit forwarding design
```task
id: RPF-WP-0066-T01
status: todo
priority: high
```
Compare the options and record the decision in `docs/openbao.md` (or an ADR if it
changes the platform boundary):
1. **File device plus a tailing sidecar shipper (preferred candidate).** A shipper such as
Vector or Fluent Bit in the `openbao` pod reads the PVC log, keeps a disk checkpoint,
maps records to the audit-core envelope and posts them to the audit-core ingest API
as a registered sender. It retries with backoff from the PVC backlog. The PVC is the
buffer; size it and set a rotation that cannot drop unshipped lines. Rotation would
use SIGHUP to reopen the log.
2. **Socket device to an in-cluster collector.** This has lower latency, but a socket
failure counts against the "all devices failed" rule. It is acceptable only as a
second, non-sole device, and its `fallback` semantics need checking.
3. **Separate durable store** (an encrypted object store with object lock). Use this only
if audit-core cannot accept OpenBao volume. It then needs its own retention and its
own restore drill.
**Done when:** one option is chosen with volume and backlog sizing, and its failure modes
are recorded: sink down, shipper down, PVC full, rotation.
## Agree the audit-core sender contract and the correlation id
```task
id: RPF-WP-0066-T02
status: wait
priority: high
blocked_on: message-from:audit-core
```
Needed from audit-core (AUDIT-WP-0013 sender admission):
- an OpenBao sender registration and its credential route (OpenBao-issued, no secret
in Git);
- an envelope mapping for OpenBao `request`/`response` records, with HMAC'd fields
passed as opaque;
- idempotency and dedup keys (OpenBao `request.id` plus record type);
- the expected volume and retention class;
- an acknowledgement and backpressure contract.
Correlation: the NetKingdom-owned cross-stream correlation id (NK-WP-0055-T11) has to
reach OpenBao requests. Set a request header such as `X-Correlation-Id`. If the
listener allows it, record it through the auth mount `audit_non_hmac_request_keys` /
`passthrough_request_headers` or the listener header settings. Otherwise derive it from
the OIDC `jti`/session claim in entity metadata. Verify which of these OpenBao records
unhashed without exposing a secret.
**Done when:** a written contract exists in both repos, and NetKingdom's correlation-id
definition is cited.
## Implement the shipper source and its tests
```task
id: RPF-WP-0066-T03
status: todo
priority: high
depends_on: [RPF-WP-0066-T01, RPF-WP-0066-T02]
```
Add the shipper configuration to `helm/openbao-values.yaml`, along with the checkpoint
volume, log rotation, and the mapping and redaction config. Test against synthetic
fixtures:
- records stay HMAC'd end to end;
- no token or accessor appears in the clear;
- dedup holds on replay;
- the backlog drains after a simulated sink outage;
- correlation-id propagation works.
Prepare a founder-run rollout helper with a post-rollout check: the audit-core record
count rises for a probe request carrying a known correlation id.
**Done when:** tests pass and the helper and its exact command are documented. The live
rollout is a separate attended step.
## Set retention and drill audit restore
```task
id: RPF-WP-0066-T04
status: wait
priority: medium
depends_on: [RPF-WP-0066-T03]
```
Record retention per store: the PVC (short, buffer only), audit-core (its retention
class), and any separate archive. The recurring audit-core restore drill belongs to
audit-core (NK-WP-0055-T11 / AUDIT-WP-0015-T01). This task supplies the OpenBao part:
after a restore, an OpenBao record found by correlation id and `request.id` verifies
against the hash chain. If option 3 is chosen in T01, this repo owns the full restore
drill of that store.
**Done when:** a dated restore receipt shows OpenBao records recovered and verified.
## Schedule OpenBao Raft snapshots
```task
id: RPF-WP-0066-T05
status: wait
priority: high
depends_on: [RPF-WP-0036-T03, ACTIVITY-WP-0042]
```
This is the OpenBao slice of RPF-WP-0036-T03, split out so NK-WP-0055 can track it.
Turn `scripts/openbao-reboot-snapshot.py` (snapshot -> age -> verify -> offsite ->
receipt) into an unattended, bounded operation run by the accepted scheduler
(ACTIVITY-WP-0042). It needs:
- a snapshot-only OpenBao policy, `sys/storage/raft/snapshot` read and nothing more;
- a scoped credential route;
- a cadence and expiry that RPF-WP-0036-T02's freshness signal can check;
- a stale or failed run that reaches a named operator.
A periodic isolated restore, reusing the RPF-WP-0064 isolated-restore path, is the
recurring proof. A dated snapshot alone does not pass.
**Done when:** the schedule is installed through the execution owner, and at least two
consecutive scheduled snapshot receipts and one scheduled isolated restore receipt exist.
## Record a dated live check of auth methods and mounts against committed policies
```task
id: RPF-WP-0066-T06
status: todo
priority: medium
```
Extend `make openbao-verify-authenticated`, or add a sibling read-only target, to emit a
dated, non-secret receipt. The receipt diffs `bao auth list`, `bao secrets list`,
`bao audit list` and `bao policy list`, plus per-policy content hashes, against
`openbao/policies/*.hcl` and the expected mounts list. It lists unexpected mounts,
missing mounts and policy drift. The founder runs it; the receipt is committed under
`docs/evidence/`.
**Done when:** one dated receipt is committed and cited in NK-WP-0055-T12.