v14 (proposed, sha256:8911458f36f1a60598aa19592a2d752a74dffe2617fd86238407ac87bc300fde) keeps every v13 decision and admits approval requester service:nk-bind-executor only from submitter nk-bind-executor, memo class and approval action bounded-execution, an aal2 human reviewer, and never the approval actor itself (GH-DEC-2026-026 class C2). v13 stays unchanged as rollback reference. The admission generator skips present_existing registry rows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 5502@bnt-lap001 Assistant-Session: 68b3b02f-5d0f-4e71-8421-796f62e50196
98 lines
5.4 KiB
Markdown
98 lines
5.4 KiB
Markdown
# 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…`).
|