railiance-platform/workplans/RPF-WP-0069-bounded-executor-lanes.md
codex 92c7c375ba
All checks were successful
CCR intake gate / gate (push) Successful in 12s
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 3s
RPF-WP-0069: State Hub id write-back for T10
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 523928@bnt-lap001
Assistant-Session: 6c737afb-9c14-4152-9f02-477214b9c350
2026-11-04 02:01:21 +01:00

296 lines
14 KiB
Markdown

---
id: RPF-WP-0069
type: workplan
title: "Bounded executor lanes: write-next-version type, journey read and audit sender (NK-WP-0056)"
domain: financials
repo: railiance-platform
status: active
flavor: implementation
owner: claude
topic_slug: railiance
created: "2026-10-31"
updated: "2026-11-04"
related:
- NK-WP-0056
- NK-WP-0040
- RPF-WP-0067
state_hub_workstream_id: "6eb39172-babd-57d1-8a3b-f23c41347c22"
---
# RPF-WP-0069 — Bounded executor lanes (NK-WP-0056-T02 owner answer)
Receiving workplan for NetKingdom's owner request (State Hub message
`9d08288d-e866-4e1c-9c0b-f1cc0968bd4d`; net-kingdom
`docs/proposals/2026-10-31-nk56-t02-owner-requests.md`). Owner answer:
`docs/credential-lane-designs/bounded-executor.md`. No live, cluster or OpenBao action is
part of T01; every CCR stays `proposed` until its approvers act.
## Answer the request and add the write-next-version request type
```task
id: RPF-WP-0069-T01
status: done
priority: high
state_hub_task_id: "27432a77-e111-5aa9-9c23-34fb4c9a2984"
```
Answer doc written; new contract-only request type `workload-kv-write-next-version`
(`scripts/workload_kv_write_next_version.py`, `tests/test_workload_kv_write_next_version.py`,
dispatch in `scripts/credential-change.py`); CCR-2026-0058 drafted `proposed` with policy artifact
`openbao/policies/net-kingdom-bind-executor-svc-authelia-write.hcl`.
## Review CCR-2026-0058 (founder gate)
```task
id: RPF-WP-0069-T02
status: done
priority: high
needs_human: true
decision_id: c29c6eda-fa13-4d53-8293-17261eb437c1
blocked_on: human
blocking_reason: "Founder approval of CCR-2026-0058 and choice of standing or window-scoped write role (hub decision c29c6eda)"
state_hub_task_id: "3d4c818e-0c5f-5a14-9735-8056ff9fc7c3"
```
platform-owner and net-kingdom-owner approve or change CCR-2026-0058. The founder chooses
standing or window-scoped write role (recommendation: standing for the pilot). Binding is
confirmed only after `sso/nk-bind-executor` exists from the reviewed rapp-* package.
## Attended setup and verification of CCR-2026-0058
```task
id: RPF-WP-0069-T03
status: wait
priority: high
depends_on: [RPF-WP-0069-T02]
blocked_on: dependency
blocking_reason: "Per-window role creation, run receipts and deletion happen in the first founder-admitted executor run (NK-WP-0056-T06)"
state_hub_task_id: "6b456804-c408-53bf-8e1d-49723108fca6"
```
After T02: an attended platform-admin (aal2) session sets `cas_required` on the svc-authelia key,
re-checks the coding-agent fence, applies policy and role, and records value-free positive and
negative receipts. This needs an owner setup script modelled on net-kingdom `bind-lane.py`
setup/verify; write it once approval exists. The founder runs it.
2026-11-03 status: the setup half is done. The owner script is net-kingdom
`tools/service-binds/executor-lanes.py`, not a new script here. On 2026-10-31 the founder
ran it: the CCR-2026-0058 policy was applied, `cas_required` was set on the svc-authelia key,
and the coding-agent fence was re-checked (CCR-2026-0058 evidence, net-kingdom `ef6284c`).
Under the window-scoped decision (c29c6eda), no write role exists between runs. What remains
is the per-window part: create the role for an admitted window, record positive and negative
receipts, and delete the role after the run's receipt. That happens in the first admitted run,
NK-WP-0056-T06, which is still `todo` and depends on T15, T16 and T19 on the net-kingdom side.
## Journey-secret read lane for the executor (NK-WP-0056-T10)
```task
id: RPF-WP-0069-T04
status: done
priority: medium
state_hub_task_id: "5615be47-2b25-5f7d-a1c2-d4391b1377d0"
```
Draft a `workload-kv-read` CCR (native login, data read only, 15m) for
`platform/workloads/net-kingdom/synthetic-journey/syn-journey`, stating that it widens
CCR-2026-0057's `runtime_access: false`. Waits for T10 scheduling and the ServiceAccount.
**2026-10-31, drafted** at the founder's request (net-kingdom session):
- `CCR-2026-0059-net-kingdom-bind-executor-syn-journey-read.yaml` and the policy
`openbao/policies/net-kingdom-bind-executor-syn-journey-read.hcl`: read on the data path, plus
`lookup-self` and `revoke-self`.
- Role `net-kingdom-bind-executor-syn-journey-read`: `sso/nk-bind-executor`, audience `openbao`, 15m, exactly one
policy. It is separate from the CCR-2026-0058 write role.
- `supersedes_boundary` names the CCR-2026-0057 change.
- `lifecycle.role_window` proposes a standing reader (founder decides; window-scoped is the alternative).
- `bound_claims_confirmed: false` until the ServiceAccount exists. Validates with only that warning. The
pre-existing failures (CCR-2026-0035 and 2 tests) are unrelated.
**Done 2026-10-31.**
- Approved by the founder (`831a0f9`). The binding was confirmed after the rapp deploy (`b4bafb0`).
- The founder ran net-kingdom `tools/service-binds/executor-lanes.py`:
- `setup`: the policy and standing role were applied; the CCR-2026-0058 policy and `cas_required` too.
- `verify`: exact policy, lease of at most 15m, reads only its path, and the negatives held.
- CCR-2026-0059 is `applied`. It becomes `verified` after the first journey run through the role (NK-WP-0056-T10).
- Finding: platform-admin has no `patch` on `platform/*`. KV metadata changes therefore use a write that names only the
changed field.
## Executor audit-core sender (NK-WP-0040)
```task
id: RPF-WP-0069-T05
status: wait
priority: medium
blocked_on: human
blocking_reason: "Founder approvals of CCR-2026-0063 (platform-owner, audit-core-owner, net-kingdom-owner), then the go-live runbook (T10)"
state_hub_task_id: "5c582aef-ee9d-56ab-a4eb-2019933f00ac"
```
After audit-core admits the sender and names it, draft a `workload-kv-read` CCR in the
CCR-2026-0021/0022 shape: custody `platform/workloads/net-kingdom/bounded-executor/audit-sender`,
ESO into `sso/nk-bind-executor-audit`, ClusterSecretStore restricted to `sso`.
2026-11-03: audit-core admitted the sender in AUDIT-WP-0018-T02 as `nk-bounded-executor`:
source `net-kingdom.bounded-executor`, tenants `[platform]`, write only, `load-bearing`,
`secret_policy: reject`, closing class `started -> receipt` within 7200 s.
**CCR-2026-0063** is drafted as `proposed`. It validates, with only the expected
unconfirmed-binding warning, and its policy file matches the generated policy.
- Policy `openbao/policies/workload-kv-read-nk-bind-executor-audit.hcl`: data read on the
exact path only.
- Role `external-secrets-nk-bind-executor-audit`: `external-secrets/external-secrets`.
- Coding-agent deny on the data and metadata paths in `agent-high-risk-boundary.hcl`. This is a
source change; it is applied in the attended session.
- `secret_policy` follows audit-core's `reject`, not the `redact` in our 2026-10-31 answer.
- The ClusterSecretStore and ExternalSecret belong in the rapp-* package, as for
CCR-2026-0053.
Open for the net-kingdom-owner review: NK-WP-0056-T15 prefers an OpenBao read role over an
ESO Secret, while audit-core and our answer specify ESO. The CCR records this. Approval,
binding confirmation and the attended seed follow, after audit-core's founder-run rollout and
the executor's 202 fix.
2026-11-04: NetKingdom answered the open question: ESO as drafted (recorded as a review comment, not
as the net-kingdom-owner approval, which is the founder's). Drafting fixes:
- Delivery target aligned with the consumer: `sso/bounded-executor-tokens`, key `audit-core`, which the
rapp run Job already mounts (was `sso/nk-bind-executor-audit`/`audit-token`). The platform carries the
store and ExternalSecret in `manifests/nk-bind-executor-eso.yaml`, as for CCR-2026-0021/0022/0047.
- Reader role brought to the CCR-2026-0033/0041/0060 shape: audience `openbao`, explicit max TTL 15m,
no default policy, token self-lifecycle (policy file regenerated).
- One seeder: `custody_procedure` names audit-core's `scripts/attended-seed-nk-bounded-executor-sender.sh`
(CAS 0 custody, registry CAS merge, receiver reload and probe). railiance-platform adds only the fence
and the verify. audit-core asked to align its `sso` Secret name and key.
## LLDAP credential custody for the executor
```task
id: RPF-WP-0069-T06
status: cancel
priority: medium
needs_human: true
decision_id: 3d0c8f86-7b9c-456b-8951-5ae889829118
blocked_on: human
blocking_reason: "Founder chooses bind self-rotation (no account needed) or a lldap_password_manager account"
state_hub_task_id: "1456b467-f7c9-529d-9f3e-39404aaa36c6"
```
After secrets-engine answers the lane shape for the executor's LLDAP credential (its Q2),
draft the custody CCR here.
## Founder decisions 2026-10-31
Approved as `ready`. CCR-2026-0058 amended to a window-scoped role (created per admitted run, deleted after the
receipt; hub decision c29c6eda) and approved by platform-owner and net-kingdom-owner. T06 is cancelled: the bind
rotates its own password (hub decision 3d0c8f86), so the executor needs no LLDAP custody lane.
## Approve tool refuses the second approval for workload-kv-write-next-version
```task
id: RPF-WP-0069-T07
status: done
priority: medium
state_hub_task_id: "b458e369-73b4-515e-ae01-e8afc0dd35eb"
```
`credential-change.py approve` sets `status: approved` after the first reviewer; for this request type, validation
then requires every role approval, so the second `approve` is refused before it can record itself (CCR-2026-0058's
net-kingdom-owner approval was recorded by hand in the tool's format). Make validation accept an `approved` request
that is still collecting role approvals, or have `approve` set `approved` only once all required roles are present,
with a test.
Done 2026-11-03 (second option): `append_decision` records every approval, but sets `approved` only when the
request type's validator reports no `explicit role approval missing` error. Until then the CCR keeps its prior
status and `approve` prints the roles still awaited. The State Hub decision sync uses the same path. Lanes without
role gates are unchanged. `validate_ccr_data` validates in memory. Tests:
`test_role_gated_approval_stays_open_until_every_required_role_approves` and
`test_approval_by_unlisted_reviewer_does_not_complete_role_gate` (CCR-2026-0058 copy). The guide in
`docs/credential-change-approval.md` is updated. Three unrelated `test_credential_change.py` failures predate this
change (CCR drift).
## Broker admits oidc-service-client@0.2 for mint-secret
```task
id: RPF-WP-0069-T08
status: done
priority: high
state_hub_task_id: "ca12e6d4-aac1-56d1-95c0-a0b16a1745a8"
```
Review R1 of `docs/credential-lane-designs/oidc-service-client-review.md`: the create-only grant
(CCR-2026-0040/0043) already covers `platform/workloads/keycape/<client_id>`, but the broker
`scripts/keycape_client_secret_generate.py` admitted only `oidc-browser-relying-party@1.1` and required
`parameters.client_type == confidential`. The founder acknowledged `oidc-service-client` 0.2 on 2026-11-01 (memo
`nk-wp-0056-t14-oidc-service-client-r2`, hub decision `f8044f81`, net-kingdom `9ce0d60`), which meets the
RPF-WP-0060-T01 rule.
Done 2026-11-01:
- `ACKNOWLEDGED_TYPES` pins `oidc-service-client@0.2` (type sha256 `cd238693...`).
- `PARAMETER_PINS` is keyed by the exact type reference (`dda3bd19...` for 0.2), so two types sharing a version
never share a pin.
- Confidentiality is per type (`CONFIDENTIALITY`). Browser 1.1 still requires `client_type: confidential`. For the
service type it is derived from the authenticated type bytes: no `client_type` parameter and an unconditional
`client-secret-path`. A service case that carries `client_type` is refused (`case_client_type_not_admitted`).
- Browser behaviour is unchanged. Create-only is unchanged: an existing path or a lost CAS race exits 3 and is
never touched.
- Tests (`tests/test_keycape_client_secret_generate.py`, `ServiceClientGenerate`):
- the case generates once at the case path;
- an existing path is refused;
- dry run and a lost CAS race;
- confidentiality comes from the type;
- before any bao call, everything the pinned validator refuses is refused: the subject prefix, a lifetime over
15m, `openid`, the tenant form, the namespace and ServiceAccount patterns, an `issuer` override, unknown
parameters, missing required parameters, and a missing acceptance;
- only 0.2 is admitted;
- a drifted or proposed type, a wrong parameter pin, and a type that is not confidential by construction all
fail closed;
- the pins match the source.
The first case's custody CCRs (CCR-2026-0060/0061) were checked against the acknowledged 0.2 materialization
and now reference it. Activation stays gated on case acceptance, approval and binding confirmation (T09).
## Approve and apply the first service-client case's readers (CCR-2026-0060/0061)
```task
id: RPF-WP-0069-T09
status: wait
priority: medium
state_hub_task_id: "d9838702-3091-5e3c-858f-91208b5537d3"
```
Waits for net-kingdom's acceptance of case `nk-bind-executor-approval` and the attended mint
(`keycape-client-secret-generate`, T08). Then:
1. platform-owner (and net-kingdom-owner for 0061) approve;
2. confirm the bindings: `external-secrets/external-secrets` for 0060, `sso/nk-bind-executor` (uid bd15569c) for
0061;
3. the delegated applier or an attended platform-admin applies, with value-free positive and negative receipts.
2026-11-04: CCR-2026-0060/0061 checked against the type 0.2 rendering (net-kingdom
`python3 -m pytest security-case-types` 36 pass, including the CCR name comparison) and each other.
CCR-2026-0060 gained its `delivery` block (store `openbao-keycape-nk-bind-executor-approval-issuer`, rendered
from the platform template); both name the coding-agent fence step. The source boundary carries the
KeyCape path deny. Founder sequence: T10.
## Bounded executor credential go-live runbook
```task
id: RPF-WP-0069-T10
status: wait
priority: high
needs_human: true
blocked_on: human
blocking_reason: "Founder runs docs/credential-lane-designs/nk-bind-executor-go-live.md; needs case nk-bind-executor-approval materialized with acceptance (net-kingdom) and audit-core ingress/ConfigMap (audit-core steps 1-2)"
state_hub_task_id: "c61c4352-1622-5077-beec-9395f0e85029"
```
Runbook `docs/credential-lane-designs/nk-bind-executor-go-live.md`: approvals and binding confirmations,
coding-agent fence (`scripts/nk_bind_executor_custody.py fence`), delegated apply of CCR-2026-0060/0061/0063,
audit-core's sender seed, broker mint of the KeyCape client secret (CAS 0, silent, receipt), ESO apply of
`manifests/nk-bind-executor-eso.yaml`, and `nk_bind_executor_custody.py verify` (metadata, capabilities,
logins and hashes only; tests `tests/test_nk_bind_executor_custody.py`, synthetic fixtures). KeyCape's
bind-env and register-client (net-kingdom) follow only after the KeyCape ExternalSecret is Ready.