--- id: netkingdom-bounded-execution-admission-v0.1 type: standard title: "NetKingdom Bounded Execution Admission v0.1" domain: netkingdom status: proposed version: "0.1" owner: net-kingdom created: "2026-10-31" updated: "2026-10-31" last_reviewed: "2026-10-31" review_interval: 3m scope: accountable-automation schema: - canon/schemas/bounded-execution-admission_v0.1.schema.json validator: - tools/bounded-execution-admission/validate.py examples: - examples/bounded-execution-admission/ related: - canon/standards/service-identity-privilege_v0.1.md - canon/standards/playbook-capability-contract_v0.2.md - workplans/NK-WP-0056-bounded-executor-path.md - workplans/NK-WP-0040-execution-attribution-receipt.md --- # NetKingdom Bounded Execution Admission v0.1 ## 0. Status Proposed (NK-WP-0056-T01). Nothing here is enforced by a running service yet. The executor runtime is T02/T03, budget and kill-switch enforcement is T07, and the first live use is the T06 pilot. A document that passes the validator is a well-formed **request**. It is an **admission** only together with a carrier record that a person approved (section 5). ## 1. Purpose SI-15 names the golden path *prepare → admit → execute → verify → retain*, and allows "a bounded executor under the admission" at step 3. This standard defines what that admission is. The founder approves, at `aal2`: - an exact plan, by digest; - a validity window; - a scope ceiling in SI `MODE @ SCOPE` terms; - a blast-radius rule; - a stop-and-revert policy tied to named machine checks; - a risk class; - an expense budget. The executor consumes the admission once. Top-level decisions and guardrails stay with the person, and execution below them is delegated, bounded and reconstructable. Out of scope: who runs the executor (T02), how a carrier stores approvals (Approval Engine owns that), and the receipt's emission and custody (NK-WP-0040-T02). ## 2. Vocabulary | Term | Meaning | | --- | --- | | Admission request | The immutable document defined here (`BoundedExecutionAdmission`), identified by `spec.id` and by its digest | | Carrier | The system that records a person's approval of one request and its single consumption: Approval Engine, or a founder SSH signature (NK-WP-0049 practice) | | Admission | A request plus a carrier record that passes BEA-C1..C7 | | Executor | The non-human identity that runs the plan: a `WORKLOAD`, `SERVICE` or harness-launched `AGENT` (SI-14) | | Step class | `delegable` (the executor may run it under an admission), `root-class` (the founder admits each run; high risk only), `human-intrinsic` (never in an admission: for example a person's own password) | | Check | A named, source-pinned machine check that must pass after a mutating step | | Consumer | The unit the blast radius counts: a service whose behaviour a step can change | ## 3. The admission request A YAML or JSON document validated by `canon/schemas/bounded-execution-admission_v0.1.schema.json`: | Field | Meaning | | --- | --- | | `spec.id`, `title`, `purpose`, `work_ref` | Identity and intent. `id` is `BEA-YYYY-NNNN` | | `risk_class` | `low`, `medium` or `high`. Bounds the window, the attempts, the ceiling and the step classes | | `window.not_before` / `not_after` | When the admission can be consumed. At most 72 h (low), 24 h (medium) or 4 h (high) | | `approval` | Who may approve (`approvers`, `HUMAN`, `aal2`) and through which carriers | | `executor` | The executing identity, its principal type and runtime | | `scope_ceiling` | Grants `{mode, scope, environments}` that bound every step. Scopes are `/`-separated paths, and a grant covers its own scope and anything below it | | `blast_radius` | `unit`, the `consumers` the plan may touch, and `max_concurrent` | | `trust_requires` | Playbook Capability Contract trust states the executor must find satisfied before the first step | | `plan.source` | Repository, commit, and the sha256 of every file the run executes or checks with | | `plan.steps`, `plan.revert_steps` | Ordered steps: `operation`, `target`, `consumer`, `class`, `mutates`, `requires` (the grant it needs), `checks_after`, `revert` or `irreversible` | | `plan_digest` | `sha256:` over the canonical JSON of `plan` (sorted keys, no whitespace, UTF-8) | | `checks` | Named checks: `ref` (a pinned file), `sha256`, `timeout_seconds`, optional `settle_seconds`, `expect: pass` | | `stop_and_revert` | `on_check_failure` and `on_budget_exhausted` (`revert` or `stop`); `on_unknown: stop`; `on_revert_failure: stop-and-alert` | | `budget` | `wall_time_seconds`, `attempts`, and `cost` (CPU seconds, egress bytes, currency, amount) | | `consumption` | `single_use: true`, `consume_before_first_step: true` | | `receipt` | The NK-WP-0040 execution-attribution receipt, where it goes, and that it is retained by hash with no secret values | | `not_authorized` | What this admission explicitly does not cover | `settle_seconds` exists because of the T08 finding: privacyIDEA's resolver cache hides a broken bind for up to 120 s, so a check run sooner proves nothing. ## 4. Rules (validator: `validate`) | Rule | Requirement | | --- | --- | | BEA-1 | The document matches the schema (`HUMAN` approvers at `aal2`, single use, `on_unknown: stop`) | | BEA-2 | `plan_digest` equals the digest of `plan`: the person admits exactly this plan | | BEA-3 | The window is positive and no longer than the risk class allows | | BEA-4 | The executor is not `HUMAN` and not an approver. An `AGENT` must be harness-launched (SI-14) | | BEA-5 | No `SOVEREIGN` or `GOVERN` in the ceiling. No `CONSTRUCT` in `PRODUCTION`. `ADMINISTER` needs `max_concurrent: 1`; at a whole-service scope (no `/`) it needs `high` risk and only `root-class` steps | | BEA-6 | Least privilege: every step and revert step is covered by a ceiling grant of the same mode, and every ceiling grant covers at least one step | | BEA-7 | No `human-intrinsic` step. A `root-class` step needs `high` risk | | BEA-8 | Every step's consumer is in the blast radius. `medium` and `high` risk change one consumer at a time | | BEA-9 | Every mutating step names checks, revert steps included: a revert must prove the restored state with its own checks. Every check is used and pinned: its `ref` and `sha256` appear in `plan.source.files` | | BEA-10 | Every mutating step has a revert step, or is `irreversible` at `high` risk. Revert steps mutate and do not nest. Step ids are unique. The executor runs revert steps in their declared order (the recovery order: data, then delivery, then restart), limited to those whose forward step ran | | BEA-11 | A revertable plan reverts on check failure. A plan with nothing to revert stops | | BEA-12 | The wall time fits the window, the checks (timeouts plus settle times) fit the wall time, and attempts are at most 3 (1 at `high` risk) | | BEA-13 | The executed source is pinned by file and commit | | BEA-14 | No secret-shaped value anywhere in the document | Findings name the rule and a location, never a value. ## 5. Carrier and consumption (validator: `check-approval`) A carrier record (`netkingdom.io/bounded-execution-approval/v0.1`) states the carrier, its approval reference, the admission id and digest, the approver (name, principal type, assurance), the approval time, and the consumptions. The **admission digest** is `sha256:` over the canonical JSON of the whole request, including `plan_digest`. That digest is what a carrier binds. | Rule | Requirement | | --- | --- | | BEA-C1 | The carrier is one the request allows, and the record has the expected shape | | BEA-C2 | The record names this admission's id and digest | | BEA-C3 | The approver is a listed `HUMAN` approver and not the executor | | BEA-C4 | The approval was made at `aal2` | | BEA-C5 | The approval was made before the window closed | | BEA-C6 | Consumed at most once | | BEA-C7 | The consumption happened in the window, after approval, by the executor identity | **Approval Engine (preferred carrier).** Approval Engine already stores an approval that binds action, actor, principal, purpose and target by digest, carries a validity window, and is consumed exactly once (`POST /v1/approvals/{id}/consume`), read back through `GET /v1/approvals/{id}`. The proposed mapping, which is for agreement with Approval Engine and Access under T02, not decided here: - `action: bounded-execution`; - `actor`: the executor identity; - `principal`: the approver; - `purpose`: `spec.purpose`; - `target: {admission_id, admission_digest}`; - validity equal to `window`; - the executor consumes before its first step (`consume_before_first_step`). Approval Engine's own contract notes that `consume` does not check that the request digest is equivalent to the decision. An independent mediator must therefore fetch the approval and compare `target.admission_digest` itself. A `consumed: true` returned by the caller is not proof. **Founder SSH signature (transitional carrier).** This is the NK-WP-0049 practice: - the founder signs the canonical request with `ssh-keygen -Y sign`, namespace `netkingdom-bounded-execution`; - the signature is verified against the repository's `allowed_signers`; - `aal2` is established by the signing key's custody, not by a token. Single use is then only as strong as the executor's own consumption ledger. That is acceptable for the transition and is recorded as such in the receipt. ## 6. Mapping **SI-15 golden path.** | Golden-path step | What it means here | | --- | --- | | Prepare | `plan.source` (source-reviewed, pinned files), tested on synthetic fixtures. For bind changes, NK-WP-0056-T08's synthetic stack | | Admit | Carrier approval of the admission digest at `aal2` | | Execute | The executor, inside `scope_ceiling`, `blast_radius`, `window` and `budget`, consuming once | | Verify | The named checks during the run. Afterwards, an independent verifier checks the carrier record (BEA-C1..C7) and the receipt's source hashes | | Retain | The receipt, kept by hash with no secret values | **Playbook Capability Contract.** `trust_requires` uses the contract's trust-state vocabulary. The executor refuses to start unless each state is satisfied, using the readiness checks of the capability declarations it runs. A step's `operation` should name a declared capability operation once Railiance declarations exist for it. **Execution-attribution receipt (Playbook Capability Contract v0.2, NK-WP-0040).** One receipt per run: | Receipt field | Filled from | | --- | --- | | `initiator` | The carrier's approver (the founder). The person authorized the run; the executor ran it | | `delegation` | Absent unless the approver acted through an agent | | `executing_workload`, `runtime_principal` | `executor.identity`, `executor.runtime` | | `run_id` | New per run | | `source_commit` | `plan.source.commit` | | `artifact_digest` | `plan_digest` | | `target`, `action` | Per step | | `decision_refs` | `spec.id`, the admission digest and the carrier's approval reference | | `time_interval` | Measured | The receipt adds the outcome per step, check results, whether a revert ran, and the budget used. It never holds a secret value. Founder decision 2026-10-31, agreed with audit-core (AUDIT-WP-0018): - When the executor consumes the admission, before its first step, it emits a separate `execution.run.started` event, so a run that crashes before its receipt is still detectable. - It then emits one `execution.attribution.receipt` per run: - `target` and `action` at the admission level (`admission:`, `bounded-execution`); - per-step detail in `steps[]`; - `decision_refs` labelled `admission`, `admission_digest` and `approval`. - Envelope ids are `run::started` and `run::receipt`. **Policy decision point.** access-engine's gate (FLEX-WP-0040) has two decisions: `start` before consume, and `execute-step` after it. The T06 pilot runs without the gate: its receipt records the gate as `not-evaluated` and claims no allow. Any further admission needs the gate, or an exception the founder records (founder decision 2026-10-31). **Failure classes.** A failed check, or an operation that reports a definite failure (for example a rollout that never becomes ready), reverts per `on_check_failure`. An error whose outcome is not established stops (`on_unknown: stop`) without reverting. Receipts name the error type, never its message. **Credentials during a run.** Write roles exist only during the admitted window: the platform creates them when an admission is approved and deletes them after the receipt (CCR-2026-0058). A directory bind rotates its own password, so no password-manager account is needed (founder decisions 2026-10-31). ## 7. The bind split as admissions NK-WP-0056 tagged each step of the 2026-10-30 LLDAP bind split. The examples express them: | Runbook step | Class | Example | | --- | --- | --- | | 2, 4, 10 (verify) | delegable, read-only | `bind-split-read-only-verify.yaml`: low risk, `OBSERVE` only, nothing to revert | | 3 create `svc-*` accounts | root-class | `bind-split-create-service-accounts.yaml`: high, whole-directory `ADMINISTER` (no narrower LLDAP grant, SI-X6), revert deletes what was created | | 5–8 switch one consumer | delegable | `bind-rotation-svc-authelia.yaml`: medium, one consumer, a synthetic-journey check after the restart, a revert per step. This is the T06 pilot shape | | 9 change LLDAP's super-admin | root-class | `bind-split-switch-super-admin.yaml`: high, one attempt, `settle_seconds: 125` on the journey check (privacyIDEA cache) | | 10 `admin`'s own password; seal `ld-admin` | human-intrinsic | Refused: `tools/bounded-execution-admission/fixtures/invalid/human-intrinsic-step.yaml` (BEA-7) | The examples are illustrative. They pin real files at a real commit, but the executor and its operations do not exist yet. ## 8. Conformance ```bash make bounded-execution-admission-test # validator tests make bounded-execution-admission-check # validate the examples python3 tools/bounded-execution-admission/validate.py check-approval python3 tools/bounded-execution-admission/validate.py digest ``` Agents may run these: they are offline and read-only. Writing an admission is preparation, and approving one is the founder's act. ## 9. Open items - T02: the carrier mapping with Approval Engine and Access (action name, actor and representation, digest equivalence, consume scope for the executor), and the executor runtime owner. - T03: the executor identity and its grants, matching the ceilings in the examples. - T07: enforcement of budget and attempts at run time, the founder's kill switch, and aggregate review through posture feedback (NK-WP-0031). - NK-WP-0040-T02: receipt emission, custody and schema in audit-core. - Recurring admissions (one approval for repeated runs of the same plan) are deliberately excluded from v0.1: every admission is single use.