# Bounded Execution Admission and the PDP — access-engine owner answer Answer to NetKingdom NK-WP-0056-T02 (owner request `net-kingdom/docs/proposals/2026-10-31-nk56-t02-owner-requests.md`, section "access-engine"), for the proposed standard `net-kingdom/canon/standards/bounded-execution-admission_v0.1.md` (BEA v0.1). Date: 2026-10-31. Status: owner answer and proposal. The founder and the named owners decide; nothing here is enabled or deployed. Follow-on work: `workplans/FLEX-WP-0040-bounded-execution-pdp-gate.md`. ## What exists today (from source) | Fact | Evidence | | --- | --- | | access-engine is the estate's only PDP and validates approvals as input claims; it never owns, mutates or consumes the approval object | `SCOPE.md` (One-liner, Out of Scope: approval object is approval-engine's) | | A typed task-execution path exists on `/v1/check`. It requires TokenReview caller mapping, a fixed owner-installed Approval reader (`GET /v1/approvals/{UUID}/claim`, no consume) and original/fresh claim correspondence before policy runs | `docs/trusted-service-task-source.md`, `internal/taskexecution/approval_source.go`, `internal/taskexecution/service_input.go` | | That path is hard-wired to one consumer: subject `secrets-engine`, transport principal `system:serviceaccount:secrets-engine:secrets-engine`, contract `SECRETS-EXEC-20261011-v1`, operation `metadata-apply-ccr`, exactly six OpenBao operations | `examples/secrets-engine-service-task-execution-v2/policy_package.md` (status `proposed`) | | The v2 policy requires `approval.consumed == false` at decision time | same file, `candidate_matches` | | The older secrets-engine `apply` rule ignores `execution_contract` content: an allow there is not exact task authority | `internal/policy/secrets_execution_gap_test.go` (gap characterization test) | | The Approval claim adapter carries id, native binding and PDP digest; it carries no approver assurance level | `third_party/approvalfact` (pinned copy of `approval-engine/adapters/go/approvalfact/claim.go`) | | Human callers on the typed path must present `aal2` + MFA from key-cape, at most 300 s old; that is the caller's assurance, not the approver's | `internal/taskexecution/identity.go` | | No chart, runtime admission or credential custody is enabled for the typed path | `docs/trusted-service-task-source.md` | So the mechanics a BEA gate needs exist in one consumer-specific shape. There is no `bounded-execution` action, no namespace for admissions, no caller mapping for `service:nk-bind-executor`, and no evaluator for BEA's `scope_ceiling` or `plan.steps`. ## Q1 — Should a PDP decision gate executor operations? **Answer: yes, in scope, recommended for production; not required for the pilot.** A decision "executor X may run operation O on target T under admission A" is the kind of decision this repository exists to make (SCOPE: estate's only PDP), and reading the admission as an approval claim through approval-engine matches the existing boundary (approval-engine owns the object, access-engine validates it as input). It adds what local enforcement cannot: an independent evaluator outside the executor's own code, a signed decision record per step with policy version and request digest, and a single place to revoke or narrow executor authority across admissions. Two shape points we propose (they change the request NetKingdom sketched): 1. **Two decisions, not one per step against an unconsumed claim.** The current typed path demands `consumed == false`. BEA consumes once *before* the first step (BEA-C6/C7). Proposed: - `start` — before consume: claim valid, unconsumed, approver human/`aal2`, executor == admission executor, now inside `window`, admission digest matches the claim's target. ALLOW is the precondition for the consume call. - `execute-step` — after consume: claim consumed exactly once, by this executor, inside the window; the step id, operation, target and required `mode/scope` match the digested plan and lie inside `scope_ceiling`. This needs approval-engine to expose `consumed_by` and `consumed_at` in the claim (question for approval-engine, alongside NK's question 3). 2. **The PDP never consumes.** Consume stays the executor's call to approval-engine, as today (`approval_source.go`: "no policy, retry, consume or effect lives here"). ## Q2 — What is needed, who owns it, timeline | Item | Status | Proposal | | --- | --- | --- | | Action vocabulary `start`, `execute-step` on resource type `bounded-execution-admission`, system `net-kingdom` | needs change | access-engine adds; vocabulary only, no allow | | Typed path generalised from the single secrets-engine mapping to an owner-installed caller map (first entry `system:serviceaccount:sso:nk-bind-executor` → `service:nk-bind-executor`) | needs change | access-engine; keeps the existing secrets-engine behaviour byte-identical | | Admission input: the executor submits the admission document; access-engine recomputes its digest and requires equality with the claim's `target.admission_digest` | needs change | access-engine; canonical digest rule must match NK's BEA digest definition | | `execution_contract` coverage: evaluate step id/operation/target/mode/scope against `plan.steps` and `scope_ceiling`, plus window and blast-radius (`max_concurrent`) | needs change | in the new pack; the old `apply` gap (see test) is not reused and stays characterised | | Approver assurance `aal2` (BEA-C4) | **missing input** | approval-engine must carry approver assurance in the claim; access-engine will not infer it | | `consumed_by` / `consumed_at` in the claim | **missing input** | approval-engine | | Policy pack `net-kingdom.bounded-execution` | proposal | **Pack mechanics and fixtures: access-engine. Semantic content (what a ceiling admits): NetKingdom as BEA standard owner, reviewed by gate-house for authority ceilings.** Founder to confirm owner | | Deployment of a pin serving the pack, caller trust, Approval reader credential | gated | founder/platform admission, as for every pin; not in this workplan's authority | **Timeline (proposal).** Source work (vocabulary, generalised caller map, pack with fixtures, DENY-by-default until inputs exist) can be done in about one to two weeks of repository work once approval-engine answers the claim-field questions. It lands as `proposed`, evaluated only in tests. A live gate follows FLEX-WP-0039 (per-pin readiness and policy import) and a founder rollout decision. Realistic: source-ready mid/late November 2026, live after the pilot. It does not block the pilot window in the BEA example (2026-11-03). ## Q3 — Pilot with local enforcement only **Answer: acceptable, with conditions.** - The executor's validator (BEA-C1..C7 against the carrier) plus a namespaced Kubernetes Role and narrowly scoped OpenBao/LLDAP credentials are the enforcement for T06. That is a consumer-side PEP and is the consumer's to own. - The pilot must not claim PDP gating. Its receipt should state the PDP decision as `not-evaluated` (no decision id), so later evidence cannot be mistaken for a flex-auth ALLOW. - Do not call the existing secrets-engine `apply` rule or the generic `/v1/check` as a stand-in: the former ignores `execution_contract`, the latter refuses task execution. - When the gate goes live, the executor's stance on PDP unavailability is fail-closed (declared by the consumer, per SCOPE "Out of Scope: fail-open"). - Revisit after the pilot: the second admission should not run without the PDP gate unless the founder records an explicit exception.