# T10 runbook: executor standing objects and OpenBao lanes (founder-run) NK-WP-0056-T10. Three steps, about 15 minutes. Nothing here starts a Job or touches the svc-authelia value. The bind write role (CCR-2026-0058) is **not** created: it exists only inside an admitted window. | Step | Where | What changes | | --- | --- | --- | | 1 | `~/rapp-bounded-executor` | creates ServiceAccount `nk-bind-executor`, its Role and RoleBinding, and NetworkPolicy `bounded-executor` in `sso` | | 2 | `~/railiance-platform` | records `binding_confirmed` in CCR-2026-0058 and CCR-2026-0059 | | 3 | `~/net-kingdom` | OpenBao: both policies, `cas_required` on the svc-authelia key, the standing journey-read role, and proof | ## 1. Standing objects (rapp) ```bash cd ~/rapp-bounded-executor && git pull --ff-only K="kubectl --kubeconfig $HOME/.kube/config-railiance01" make server-dry-run KUBECTL="$K" # 4 objects "serverside-applied (server dry run)" make deploy KUBECTL="$K" # the same 4 objects, without "(server dry run)" make verify-live KUBECTL="$K" # {"role_matches_ceiling": true, "standing_objects_present": true, ...} ``` The pod runs nothing yet: no Job exists until `make run` under an admission. ## 2. Confirm the binding (railiance-platform) The CCRs bind `service_account_names: [nk-bind-executor]` in `sso`, audience `openbao`. Confirm that this ServiceAccount now exists, as declared: ```bash cd ~/railiance-platform && git pull --ff-only UID_SA=$($K -n sso get serviceaccount nk-bind-executor -o jsonpath='{.metadata.uid}'); echo "$UID_SA" for C in CCR-2026-0058 CCR-2026-0059; do scripts/credential-change.py confirm-binding "$C" --reviewer platform-owner --comment \ "Binding confirmed: ServiceAccount nk-bind-executor in namespace sso only (uid $UID_SA), audience openbao, from rapp-bounded-executor." done git status --short # exactly the two CCR files modified ``` ## 3. OpenBao lanes (attended platform-admin) ```bash cd ~/net-kingdom && git pull --ff-only bao login -method=oidc -path=netkingdom role=platform-admin # MFA; the tool fails closed without it W=$(sha256sum ~/railiance-platform/credential-change-requests/CCR-2026-0058-*.yaml | cut -d' ' -f1) J=$(sha256sum ~/railiance-platform/credential-change-requests/CCR-2026-0059-*.yaml | cut -d' ' -f1) E=docs/evidence/$(date +%F)-nk56-t10-executor-lanes; mkdir -p "$E" python3 tools/service-binds/executor-lanes.py setup --write-ccr-sha256 "$W" --journey-ccr-sha256 "$J" \ --receipt "$E/01-setup.json" # {"status": "lanes_prepared", "phase": "done"} python3 tools/service-binds/executor-lanes.py verify --write-ccr-sha256 "$W" --journey-ccr-sha256 "$J" \ --kubeconfig "$HOME/.kube/config-railiance01" --receipt "$E/02-verify.json" # {"status": "lanes_verified", ...} ``` `setup` is idempotent: it creates what is missing and refuses on any drift. It never changes the coding-agent fence, because CCR-2026-0053 and CCR-2026-0057 established it; it only proves the fence. Receipts hold no values. `verify` reads the journey entry into memory only to check its field names. If a step stops, the receipt's `phase` and `reason` say where: | `reason` | Meaning, next step | | --- | --- | | `write:ccr_digest` / `journey:ccr_digest` | the CCR changed after `W`/`J` were computed; compute them again | | `*:binding_unconfirmed` | step 2 not done (or not saved) | | `attended_platform_admin_required` | no `bao login` as platform-admin, or a root token | | `agent_fence_missing` | the boundary policy lacks a deny line for one of the two paths; stop and hand to claude-code | | `command_failed` in phase `cas_required` | platform-admin may not patch KV metadata; hand to claude-code | | `write_role_exists_outside_a_window` | someone created the window-scoped write role; delete it, or stop | | `*:policy_drift` | a policy of that name exists with other text; stop | | `negative_login_accepted` / `journey_capabilities` | the role is wider than approved; delete the journey role and stop | ## 4. Afterwards Tell claude-code. It commits the two CCRs and the receipts, moves CCR-2026-0059 on, and records T10 progress.