NK-WP-0056: T15 done; T16/T06 ready for founder-run live steps; T07 built, waits on the pilot's receipts
Runbook reordered to railiance-platform's gates: case acceptance (59d570ef) before custody; case materialized before the broker mint; audit seed inside the custody sequence. 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
This commit is contained in:
parent
000f1e3222
commit
4c37d5cf4d
3 changed files with 99 additions and 41 deletions
|
|
@ -349,7 +349,7 @@
|
|||
| task | NK-WP-0056-T04 | done | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
| task | NK-WP-0056-T05 | done | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
| task | NK-WP-0056-T06 | todo | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
| task | NK-WP-0056-T07 | todo | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
| task | NK-WP-0056-T07 | wait | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
| task | NK-WP-0056-T08 | done | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
| task | NK-WP-0056-T09 | done | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
| task | NK-WP-0056-T10 | done | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
|
|
@ -357,7 +357,7 @@
|
|||
| task | NK-WP-0056-T12 | done | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
| task | NK-WP-0056-T13 | done | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
| task | NK-WP-0056-T14 | done | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
| task | NK-WP-0056-T15 | todo | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
| task | NK-WP-0056-T15 | done | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
| task | NK-WP-0056-T16 | wait | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
| task | NK-WP-0056-T17 | done | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
| task | NK-WP-0056-T18 | done | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# T06 runbook: the live pilot rotation under one admission (founder-run)
|
||||
|
||||
NK-WP-0056-T06. The executor rotates `svc-authelia`'s LLDAP bind. Your only part *in the run* is the
|
||||
admission: you approve it at aal2 in informed-decision. Everything before that (sections 1 to 5) is one-time
|
||||
go-live of the standing paths. Section 7 is the run.
|
||||
admission: you approve it at aal2 in informed-decision. Everything before that (sections 1 to 4) is one-time
|
||||
go-live of the standing paths. Section 6 is the run.
|
||||
|
||||
Each step prints a value-free result. Paste it back, and claude-code verifies it read-only and records it.
|
||||
|
||||
|
|
@ -15,12 +15,11 @@ Each step prints a value-free result. Paste it back, and claude-code verifies it
|
|||
| # | What | Where | Changes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Owner ingress (T16) | approval-engine, audit-core, rapp | two NetworkPolicies; read-only netcheck |
|
||||
| 2 | Custody | railiance-platform | approve CCR-2026-0060, -0061, -0063; apply policies and roles, ESO; mint the KeyCape client secret |
|
||||
| 3 | Accept the case | State Hub decision | `security-cases/nk-bind-executor-approval.yaml` becomes `accepted` |
|
||||
| 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 | Audit sender | audit-core | mint and seed the `nk-bounded-executor` token |
|
||||
| 6 | Admission | net-kingdom (claude-code) | `admissions/BEA-2026-0002.yaml` for the window you choose |
|
||||
| 7 | 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-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 |
|
||||
|
||||
## 1. Owner ingress (T16)
|
||||
|
||||
|
|
@ -34,8 +33,10 @@ python3 -c "import yaml,sys; yaml.safe_dump([d for d in yaml.safe_load_all(open(
|
|||
$K apply --dry-run=server -f /tmp/ae-bx.yaml && $K apply -f /tmp/ae-bx.yaml
|
||||
```
|
||||
|
||||
audit-core: run step 1 of audit-core `docs/bounded-executor-receipts.md`, "Founder runbook — nk-bounded-executor
|
||||
sender". It applies `audit-core-nk-bounded-executor-ingress` the same way.
|
||||
audit-core: run steps 1 and 2 of audit-core `docs/bounded-executor-receipts.md`, "Founder runbook —
|
||||
nk-bounded-executor sender". Step 1 applies `audit-core-nk-bounded-executor-ingress` the same way. Step 2 is a
|
||||
read-only preflight, which also checks that the live scope ConfigMap carries `nk-bounded-executor`. This is
|
||||
railiance-platform's gate G2 before the audit seed.
|
||||
|
||||
Then prove the path from an executor-labelled pod. It holds no token and makes no login:
|
||||
|
||||
|
|
@ -47,22 +48,28 @@ make netcheck KUBECTL="$K"
|
|||
Expected, on the last lines: `"approval_engine_health": 200`, `"audit_core_health": 200` and
|
||||
`"informed_decision_tcp": "ok"`, alongside the existing OpenBao, KeyCape and Authelia columns.
|
||||
|
||||
## 2. Custody (railiance-platform)
|
||||
## 2. Accept the service-client case
|
||||
|
||||
Follow railiance-platform's go-live runbook for the three requests (path in its hub message
|
||||
"NK-WP-0056-T06 custody go-live"):
|
||||
Answer State Hub decision `59d570ef` ("Accept SecurityCase nk-bind-executor-approval"). The case type requires
|
||||
owner and founder acceptance; you are both. claude-code then commits the case as `accepted`, with the acceptance
|
||||
record.
|
||||
|
||||
- approve CCR-2026-0060, -0061 and -0063 with the approve tool;
|
||||
- apply the policies, roles and ESO objects;
|
||||
- mint the KeyCape client secret into `platform/workloads/keycape/nk-bind-executor-approval` without printing it;
|
||||
- check that the ExternalSecret `sso/keycape-nk-bind-executor-approval-client` reports `Ready=True`.
|
||||
## 3. Custody and audit sender (railiance-platform, audit-core)
|
||||
|
||||
Section 4 needs that `Ready` immediately before it runs.
|
||||
Follow railiance-platform `docs/credential-lane-designs/nk-bind-executor-go-live.md`, steps 0 to 7, in order:
|
||||
|
||||
## 3. Accept the service-client case
|
||||
- **Steps 0 to 3:** session; approve CCR-2026-0060, -0061 and -0063 and confirm their bindings; the coding-agent
|
||||
fence; policies and roles.
|
||||
- **Then tell claude-code.** It commits the case as `materialized`: its OpenBao structure now exists. The broker
|
||||
mints only for a materialized, accepted case (gate G1). The case's hash changes with that commit, and step 5
|
||||
derives `REF` from the committed file. So `git pull --ff-only` in net-kingdom before step 5.
|
||||
- **Step 4:** the audit seed, which is step 3 of audit-core's founder runbook. It needs gate G2 from section 1.
|
||||
- **Step 5:** mint the KeyCape client secret through the broker. No value is printed.
|
||||
- **Step 6:** ESO delivery to `sso`: KeyCape's `keycape-nk-bind-executor-approval-client`, and the executor's
|
||||
`bounded-executor-tokens` key `audit-core`.
|
||||
- **Step 7:** `verify`, which checks metadata, capabilities, logins and hashes only.
|
||||
|
||||
Answer State Hub decision `59d570ef` ("Accept SecurityCase nk-bind-executor-approval"). claude-code then records the
|
||||
acceptance in the case file. The case type requires owner and founder acceptance; you are both.
|
||||
Section 4 needs step 7's `Ready=True` for `keycape-nk-bind-executor-approval-client` immediately before it runs.
|
||||
|
||||
## 4. KeyCape: bind and register in one restart
|
||||
|
||||
|
|
@ -93,7 +100,7 @@ Then put the noted values into the apply line, in place of `UID` and `RV`:
|
|||
|
||||
```bash
|
||||
python3 sso-mfa/k8s/keycape/keycape-client.py apply --client-file "$C" \
|
||||
--case-acceptance "security-cases/nk-bind-executor-approval.yaml (accepted, hub decision in section 3)" \
|
||||
--case-acceptance "security-cases/nk-bind-executor-approval.yaml (accepted, hub decision 59d570ef)" \
|
||||
--check-config "$B/keycape" --expected-uid UID --expected-resource-version RV
|
||||
$K -n sso rollout resume deployment/keycape
|
||||
$K -n sso rollout status deployment/keycape --timeout=180s
|
||||
|
|
@ -103,15 +110,10 @@ If `apply` refuses, nothing in the registry changed. Undo the env patch before r
|
|||
`$K -n sso rollout undo deployment/keycape`, then `$K -n sso rollout resume deployment/keycape`, and paste the
|
||||
refusal.
|
||||
|
||||
claude-code then runs the type's verification. The executor's request Job (section 7) performs the token exchange
|
||||
claude-code then runs the type's verification. The executor's request Job (section 6) performs the token exchange
|
||||
per scope. The excess-scope refusal, the custody denials and the RBAC can-i denial are read-only checks.
|
||||
|
||||
## 5. Audit sender
|
||||
|
||||
Run steps 2 to 4 of audit-core's founder runbook (see section 1): preflight, the silent seed under
|
||||
`warden access ... --exec`, and its receipt. The seed needs CCR-2026-0063 applied (section 2).
|
||||
|
||||
## 6. Admission (claude-code prepares, you check)
|
||||
## 5. Admission (claude-code prepares, you check)
|
||||
|
||||
claude-code runs, for the window you name (at most 2 h):
|
||||
|
||||
|
|
@ -123,7 +125,7 @@ python3 bounded-executor/prepare_admission.py --id BEA-2026-0002 --commit 9bd7bf
|
|||
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.
|
||||
|
||||
## 7. The run
|
||||
## 6. The run
|
||||
|
||||
```bash
|
||||
K="kubectl --kubeconfig $HOME/.kube/config-railiance01"
|
||||
|
|
@ -134,16 +136,16 @@ python3 -c "import json; c=json.load(open('$HOME/rapp-bounded-executor/examples/
|
|||
# trust_satisfied is your attestation, recorded in the run's result: OpenBao custody and KeyCape identity are healthy
|
||||
```
|
||||
|
||||
**7a. Request.** The executor files the approval as `service:nk-bind-executor` and presents it in informed-decision:
|
||||
**6a. Request.** The executor files the approval as `service:nk-bind-executor` and presents it in informed-decision:
|
||||
|
||||
```bash
|
||||
cd ~/rapp-bounded-executor && make request ADMISSION=$A CONFIG=$CFG KUBECTL="$K"
|
||||
# -> {"outcome": "presented", "approval_id": "...", ...}; note the approval_id
|
||||
```
|
||||
|
||||
**7b. Approve.** Open the memo in informed-decision and approve it. You must be signed in at aal2 (OTP in this login).
|
||||
**6b. Approve.** Open the memo in informed-decision and approve it. You must be signed in at aal2 (OTP in this login).
|
||||
|
||||
**7c. Open the window.** This creates CCR-2026-0058's write role for this admission only:
|
||||
**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
|
||||
|
|
@ -154,7 +156,7 @@ python3 tools/service-binds/executor-lanes.py window-open --admission $A --write
|
|||
--journey-ccr-sha256 "$J" --receipt "$E/01-window-open.json" # {"status": "window_opened", ...}
|
||||
```
|
||||
|
||||
**7d. Run.** Put the approval id from 7a in place of `APPROVAL`:
|
||||
**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"
|
||||
|
|
@ -181,14 +183,14 @@ $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.
|
||||
|
||||
**7e. Close the window** right after the result, or at window end at the latest:
|
||||
**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", ...}
|
||||
```
|
||||
|
||||
**7f. Tell claude-code.** It does the rest read-only:
|
||||
**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;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ flavor: design
|
|||
owner: claude
|
||||
topic_slug: netkingdom
|
||||
created: "2026-10-30"
|
||||
updated: "2026-11-03"
|
||||
updated: "2026-11-04"
|
||||
related:
|
||||
- NK-WP-0054
|
||||
- NK-WP-0040
|
||||
|
|
@ -841,7 +841,7 @@ Follow-ups, both settled 2026-11-04:
|
|||
|
||||
```task
|
||||
id: NK-WP-0056-T15
|
||||
status: todo
|
||||
status: done
|
||||
priority: high
|
||||
assignee: claude-code
|
||||
depends_on: [NK-WP-0056-T13]
|
||||
|
|
@ -857,6 +857,25 @@ audit-core accepts the `started` event and the receipt only from a registered se
|
|||
**Done when:** a synthetic run's events are accepted by audit-core's real ingestion (202, duplicate 200, conflict
|
||||
409, wrong source refused), and the live seed is prepared for the founder.
|
||||
|
||||
**Done 2026-11-04** ([evidence](../docs/evidence/2026-11-04-nk56-t15-audit-sender/README.md)).
|
||||
|
||||
- **Schema:** receipt schema v0.1 (`canon/schemas/execution-attribution-receipt_v0.1.schema.json`) covers both
|
||||
events. The validator (`tools/execution-attribution-receipt`, EAR-1..10) has fixtures generated from the executor.
|
||||
- **Executor:** the started event now carries `data.window.not_after` (audit-core's T03 request), the digests and
|
||||
the planned step count. The receipt carries `receipt_version` and `initiator.iss`.
|
||||
- **Exercise:** `bounded-executor/exercise_audit_sender.py` runs against audit-core `876c3f6`'s real ingestion and
|
||||
scope overlay. 8 checks pass:
|
||||
- 202 for each event;
|
||||
- duplicate 200;
|
||||
- 409 reported as run-id reuse;
|
||||
- wrong source, tenant or token refused and not stored;
|
||||
- a receipt-less start flagged by its own window.
|
||||
- **Custody:** CCR-2026-0063 (railiance-platform `f3b0c4f`, proposed). ESO delivers to `sso/bounded-executor-tokens`
|
||||
key `audit-core`, which the run Job mounts. NetKingdom answered "ESO as drafted".
|
||||
- **Live seed:** audit-core `scripts/seed-nk-bounded-executor-sender.py` (`876c3f6`) is the single seeder. Its
|
||||
runbook is in audit-core `docs/bounded-executor-receipts.md`.
|
||||
- **What remains is founder-run:** T06 runbook section 3.
|
||||
|
||||
## Owner ingress for the executor pod
|
||||
|
||||
```task
|
||||
|
|
@ -864,7 +883,7 @@ id: NK-WP-0056-T16
|
|||
status: wait
|
||||
priority: medium
|
||||
assignee: claude-code
|
||||
blocked_on: message-from:approval-engine
|
||||
blocked_on: human
|
||||
depends_on: [NK-WP-0056-T10]
|
||||
state_hub_task_id: "a08c6b82-be3f-5dca-82f7-b2a0ced6b335"
|
||||
```
|
||||
|
|
@ -875,6 +894,14 @@ pod label `app.kubernetes.io/name=bounded-executor` on 8080. Our side: the rapp'
|
|||
**Done when:** both rules are live and `make netcheck` (extended to both endpoints) shows them reachable from an
|
||||
executor pod.
|
||||
|
||||
**2026-11-04: our side is done; the live apply is the founder's.**
|
||||
|
||||
- Both owner rules are in source: approval-engine `e9e9f93` and audit-core `7728fde`. Neither is live (read-only
|
||||
check: the policy list in each namespace).
|
||||
- rapp `cf4bbb9`: `make netcheck` probes approval-engine and audit-core `/healthz` and informed-decision:8081.
|
||||
- Founder steps: T06 runbook (`sso-mfa/k8s/bounded-executor/T06-PILOT-RUNBOOK.md`) section 1. Each object is applied
|
||||
on its own, because live approval-engine has a policy that its file lacks.
|
||||
|
||||
## Founder approval path at aal2
|
||||
|
||||
```task
|
||||
|
|
@ -1048,13 +1075,29 @@ founder-signed admission.
|
|||
**Done when:** the live rotation completes or reverts on its own, within its budget, with a verified
|
||||
receipt, and the founder's only action was the admission.
|
||||
|
||||
**2026-11-04: ready for the founder.** Runbook: `sso-mfa/k8s/bounded-executor/T06-PILOT-RUNBOOK.md`. The rehearsal
|
||||
on a synthetic directory is T12's pilot. The go-live of the standing paths runs once, in this order:
|
||||
|
||||
1. owner ingress (T16);
|
||||
2. case acceptance, hub decision `59d570ef`;
|
||||
3. railiance-platform's custody go-live (`docs/credential-lane-designs/nk-bind-executor-go-live.md`, CCR-2026-0060,
|
||||
-0061 and -0063), with the audit seed inside it;
|
||||
4. KeyCape bind-env and register-client in one restart.
|
||||
|
||||
Then the run: `prepare_admission.py` writes `admissions/BEA-2026-0002.yaml`; then `make request`; the founder
|
||||
approves at aal2; `executor-lanes.py window-open`; `make run`; `window-close`.
|
||||
|
||||
The image is `sha256:2926d7d9…` (net-kingdom `9bd7bf0`), pinned in rapp `cf4bbb9`. The approver subject is the
|
||||
LDAP DN (KeyCape `sub`).
|
||||
|
||||
## Budget and risk enforcement
|
||||
|
||||
```task
|
||||
id: NK-WP-0056-T07
|
||||
status: todo
|
||||
status: wait
|
||||
priority: medium
|
||||
assignee: claude-code
|
||||
blocked_on: dependency
|
||||
depends_on: [NK-WP-0056-T06]
|
||||
state_hub_task_id: "a87c5edb-7604-5eba-9261-b1ed2ed16655"
|
||||
```
|
||||
|
|
@ -1065,3 +1108,16 @@ founder holds, refusal when a check is missing), and feed outcomes and drift int
|
|||
|
||||
**Done when:** a run that exceeds its budget or scope stops and reverts in a synthetic test, and the
|
||||
pilot's receipts appear in a posture-feedback report.
|
||||
|
||||
**2026-11-04: enforcement and feedback are built; the pilot's receipts are still to come (T06).**
|
||||
|
||||
- **Budget and scope:** attempt and wall-time limits, refusal of an unknown check or operation, and the scope ceiling
|
||||
were already enforced (T11). Covered by tests: budget exhausted reverts; kill switch reverts; window shorter than
|
||||
budget refused.
|
||||
- **Kill switch (`9bd7bf0`):** SIGTERM or SIGINT sets the stop flag. That happens when the founder runs
|
||||
`kubectl delete job`, and at the Job deadline. The runner reverts at the next step boundary. A stop before consume
|
||||
refuses and spends nothing. rapp `601ada1` sets the termination grace period to the budget.
|
||||
- **Posture feedback v0.1 section 4a (`9bd7bf0`):** `--receipts` reads the executor's events through the receipt
|
||||
validator. Findings: receipt-missing, not-completed, reverted and budget-pressure, plus the aggregate
|
||||
`execution-recurring-revert`. Owners come from `tools/posture-feedback/execution-owners.yaml`, never inferred.
|
||||
- **Left:** run the report over the pilot's receipts after T06.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue