diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 19985ae..ee762df 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -53,6 +53,7 @@ | workplan | NK-WP-0053 | finished | — | workplans/NK-WP-0053-identity-restore-drill-cadence.md | | workplan | NK-WP-0054 | active | — | workplans/NK-WP-0054-service-identity-policy.md | | workplan | NK-WP-0055 | active | — | workplans/NK-WP-0055-security-platform-production-readiness.md | +| workplan | NK-WP-0056 | proposed | — | workplans/NK-WP-0056-bounded-executor-path.md | | task | NK-WP-ADHOC-2026-07-02-T01 | done | — | workplans/ADHOC-2026-07-02.md | | task | NK-WP-ADHOC-2026-07-02-T02 | done | — | workplans/ADHOC-2026-07-02.md | | task | NK-WP-ADHOC-2026-08-14-T01 | done | — | workplans/ADHOC-2026-08-14.md | @@ -334,6 +335,13 @@ | task | NK-WP-0055-T14 | todo | — | workplans/NK-WP-0055-security-platform-production-readiness.md | | task | NK-WP-0055-T15 | done | — | workplans/NK-WP-0055-security-platform-production-readiness.md | | task | NK-WP-0055-T16 | wait | — | workplans/NK-WP-0055-security-platform-production-readiness.md | +| task | NK-WP-0056-T01 | todo | — | workplans/NK-WP-0056-bounded-executor-path.md | +| task | NK-WP-0056-T02 | todo | — | workplans/NK-WP-0056-bounded-executor-path.md | +| task | NK-WP-0056-T03 | todo | — | workplans/NK-WP-0056-bounded-executor-path.md | +| task | NK-WP-0056-T04 | todo | — | workplans/NK-WP-0056-bounded-executor-path.md | +| task | NK-WP-0056-T05 | todo | — | 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 | | intake | NK-IN-0001 | closed | blue | docs/intakes/activity-core-ops-sso-operators.md | | intake | NK-IN-0002 | closed | blue | docs/intakes/activity-core-ops-sso-operators.md | | intake | NET-IN-0001 | open | — | intakes/intakes.md | diff --git a/workplans/NK-WP-0056-bounded-executor-path.md b/workplans/NK-WP-0056-bounded-executor-path.md new file mode 100644 index 0000000..de0532f --- /dev/null +++ b/workplans/NK-WP-0056-bounded-executor-path.md @@ -0,0 +1,182 @@ +--- +id: NK-WP-0056 +type: workplan +title: "Bounded executor path: founder admits, executors run" +domain: infotech +repo: net-kingdom +status: proposed +flavor: design +owner: claude +topic_slug: netkingdom +created: "2026-10-30" +updated: "2026-10-30" +related: + - NK-WP-0054 + - NK-WP-0040 + - NK-WP-0031 + - NK-WP-0055 +--- + +# NK-WP-0056 — Bounded executor path + +Intake from the founder's direction on 2026-10-30, before the live LLDAP bind split: top-level +decisions and guardrails stay with the founder; execution below that is delegated to automation with +limited expense budgets and risk control, and the security architecture is the means. Founder-attended +runbooks are a transitional state. + +SI-15 (`canon/standards/service-identity-privilege_v0.1.md`) already names the golden path *prepare → +admit → execute → verify → retain* and allows "a bounded executor under the admission" at step 3. +Today preparation and verification are strong, admission is prose (a hub decision) and execution falls +to the founder, because no executor exists that has its own identity, its own secret delivery and an +authority ceiling the founder can admit and bound. SI-14 adds that an interactive agent session holds +everything its tools reach, so it cannot be that executor until a session contract exists +(glas-harness GLAS-WP-0018, proposed). + +## Why the bind split needed the founder (2026-10-30 run, step by step) + +| Runbook step | Needed the founder because | Class | Delegable once | +| --- | --- | --- | --- | +| Setup: decrypt custody copy | custody is a personal SOPS/age copy | delegable | service credentials live in OpenBao (T04) | +| 1 prepare custody (generate passwords) | writes the personal custody copy | delegable | executor generates into OpenBao (T04) | +| 2 plan, 4 verify, 10 verify | sign in as the human `admin` | delegable | read-only executor directory identity (T03) | +| 3 create `svc-*` accounts | needs `lldap_admin` (LLDAP has no narrower grant that can create users) | root-class | admitted per run; executor runs it (T03) | +| 5-8 switch one consumer | cluster-admin kubeconfig; secret values; founder sign-in check | delegable | scoped service account (T03), OpenBao/ESO (T04), synthetic MFA journey (T05) | +| 9 change LLDAP's configured super-admin | changes who administers the directory | root-class | admitted per run; executor runs it | +| 10 change `admin`'s own password; seal `ld-admin` in the password safe | the founder's own credential and crisis custody | human-intrinsic | never: stays with the founder | +| Afterwards: restore drill on the next generation | `admin` operates drills | delegable | executor identity with the drill's read scope | + +Root-class means the founder still admits each run, but no longer types it. The run also showed why +personal custody does not scale: the custody copy had drifted from live (`AUTHELIA_KEYCAPE_CLIENT_SECRET`) +and step 6 had to be done by a one-off path. + +## Admission contract + +```task +id: NK-WP-0056-T01 +status: todo +priority: high +assignee: claude-code +``` + +Draft a NetKingdom standard for a **bounded-execution admission**: the founder approves, at `aal2`, an +exact plan by digest with a validity window, a scope ceiling (`MODE @ SCOPE` grants, SI terms), a +blast-radius rule (for example one consumer at a time), a stop-and-revert policy tied to named machine +checks, a risk class, and an expense budget (wall time, attempts, compute/egress cost). The executor +consumes the admission once. Map it to SI-15, the Playbook Capability Contract's trust-state +requirements and the execution-attribution receipt (NK-WP-0040). Include a validator and synthetic +fixtures. + +**Done when:** the standard is proposed with a schema, a validator, and the bind-split steps expressed +as admissions in its examples. + +## Owner agreement on the components + +```task +id: NK-WP-0056-T02 +status: todo +priority: high +assignee: claude-code +needs_human: true +depends_on: [NK-WP-0056-T01] +``` + +Ask the owners which part each carries: approval-engine (the admission as its consumable approval +object, plan digest and budget as bound fields, single consume), access-engine (reads the admission +as an input claim), secrets-engine and railiance-platform (executor credential delivery through +OpenBao), glas-harness (GLAS-WP-0018 session contract, so a harness-launched agent can be an executor), +audit-core (receipt holder, as in NK-WP-0040). The founder decides who builds the executor runtime +itself. + +**Done when:** each component has a named owner and an answer, and the founder has chosen the executor +runtime owner. + +## Executor identity and authority ceiling + +```task +id: NK-WP-0056-T03 +status: todo +priority: high +assignee: claude-code +depends_on: [NK-WP-0056-T02] +``` + +Declare the executor as a `WORKLOAD` (or harness-launched `AGENT`) principal in `declarations/` with +grants no wider than the pilot: a Kubernetes service account whose Role names the `sso` Secrets, +ConfigMaps and Deployments it may patch or restart; a read-only directory bind for plan and verify; +`lldap_admin` only for root-class steps under an admission. Extend `tools/service-identity` to check +it. + +**Done when:** the declaration validates and the Role is prepared in source with tests, not applied. + +## Service credentials into OpenBao + +```task +id: NK-WP-0056-T04 +status: todo +priority: high +assignee: claude-code +needs_human: true +depends_on: [NK-WP-0056-T02] +``` + +With railiance-platform, move the LLDAP service binds (`LLDAP_SVC_*_PASS`) and the Authelia secrets +from the personal custody copy into OpenBao paths delivered by ESO, so that neither a person nor an +agent handles the values in a rotation. First reconcile the stale custody +`AUTHELIA_KEYCAPE_CLIENT_SECRET` with the live value (founder-run, value-free comparison as in the +2026-10-30 evidence). Root-class material (`ld-admin`, unseal shares) stays in founder custody. + +**Done when:** the four service binds are ESO-delivered from OpenBao, and the custody copy no longer +needs to be decrypted for a bind rotation. + +## Synthetic verification instead of a founder sign-in + +```task +id: NK-WP-0056-T05 +status: todo +priority: medium +assignee: claude-code +depends_on: [NK-WP-0056-T04] +``` + +A synthetic test user with an OTP seed held in OpenBao, and a journey that signs in through Authelia +and KeyCape with MFA and resolves through privacyIDEA. Reuse the identity-provider journey acceptance. +The executor runs it as the check between consumers and reverts on failure. + +**Done when:** the journey runs unattended, and fails closed against a deliberately broken bind on a +synthetic directory. + +## Pilot: unattended bind rotation under one admission + +```task +id: NK-WP-0056-T06 +status: todo +priority: high +assignee: claude-code +needs_human: true +depends_on: [NK-WP-0056-T01, NK-WP-0056-T03, NK-WP-0056-T04, NK-WP-0056-T05] +``` + +Rotate `svc-authelia`'s password with no person in the loop beyond the admission: generate into +OpenBao, set in LLDAP, let ESO deliver, restart, run the synthetic journey, revert on failure, emit a +receipt to audit-core. Rehearse on a synthetic directory first, then one live run under a +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. + +## Budget and risk enforcement + +```task +id: NK-WP-0056-T07 +status: todo +priority: medium +assignee: claude-code +depends_on: [NK-WP-0056-T06] +``` + +Enforce the admission's budget and blast radius at run time (attempt and time limits, a kill switch the +founder holds, refusal when a check is missing), and feed outcomes and drift into posture feedback +(NK-WP-0031) so that recurring admissions can be reviewed in aggregate rather than one by one. + +**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.