# Owner note: compact-sitting v14, present-existing requester **Date:** 2026-11-01 **Owner:** access-engine (flex-auth PDP) **Workplan:** `workplans/FLEX-WP-0040-bounded-execution-pdp-gate.md`, task FLEX-WP-0040-T07 **Answers:** informed-decision `docs/decision-services-alignment-answer.md` (commit `0e66a33`, INFD-WP-0010), blocker 1 and open question 3. Doctrine: gate-house GH-DEC-2026-026 (an approval something executes against is class C2: human approver at aal2, and the actor that files the approval may never approve it). ## Package | Field | Value | | --- | --- | | package | `informed-decision.compact-sitting` | | version | `v14` (status `proposed`) | | package_digest | `sha256:8911458f36f1a60598aa19592a2d752a74dffe2617fd86238407ac87bc300fde` | | source | `examples/informed-decision-present-existing-review/policy.md` | | pin | `examples/informed-decision-present-existing-review/pin.json` | | rollback | v13 `sha256:31be5985…3711873`, unchanged in `examples/informed-decision-lifecycle-review/` | v14 lives in a new directory so the deployed v13 package, its pin and the release values stay byte-identical as the rollback reference. ## Behaviour Unchanged from v13: every exact-record and list-only decision; the attribute branch for requester `informed-decision` (same generated submitter/class sets, same reasons); any other requester is still `requester_mismatch` (or an earlier class/submitter refusal). Added: an owner-authored `present_existing_profiles` table with one entry: | approval_requester | intake_submitter | memo_class | approval_action | | --- | --- | --- | --- | | `service:nk-bind-executor` | `nk-bind-executor` | `bounded-execution` | `bounded-execution` | When `context.approval_requester` names this profile, the request is allowed (`present_existing_eligible`) only if, in addition to every v13 attribute guard (authenticated human, tenant, review group in the subject's groups, recipient for `list`, resource shape, `approval_human_control == true`, UUID approval id, digest shape, memo version >= 1): - `intake_submitter` and `memo_class` equal the profile (otherwise `unknown_submitter` / `unknown_class`); the generated sets are not widened, so the executor cannot use the create path and this requester cannot borrow state-hub's class; - `context.approval_action == "bounded-execution"` (otherwise, or when absent, `approval_action_not_admitted`); - the reviewing human holds KeyCape AAL2 with MFA `pwd`+`otp`, 900 s fresh for read and acts, 12 h for list (otherwise `identity_refused` / `stale_mfa`); - the reviewing human's `subject.id` is neither `service:nk-bind-executor` nor `nk-bind-executor` (`self_approval_refused`). The PDP still proves no pin. The consumer re-reads the approval and compares actor, human-control flag and binding digest before asking, as today. ## Consumer change required (informed-decision) v14 needs one new context key, `approval_action`, on present-existing requests only. Today `policy.build_request` accepts exactly five intake keys and `store._intake_context` does not carry the action, so a v14-pinned consumer would be refused with `approval_action_not_admitted` until both are changed. Suggested shape: record the approval's `binding.action` in the ledger metadata at intake (already verified there), emit it as `approval_action` for present-existing memos, and in `review._authorize` also compare the live `binding.action` to it. Requests for requester `informed-decision` may omit the key; v14 ignores it there. `tools/gen_informed_decision_admission.py` now accepts a registry row with a `present_existing` profile and skips it, so adding the nk-bind-executor row to informed-decision `deploy/intake-submitters.json` does not change the generated sets or break `--check`. ## Tests - 46 embedded Rego tests (32 from v13 unchanged, 14 for v14: positive read/acts/list, self-approval for acts and list, aal1/no-MFA/password-only, stale MFA, service subject, wrong or missing action, wrong submitter/class, other service requester, executor on the create path, and v13 requester unaffected by the new key or subject). - `internal/policy/informed_decision_present_existing_test.go`: v14 package valid, pin matches the computed digest, 12 engine evaluation cases, and the generator skips present-existing rows. - `go test ./internal/policy/` passes; generator `--check` in sync. ## Live steps (founder; none performed by this owner) 1. informed-decision lands the `approval_action` context change above. 2. Build the access-engine image from the commit carrying v14 (owner CI), scan it. 3. Update the review release values (`values/informed-decision-sitting.yaml` and the `access-engine` twin) to the new image digest and `--policy /opt/flex-auth/examples/informed-decision-present-existing-review/policy.md` (registry path may stay on the lifecycle-review directory or the identical copy); dry-run, diff, then upgrade the Helm release with `--atomic`. 4. Pin informed-decision to `informed-decision.compact-sitting` / `v14` / `sha256:8911458f36f1a60598aa19592a2d752a74dffe2617fd86238407ac87bc300fde` in the same release window: the `policy` object of its review runtime (`deploy/lifecycle/service.candidate.json` `runtime.json`, and `deploy/lifecycle/admission.candidate.json`). A version or digest mismatch fails closed. 5. Rollback: restore the release values in force before step 3 (v13 policy path and the image then deployed) and the consumer's v13 pin (`sha256:31be5985…`).