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
97 lines
7.5 KiB
Markdown
97 lines
7.5 KiB
Markdown
# 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.
|