NK-WP-0058-T04 done: bx, four founder commands plus the approval
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s

bx ready / request / run / status (close for emergencies): inputs in a state file, receipts numbered
by the tool, every command safe to repeat and one value-free line. OpenBao steps run as silent
children of the warden platform-admin lane (executor-lanes.py --quiet); run closes the window in the
same child, also on error. Runbook sections 5-6 replaced; pilot-run.sh deleted. 134 tests.

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

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 943911@bnt-lap001
Assistant-Session: fc322940-1c8e-4bed-ab39-86cec99f23a0
This commit is contained in:
tegwick 2026-11-05 23:45:02 +01:00
parent a29d92ecda
commit 646ced3f9e
10 changed files with 577 additions and 120 deletions

View file

@ -18,8 +18,8 @@ Each step prints a value-free result. Paste it back, and claude-code verifies it
| 2 | Accept the case | State Hub decision | `security-cases/nk-bind-executor-approval.yaml` becomes `accepted` |
| 3 | Custody and audit sender | railiance-platform, audit-core | approve CCR-2026-0060, -0061, -0063; fence, policies, roles; audit seed; mint; ESO |
| 4 | KeyCape client | net-kingdom | bind the env var and register the client in one KeyCape restart |
| 5 | Admission | net-kingdom (claude-code) | `admissions/BEA-2026-0002.yaml` for the window you choose |
| 6 | The run | rapp, net-kingdom | request, approve at aal2, open the window, run, close the window, verify |
| 5 | Admission | net-kingdom (claude-code) | `admissions/BEA-YYYY-NNNN.yaml` for the window you choose |
| 6 | The run | net-kingdom `bx` | `ready`, `request`, approve at aal2, `run`, `status` |
## 1. Owner ingress (T16)
@ -115,84 +115,48 @@ per scope. The excess-scope refusal, the custody denials and the RBAC can-i deni
## 5. Admission (claude-code prepares, you check)
claude-code runs, for the window you name (at most 2 h):
claude-code runs `bounded-executor/prepare_admission.py` for the window you name (at most 2 h), with `--commit` set
to the commit the pinned image was built from. It commits `admissions/BEA-YYYY-NNNN.yaml`. Read it: the plan,
checks, revert steps, budget and window are what you will approve.
## 6. The run: four commands and the approval (NK-WP-0058-T04)
Run from `~/net-kingdom` after `git pull --ff-only` here and in `~/rapp-bounded-executor`:
```bash
python3 bounded-executor/prepare_admission.py --id BEA-2026-0002 --commit 9bd7bf0 \
--not-before 2026-11-05T09:00:00Z --hours 2 --out admissions/BEA-2026-0002.yaml
BX="python3 tools/bounded-execution-run/bx.py"
$BX ready admissions/BEA-YYYY-NNNN.yaml # one platform-admin login; expect "ready": true
$BX request # expect "outcome": "presented"
# approve the memo in informed-decision: browser profile of admin, aal2, fresh OTP
$BX run # one platform-admin login; preflight, open, run, close
$BX status # expect "outcome": "completed", "window_closed": true
```
It commits the file. The pins are the files inside the pinned image (`sha256:2926d7d9…`, built from `9bd7bf0`).
Read it: the plan, the checks, the revert steps, the budget and the window are what you will approve.
Then tell claude-code. It checks the receipts in `docs/evidence/<date>-<id>/` read-only, confirms the run in
audit-core, runs posture feedback and records the evidence.
## 6. The run
- **Each command prints one value-free line and is safe to repeat.** `run` never starts a second run for an
admission, and the state file keeps the approval id, so nothing is copied by hand.
- **`ready` and `run` each open one `warden access openbao-platform-admin-login` login** (browser, MFA). Its child
is silent and writes the receipts. In `run`, the window closes in the same child, also when the run fails.
- **Not ready?** The line names each failed check. `run` refuses to open the window unless the preflight Job
passes, so fix the cause and repeat.
- **Kill switch, at any moment:** `kubectl --kubeconfig ~/.kube/config-railiance01 -n sso delete job
bounded-executor-<id>`. The executor finishes the step in flight, then reverts. Before consume it spends nothing.
- **Emergency close:** `$BX close` deletes the write role; it is safe to repeat.
```bash
K="kubectl --kubeconfig $HOME/.kube/config-railiance01"
cd ~/rapp-bounded-executor && git pull --ff-only && cd ~/net-kingdom && git pull --ff-only
A=~/net-kingdom/admissions/BEA-2026-0002.yaml
CFG=$(mktemp --suffix=.json)
python3 -c "import json; c=json.load(open('$HOME/rapp-bounded-executor/examples/config.pilot.json')); c['trust_satisfied']=['runtime_secret_trust','runtime_identity_trust']; json.dump(c, open('$CFG','w'), indent=2)"
# trust_satisfied is your attestation, recorded in the run's result: OpenBao custody and KeyCape identity are healthy
```
| Result | Meaning |
| --- | --- |
| `completed` | rotated, delivered, restarted, journey passed |
| `reverted` | a check failed, and the previous value is back, checked |
| `refused` | nothing was spent |
| `not_started` | the preflight or the window did not pass; no window stayed open |
| `stopped`, `unknown`, `revert_failed` | the alert in the result receipt names the step |
**6a. Request.** The executor files the approval as `service:nk-bind-executor` and presents it in informed-decision:
### Identity hygiene
```bash
cd ~/rapp-bounded-executor && make request ADMISSION=$A CONFIG=$CFG KUBECTL="$K"
# -> {"outcome": "presented", "approval_id": "...", ...}; note the approval_id
```
**6b. Approve.** Open the memo in informed-decision and approve it. You must be signed in at aal2 (OTP in this login).
**6c. Open the window.** This creates CCR-2026-0058's write role for this admission only:
```bash
cd ~/net-kingdom && bao login -method=oidc -path=netkingdom role=platform-admin
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-t06-pilot; mkdir -p "$E"
python3 tools/service-binds/executor-lanes.py window-open --admission $A --write-ccr-sha256 "$W" \
--journey-ccr-sha256 "$J" --receipt "$E/01-window-open.json" # {"status": "window_opened", ...}
```
**6d. Run.** Put the approval id from 6a in place of `APPROVAL`:
```bash
cd ~/rapp-bounded-executor && make run ADMISSION=$A APPROVAL_ID=APPROVAL CONFIG=$CFG KUBECTL="$K"
make run-status ADMISSION_ID=BEA-2026-0002 KUBECTL="$K"
$K -n sso logs job/bounded-executor-bea-2026-0002 > ~/net-kingdom/$E/02-result.json
```
The last line of the log is the value-free result:
| Exit | Result | Meaning |
| --- | --- | --- |
| 0 | `completed` | rotated, delivered, restarted, journey passed |
| 3 | `reverted` | a check failed, and the previous value is back, checked |
| 4 | `refused` | nothing was spent |
| 5 | `stopped`, `unknown` or `revert_failed` | the alert names the step |
| 6 | consumed but not in custody | — |
**Kill switch**, at any moment of the run:
```bash
$K -n sso delete job bounded-executor-bea-2026-0002
```
The executor finishes the step in flight, then reverts what it changed (grace period = the budget). Before consume
it refuses and spends nothing.
**6e. Close the window** right after the result, or at window end at the latest:
```bash
cd ~/net-kingdom && python3 tools/service-binds/executor-lanes.py window-close --admission $A \
--receipt "$E/03-window-close.json" # {"status": "window_closed", ...}
```
**6f. Tell claude-code.** It does the rest read-only:
- it confirms the run's started event and receipt in audit-core (operator read by `correlation_id`);
- it validates the pair against receipt schema v0.1;
- it runs the posture-feedback report over the receipts (T07);
- it records the evidence and closes T06.
- Keep one browser profile per identity, and approve only in the `admin` profile. On 2026-11-04 the approval came
from whichever identity was signed in (`platform-root`) and was refused.
- Before approving, check the signed-in subject in informed-decision. Sign in again with OTP if the memo doesn't
list: access-engine lists memos only within a 12-hour MFA window and opens them within 15 minutes.
- The warden logins for `ready` and `run` are `platform-admin` in OpenBao, through KeyCape as `admin`.