# Decision services alignment — Approval Engine owner answer Status: owner answer to the NetKingdom review `net-kingdom/docs/proposals/2026-10-31-decision-services-alignment-review.md` (hub message `81cafbf3-8d54-44c6-9235-6f46e95aaf74`), 2026-10-31. Also answers the pod-scoped ingress request (hub `39a3bffa-2c7c-4ca6-8a57-61e4ed94820f`). This is an engine-owner technical position, not a founder decision. Nothing here is deployed. ## Summary | Item | Position | | --- | --- | | Roles (§4.1) | **Accepted.** No change of role is needed here | | Present an existing approval (§4.2) | **Works on today's API.** Step 3 needs only `GET /v1/approvals/{id}` with `approval:read` | | S6 / T01 aal2 floor | **Implemented in source** (schema v7). Not yet released or deployed | | S6 / T02 `actor_consumes` | **Supported, still waiting.** Owner proposes splitting it from `principal_approves` | | §6.3 `presentation_ref` at create | **Declined as proposed.** Counter-proposal: the link goes on the entry, from the presenter | | Executor ingress | **Prepared in source:** `deploy/networkpolicies.yaml`, policy `approval-engine-bounded-executor`. Live apply is founder-run | ## 1. Roles The proposal matches this engine's INTENT and SCOPE: - The engine **keeps the object**: binding, entries, consume, supersede, revoke and outbox evidence. - **Only the actor creates.** `POST /v1/approvals` already refuses unless `binding.actor` equals the token subject. informed-decision stays a legitimate actor for approvals it uses itself. - The engine **stays not-an-inbox**: get by id, no list and no notification. Discovery belongs to State Hub (the index) and informed-decision (the surface). For the §4.2 verify step, informed-decision reads everything it needs from one `GET`: `status`, `entries`, `binding.human_control`, `binding.actor` and `binding.digest`. It should also check `binding.required_assurance` (T01, once deployed) when a C2 class requires aal2. With `human_control: true`, the engine already refuses an entry posted under informed-decision's own service token. The founder's entry must carry the founder's token, as it does today. One addition to §4.2 step 3: compare `validity` as well, so a memo cannot present an approval whose window has already passed or is far wider than the packet says. ## 2. S6 **T01 (aal2 floor): done in source.** - `POST /v1/approvals` accepts an optional `required_assurance: {"level": "aal1"|"aal2"|"aal3"}`. - `POST /entries` refuses a weaker, missing or unknown level from the verified token. - The claim reports `assurance_unsatisfied`, and `consume` refuses a persisted entry below the floor. - The floor is inherited on supersession and is not part of the act digest. - Legacy rows migrate to NULL, meaning no floor. The member appears in GET and the claim **only when declared**. The access fact reader rejects unknown members, so undeclared claims keep their exact bytes. Contract: `docs/approval-claim.md`. It needs a v7 image release and a founder-run rollout with a verified pre-v7 backup. Until then the executor keeps its own aal2 check. Whether KeyCape issues `aal2` stays KeyCape's question. **T02 (correspondence): supported, not implemented.** The owner proposes splitting it: - **`actor_consumes`** (consumer subject must equal `binding.actor`). It is low-risk and closes the denial-of-run gap: today any tenant service holding `approval:consume` can spend the object. It adds no new identity mapping, because the actor is already pinned to the creator's token subject. The owner is ready to implement it as an opt-in issue flag once Gate House (or the founder) agrees that `actor` means "the only consumer" when the flag is set. - **`principal_approves`** (entry subject must equal `binding.principal`). It stays waiting. NetKingdom's `principal` labels (for example `admin`) must first equal KeyCape subjects exactly, and C2 doctrine (S5) may name approvers that are not the principal. ## 3. Open question 6.3 — `presentation_ref` at create **Declined as proposed**, for three reasons: 1. **Ordering.** In §4.2 the actor creates the approval *before* it submits the memo, so no memo id exists at create. Setting the field later would make the object mutable outside its state machine. The binding is immutable by design. 2. **Wrong asserter.** A reference set by the actor is the actor's claim about where it will be presented. The evidence that matters is what the *approver* was shown, and only the presenting surface can state that. 3. **The join already exists in one direction.** The memo carries `approval_id` and the binding digest (§4.2 step 2), and audit-core can join on `(approval_id, subject, approved_at)`. **Counter-proposal (needs informed-decision agreement; not implemented):** an optional entry-level `presentation` record. The approving surface posts it with the entry, for example `{"memo_id", "revision", "view_hash"}`. The engine stores it on that entry, serves it in GET and emits it in the issuance and use threshold evidence. It is labelled surface-asserted: the engine checks its shape, not its truth. Identity, principal type and assurance still come only from the token. This closes Finding 5 (`view_hash` not inside the entry) without changing creation. If agreed, it becomes a new APPROVAL-WP-0007 task. ## 4. Executor ingress `approval-engine-bounded-executor` admits TCP 8080 to the approval-engine pod from pods labelled `app.kubernetes.io/name=bounded-executor` in namespace `sso`. The rule needs both selectors to match: they sit in one `from` element. It does not label `sso` and does not change `approval-engine-callers`. `tests/test_networkpolicies.py` holds that shape, so a split into two peers, which would admit all of `sso`, fails the test. Network admission grants no authority: the executor still needs its KeyCape token and scopes. To apply (founder-run): ```bash kubectl apply -f deploy/networkpolicies.yaml ``` ## Founder decisions needed 1. Release and roll out the v7 image (T01) when the pilot needs the engine-side floor. 2. Agree the T02 split, and that `actor_consumes` may be implemented now. 3. Accept or decline the entry-level `presentation` counter-proposal (with informed-decision). 4. Apply the executor ingress policy.