net-kingdom/sso-mfa/k8s/bounded-executor/T10-LANES-RUNBOOK.md
tegwick 634b3a41df
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
NK-WP-0056-T10: attended OpenBao setup and proof for the executor lanes
tools/service-binds/executor-lanes.py (bind-lane.py shape): under both
sha256-bound, approved, binding-confirmed CCRs (0058 write, 0059 journey) and
an attended platform-admin, apply both policies, set cas_required on the
svc-authelia key, create the standing journey-read role, refuse if the
window-scoped write role exists, prove the agent fence; verify proves the
journey token reads only its path (<=15m) and denies wrong SA, wrong audience
and write-role login. Value-free receipts. 12 tests on a fake OpenBao (real
helpers), in make bounded-executor-test. Founder runbook:
sso-mfa/k8s/bounded-executor/T10-LANES-RUNBOOK.md.

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

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 5502@bnt-lap001
Assistant-Session: 68b3b02f-5d0f-4e71-8421-796f62e50196
2026-10-31 19:15:46 +01:00

4.1 KiB

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)

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:

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)

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.