RPF-WP-0069: answer NK-WP-0056-T02; add workload-kv-write-next-version; CCR-2026-0058 (proposed)
All checks were successful
CCR intake gate / gate (push) Successful in 11s
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Owner answer for the bounded executor (hub 9d08288d): one Kubernetes role per
lane for sso/nk-bind-executor; new contract-only request type for a CAS
next-version write (no create, metadata or delete, 15m, agents fenced);
CCR-2026-0058 drafted as proposed, not approved; audit sender in the
CCR-2026-0021/0022 shape once audit-core admits it.

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

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 994874@bnt-lap001
Assistant-Session: 6017c416-d619-47eb-bd1a-f670a02d7d87
This commit is contained in:
codex 2026-10-31 14:21:35 +01:00
parent c5f9770c97
commit 8b57d270de
8 changed files with 553 additions and 0 deletions

View file

@ -0,0 +1,107 @@
# Bounded executor: OpenBao lanes and audit sender (owner answer, NK-WP-0056-T02)
Owner answer from railiance-platform to NetKingdom's request
(net-kingdom `docs/proposals/2026-10-31-nk56-t02-owner-requests.md` §railiance-platform;
State Hub message `9d08288d`). Basis: Bounded Execution Admission v0.1 (proposed) and its pilot
example `bind-rotation-svc-authelia.yaml`. Workplan: `workplans/RPF-WP-0069-bounded-executor-lanes.md`.
Everything here is source and proposals. No role, policy, Secret or KV value was created or read.
CCR-2026-0058 is `proposed`; approvals and the founder's choices below stay open.
## Q1. Kubernetes auth role for `sso/nk-bind-executor`: which request types?
**Answer: one role per lane, all bound to the one ServiceAccount, two request types.**
The existing `workload-kv-read` contract requires a role to carry exactly its own policy
(`scripts/credential-change.py` `validate_workload_kv_read`, "openbao.auth.policies must contain exactly
the policy used by the auth method"; applier check "must contain only openbao.policy_name"). We keep that
rule. The executor logs in once per lane with the same projected ServiceAccount token (audience
`openbao`); each token carries one policy and lives at most 15 minutes. A combined role would make every
lane's review depend on every other lane.
| Executor need | Request type | Status |
| --- | --- | --- |
| Write the next version of `platform/workloads/net-kingdom/directory-binds/svc-authelia` (CAS) and read it for checks/revert (T06) | `workload-kv-write-next-version` (**new**, `scripts/workload_kv_write_next_version.py`) | Type in source; CCR-2026-0058 `proposed` |
| Read `platform/workloads/net-kingdom/synthetic-journey/syn-journey` (`PASSWORD`, `TOTP_SEED`) for the journey (T10) | `workload-kv-read`, native workload login (`token_self_lifecycle: true`, `metadata_read: false`), as the native reader proof in CCR-2026-0053 | Not drafted; see below |
| LLDAP credential to set `svc-authelia`'s password | `workload-kv-read` of a new custody entry, after secrets-engine answers its Q2 | Not drafted |
| audit-core sender bearer (receipts) | `workload-kv-read` with ESO delivery, as CCR-2026-0021/0022 | Not drafted; see Q2 |
### The new type `workload-kv-write-next-version`
Prepared the way `attended-service-credential-delivery` was added: module
`scripts/workload_kv_write_next_version.py`, tests `tests/test_workload_kv_write_next_version.py`, dispatch in
`scripts/credential-change.py` (validate, plan, operator-commands, runbook). It is **contract-only**: there
is no delegated applier (it is not in `LANE_MODULES`). The attended platform-admin applies policy and role
from a reviewed commit, like CCR-2026-0052..0055.
The contract refuses anything wider than:
- one exact `platform/workloads/...` path on mount `platform`; no wildcard, no sibling;
- policy (generated by `policy_hcl`, artifact `openbao/policies/<policy>.hcl`):
`read` + `update` on `platform/data/<path>` only, `required_parameters = ["options"]`,
`allowed_parameters = {data, options}`; plus `lookup-self`/`revoke-self`. No `create` (a missing path is
refused, so the executor cannot mint new entries), no `metadata/`, `delete/`, `destroy/`, `undelete/`, list;
- key-level `cas_required = true`, set by the attended platform-admin at setup. The engine then refuses
every write that does not name the version it replaces; races and replays fail closed in OpenBao, not in
executor code. (`required_parameters = ["options"]` alone cannot force `options.cas`; the key setting does.)
- Kubernetes auth: one ServiceAccount, one namespace, audience `openbao`, `ttl`/`token_max_ttl`/
`token_explicit_max_ttl` = 15m, `token_no_default_policy: true`, exactly one policy;
- `access_frontdoor.resolvable: false`; `agent_fence.data_and_metadata_denied: true` (coding agents fenced);
- `admission` names the standard and executor identity; full `verification` and `lifecycle`; explicit
approval by every `review.required_approvers` role from `approved` onward.
Revert (`restore-kv` in the example) is a further next-version write of the prior value with CAS. Reading
an older version is a `read` on `data/<path>?version=N`, which the policy already grants; no extra
capability is needed.
**What the role does not do.** OpenBao does not evaluate the admission. The role is standing: a compromised
`nk-bind-executor` ServiceAccount can replace the svc-authelia bind (sign-in outage on Authelia's next
restart) but reach nothing else. The admission window, consume-once and plan digest are enforced by the
executor, approval-engine and access-engine. If that is not enough, the founder can choose a
window-scoped role instead (created by the attended platform-admin at the window start, removed after);
that removes the "unattended" property of T06 for the platform side. Recommendation: standing role for the
pilot, because the reachable damage is one read-only directory bind already covered by an attended
recovery path (CCR-2026-0053 `lifecycle.compromised`).
### Journey secrets (T10)
CCR-2026-0057 is `attended-service-credential-delivery` with `runtime_access: false`; its contract forbids
any role or policy on that path. A `workload-kv-read` request for the executor therefore changes
CCR-2026-0057's stated boundary. It must say so, cite CCR-2026-0057, and be approved by both
platform-owner and net-kingdom-owner. CCR-2026-0057's attended procedure stays valid. Shape: role
`net-kingdom-bind-executor-syn-journey-read`, policy `read` on the data path only, native login, 15m.
Draft it when T10 is scheduled and the ServiceAccount exists.
## Q2. Can the executor pod receive an ESO-projected audit-core sender bearer?
**Yes, with the CCR-2026-0021/0022 shape, once audit-core admits the sender.** The receipt is an event to
audit-core; per RPF-WP-0067-T01 the wire is `POST /v1/events` to
`http://audit-core.audit-core.svc.cluster.local:8080`, with a per-sender bearer from the registry at
`platform/workloads/audit-core/senders`. `Idempotency-Key` is the envelope `id` and `correlation_id` is the
`run_id`. The envelope `source` equals the sender name.
Shape (as `docs/credential-lane-designs/factory-audit-senders-review.md`):
- custody `platform/workloads/net-kingdom/bounded-executor/audit-sender` (`AUDIT_TOKEN`), generated CAS=0 in
the attended platform process and merged into the registry as one exact sender (proposed name
`nk-bounded-executor`, `tenant:platform`, write true, read false, `evidence_kind: load-bearing`,
`secret_policy: redact`); no existing sender changes;
- exact-path policy, Kubernetes role for `external-secrets/external-secrets` only, ClusterSecretStore
restricted to namespace `sso`; ExternalSecret into `sso/nk-bind-executor-audit` key `audit-token`,
mounted as a file in the executor pod;
- coding-agent fence on the new data and metadata paths.
The bearer lets the executor append its own receipts only. It is not an OpenBao identity. The ESO
manifests belong in the `rapp-*` package, as in CCR-2026-0053, which points to net-kingdom
`bind-eso.yaml`. Prerequisites: audit-core says yes to its Q1 (net-kingdom request §audit-core) and
names the sender. Then a `workload-kv-read` CCR follows here.
## Open items for the founder and other owners
1. Review and approve or change CCR-2026-0058 (platform-owner, net-kingdom-owner). It stays `proposed`.
2. Standing vs window-scoped write role (recommendation: standing for the pilot).
3. Accept that a journey-read CCR widens CCR-2026-0057's `runtime_access: false`.
4. secrets-engine: the LLDAP credential lane shape (its Q2) before a custody CCR can be drafted.
5. audit-core: sender admission and name, before the sender CCR.
6. railiance-apps / rapp package: the ServiceAccount `sso/nk-bind-executor` must exist before
`bound_claims_confirmed` can be set.