access-engine/docs/bounded-execution-admission-pdp.md
tegwick f5b7a9071e
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
NK-WP-0056-T02 owner answer: PDP gate for bounded execution; FLEX-WP-0040 proposed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 994874@bnt-lap001
Assistant-Session: 6017c416-d619-47eb-bd1a-f670a02d7d87
2026-10-31 14:19:08 +01:00

7.5 KiB

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.