Updated by fix-consistency on 2026-10-31: - workplan status: ready → active Assistant: claude-code Assistant-Model: opus Assistant-Process: 994874@bnt-lap001 Assistant-Session: 6017c416-d619-47eb-bd1a-f670a02d7d87
101 lines
3.7 KiB
Markdown
101 lines
3.7 KiB
Markdown
---
|
|
id: APPROVAL-WP-0007
|
|
type: workplan
|
|
title: "Bounded-execution admission carrier: assurance floor, correspondence and revoker evidence"
|
|
domain: infotech
|
|
repo: approval-engine
|
|
status: active
|
|
flavor: implementation
|
|
owner: approval-engine
|
|
topic_slug: netkingdom
|
|
created: "2026-10-31"
|
|
updated: "2026-10-31"
|
|
depends_on: []
|
|
state_hub_workstream_id: "af365506-f451-50b5-a0a2-f0ba9a0a4d9c"
|
|
---
|
|
|
|
Demand: NetKingdom NK-WP-0056-T02 owner request (hub message
|
|
40344380-ea33-4670-9b27-dafca1699d36) to carry a Bounded Execution Admission
|
|
v0.1 (proposed) as an approval. Owner answer:
|
|
`docs/bounded-execution-admission-carrier.md`. The binding, consume and
|
|
revoke already work. This plan closes the engine-side gaps the answer found.
|
|
Every change is opt-in at issue, so existing approvals and consumers keep
|
|
their behavior. Native digest, CAS consumption and no-unconsume are unchanged.
|
|
|
|
## Declared minimum approver assurance
|
|
|
|
```task
|
|
id: APPROVAL-WP-0007-T01
|
|
status: todo
|
|
priority: high
|
|
state_hub_task_id: "9ce0aca8-7694-53c6-a76a-f78d395a9861"
|
|
```
|
|
|
|
Add an optional `required_assurance` (minimum `level`, ordered aal1 < aal2 <
|
|
aal3) to `POST /v1/approvals`. Store it and serve it in the object and the
|
|
claim, and inherit it on supersede. `add_entry` refuses an entry whose
|
|
verified token `assurance.level` is weaker or missing. `_evaluate` and
|
|
`consume` refuse when an existing entry does not meet it. Schema migration
|
|
leaves old rows NULL, meaning no floor. Tests cover aal1 refused, aal2
|
|
accepted, missing level refused, supersede inheritance and the claim
|
|
reason_code. Serves BEA-C4. Whether KeyCape emits `aal2` is KeyCape's
|
|
question, outside this plan.
|
|
|
|
## Opt-in approver and consumer correspondence
|
|
|
|
```task
|
|
id: APPROVAL-WP-0007-T02
|
|
status: wait
|
|
priority: medium
|
|
state_hub_task_id: "9657820d-23f9-54d9-920c-8f2a72110ad0"
|
|
```
|
|
|
|
Proposal for owner and Gate House agreement before implementation, because
|
|
it gives `principal` and `actor` an enforced meaning. Two optional issue
|
|
flags:
|
|
|
|
- `principal_approves`: every entry subject must equal `binding.principal`.
|
|
- `actor_consumes`: the consuming subject must equal `binding.actor`.
|
|
|
|
Today any human with `approval:approve` can approve, and any tenant service
|
|
with `approval:consume` can spend the object (a denial-of-run risk). Wait
|
|
reason: semantic decision. NetKingdom's actor and principal strings must also
|
|
match KeyCape subjects exactly.
|
|
|
|
## Revoker identity in revocation evidence
|
|
|
|
```task
|
|
id: APPROVAL-WP-0007-T03
|
|
status: todo
|
|
priority: medium
|
|
state_hub_task_id: "7ceb5ffd-3ba8-5e9d-96a2-5e89c38a5c43"
|
|
```
|
|
|
|
Record the verified revoker's subject, principal_type and assurance, plus an
|
|
optional bounded `reason`, in the `approval.revocation` outbox event. Persist
|
|
them on the object (the `revoked_by` fields) without changing the CAS or
|
|
terminal semantics. This is the evidence for the founder's pre-start kill
|
|
switch (NK-WP-0056-T07). Do not require the revoker to equal the principal:
|
|
revocation must stay possible without the holder.
|
|
|
|
## Synthetic bounded-execution carrier proof
|
|
|
|
```task
|
|
id: APPROVAL-WP-0007-T04
|
|
status: todo
|
|
priority: medium
|
|
state_hub_task_id: "673890fe-3d49-5fe3-8ad7-c8c73e4d9376"
|
|
```
|
|
|
|
Add an in-process test and an example request covering the full path: the
|
|
executor (service) creates the request (`action: bounded-execution`,
|
|
`target: {admission_id, admission_digest}`, `human_control: true`,
|
|
`pdp_path: false`); a human aal2 entry approves it; GET binding comparison;
|
|
consume with `request_digest` = admission digest; idempotent retry; a
|
|
different digest returns 409; revoke before consume gives 409 on consume;
|
|
consumption outside the window is refused. Synthetic fixtures only, with no
|
|
live service.
|
|
|
|
## Founder decision 2026-10-31
|
|
|
|
Approved by the founder (`proposed` -> `ready`) after the NK-WP-0056-T02 owner answers (hub decision 19afd15e).
|