NK-WP-0056-T02 owner answer: PDP gate for bounded execution; FLEX-WP-0040 proposed
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

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
This commit is contained in:
tegwick 2026-10-31 14:19:08 +01:00
parent 7ef17639f8
commit f5b7a9071e
3 changed files with 217 additions and 0 deletions

View file

@ -49,6 +49,7 @@
| workplan | FLEX-WP-0037 | finished | — | workplans/FLEX-WP-0037-ops-warden-agt-custodian-actor.md |
| workplan | FLEX-WP-0038 | active | — | workplans/FLEX-WP-0038-wave2-resource-right-sizing.md |
| workplan | FLEX-WP-0039 | proposed | — | workplans/FLEX-WP-0039-core-pdp-production-readiness.md |
| workplan | FLEX-WP-0040 | proposed | — | workplans/FLEX-WP-0040-bounded-execution-pdp-gate.md |
| task | FLEX-WP-ADHOC-2026-10-03-T01 | done | — | workplans/ADHOC-2026-10-03.md |
| task | FLEX-WP-ADHOC-2026-10-03-T02 | wait | — | workplans/ADHOC-2026-10-03.md |
| task | FLEX-WP-ADHOC-2026-10-11-T01 | done | — | workplans/ADHOC-2026-10-11.md |
@ -238,6 +239,12 @@
| task | FLEX-WP-0039-T02 | todo | — | workplans/FLEX-WP-0039-core-pdp-production-readiness.md |
| task | FLEX-WP-0039-T03 | todo | — | workplans/FLEX-WP-0039-core-pdp-production-readiness.md |
| task | FLEX-WP-0039-T04 | todo | — | workplans/FLEX-WP-0039-core-pdp-production-readiness.md |
| task | FLEX-WP-0040-T01 | wait | — | workplans/FLEX-WP-0040-bounded-execution-pdp-gate.md |
| task | FLEX-WP-0040-T02 | wait | — | workplans/FLEX-WP-0040-bounded-execution-pdp-gate.md |
| task | FLEX-WP-0040-T03 | todo | — | workplans/FLEX-WP-0040-bounded-execution-pdp-gate.md |
| task | FLEX-WP-0040-T04 | todo | — | workplans/FLEX-WP-0040-bounded-execution-pdp-gate.md |
| task | FLEX-WP-0040-T05 | todo | — | workplans/FLEX-WP-0040-bounded-execution-pdp-gate.md |
| task | FLEX-WP-0040-T06 | wait | — | workplans/FLEX-WP-0040-bounded-execution-pdp-gate.md |
| intake | FLEX-IN-0001 | closed | — | intakes/intakes.md |
| intake | FLEX-IN-0002 | closed | — | intakes/intakes.md |
| intake | FLEX-IN-0003 | open | — | intakes/intakes.md |

View file

@ -0,0 +1,97 @@
# 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.

View file

@ -0,0 +1,113 @@
---
id: FLEX-WP-0040
type: workplan
title: "Bounded execution PDP gate: decide executor steps under an approved admission"
domain: infotech
repo: access-engine
status: proposed
flavor: implementation
owner: access-engine
created: "2026-10-31"
updated: "2026-10-31"
related: [NK-WP-0056, FLEX-WP-0039, FLEX-WP-0031]
---
# FLEX-WP-0040 — Bounded execution PDP gate
NetKingdom's proposed Bounded Execution Admission v0.1 (NK-WP-0056) lets the
founder approve, at `aal2`, an exact digested admission that a bounded executor
consumes once. Owner answer: `docs/bounded-execution-admission-pdp.md`. PDP
gating is in scope and recommended for production; the T06 pilot may run on
local enforcement without it.
Today the typed task path (`docs/trusted-service-task-source.md`) serves only
the secrets-engine v2 contract, requires an unconsumed claim, and the Approval
claim carries no approver assurance. Everything below lands as `proposed`
source, evaluated in tests only. No deployment, caller trust or credential is
admitted by this workplan.
## 1. Settle the claim inputs with approval-engine
```task
id: FLEX-WP-0040-T01
status: wait
priority: high
```
Wait: approval-engine answers to NK-WP-0056-T02 (binding to
`{admission_id, admission_digest}`, approver assurance `aal2`, consume scope)
plus our two additions: `consumed_by` and `consumed_at` in the claim. Record
the agreed claim fields here. Gate: written claim field list with owner ack.
## 2. Pack owner and semantic review
```task
id: FLEX-WP-0040-T02
status: wait
priority: medium
```
Wait: founder confirms the proposal — access-engine owns pack mechanics and
fixtures; NetKingdom (BEA owner) owns what a ceiling admits; gate-house reviews
authority-ceiling semantics. Gate: decision recorded.
## 3. Generalise the typed path caller map
```task
id: FLEX-WP-0040-T03
status: todo
priority: medium
```
Replace the single hard-wired secrets-engine mapping with an owner-installed
caller map; first new entry `system:serviceaccount:sso:nk-bind-executor` →
`service:nk-bind-executor`. Gate: existing secrets-engine v2 tests unchanged
and passing; unknown service accounts refuse; generic `/v1/check` still refuses
task execution.
## 4. Vocabulary and admission digest
```task
id: FLEX-WP-0040-T04
status: todo
priority: medium
depends_on: [FLEX-WP-0040-T01]
```
Add actions `start` and `execute-step` on resource type
`bounded-execution-admission` (system `net-kingdom`). The executor submits the
admission document; access-engine recomputes its digest by NK's BEA digest rule
and requires equality with the claim's admission digest. Gate: digest fixtures
shared with NetKingdom's validator agree byte-for-byte.
## 5. Policy pack `net-kingdom.bounded-execution` (DENY by default)
```task
id: FLEX-WP-0040-T05
status: todo
priority: medium
depends_on: [FLEX-WP-0040-T02, FLEX-WP-0040-T03, FLEX-WP-0040-T04]
```
`start`: claim valid and unconsumed, approver HUMAN at `aal2` and not the
executor, executor equals admission executor, now inside `window`.
`execute-step`: claim consumed once by this executor inside the window; step
id/operation/target/mode/scope match the digested `plan.steps` and lie inside
`scope_ceiling`; `max_concurrent` respected. Fixtures from
`net-kingdom/examples/bounded-execution-admission/bind-rotation-svc-authelia.yaml`
including out-of-ceiling, wrong executor, expired window, replayed consume and
missing assurance. Gate: pack validates, all fixtures pass, the existing
`apply` gap test stays as characterisation.
## 6. Live gate readiness
```task
id: FLEX-WP-0040-T06
status: wait
priority: low
depends_on: [FLEX-WP-0040-T05, FLEX-WP-0039-T01]
```
Wait: FLEX-WP-0039 readiness surface and a founder rollout decision for a pin
serving the pack, with the executor's declared fail-closed stance. Gate:
founder-approved rollout; no live change from this repo's agents.