2026-08-29 11:58:28 +02:00
|
|
|
---
|
|
|
|
|
id: APPROVAL-WP-0001
|
|
|
|
|
type: workplan
|
|
|
|
|
title: "v0.7 alignment and the engine spine"
|
|
|
|
|
domain: infotech
|
|
|
|
|
repo: approval-engine
|
2026-09-01 23:45:48 +02:00
|
|
|
status: finished
|
2026-08-29 11:58:28 +02:00
|
|
|
owner: grok
|
|
|
|
|
topic_slug: netkingdom
|
|
|
|
|
created: "2026-08-29"
|
2026-09-01 23:45:48 +02:00
|
|
|
updated: "2026-09-01"
|
2026-08-29 12:01:16 +02:00
|
|
|
state_hub_workstream_id: "546f2fae-c53e-5ea5-8c63-320118d8ee1e"
|
2026-08-29 11:58:28 +02:00
|
|
|
---
|
|
|
|
|
|
|
|
|
|
# APPROVAL-WP-0001 — v0.7 alignment and the engine spine
|
|
|
|
|
|
|
|
|
|
Evolve this repository from a v0.5 seed INTENT into a v0.7-aligned PIP with
|
|
|
|
|
the contracts and first implementation that make Canon `T-06` passable and
|
|
|
|
|
unblock `FLEX-WP-0017` T03/T05.
|
|
|
|
|
|
|
|
|
|
Source:
|
|
|
|
|
|
|
|
|
|
- `net-kingdom/canon/standards/security-layer-model_v0.7.md` (accepted)
|
|
|
|
|
- `net-kingdom/SECURITY-COMPANION.md` v0.2
|
|
|
|
|
- `history/2026-08-29-security-layer-model-v0.7-scope-intent-review.md`
|
|
|
|
|
- `INTENT.md`, `SCOPE.md`, `layer.yaml`
|
|
|
|
|
|
|
|
|
|
**Rule of the workplan.** Contracts before code. Consumption is not
|
|
|
|
|
implemented until `GH-WP-0002-T06` settles it. A reachable mutation that
|
|
|
|
|
guesses the three races is a defect, not a prototype.
|
|
|
|
|
|
|
|
|
|
Peer work this does not own and must not duplicate: `GH-WP-0002` (T02 outbox
|
|
|
|
|
wire, T03 revocation failure mode, T04 detection surface, T06 consumption
|
|
|
|
|
ordering), `FLEX-WP-0017` T03/T05, `AUDIT-IN-0001`.
|
|
|
|
|
|
|
|
|
|
## T01 — Align declaration to the accepted statute
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
id: APPROVAL-WP-0001-T01
|
|
|
|
|
status: done
|
|
|
|
|
priority: high
|
2026-08-29 12:01:16 +02:00
|
|
|
state_hub_task_id: "090ab9d5-1467-5a82-b3cd-ac4215bec0f0"
|
2026-08-29 11:58:28 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
2026-08-29: INTENT frontmatter `layer: Engine` / `role: PIP`; aligned to
|
|
|
|
|
v0.7 (PIP typing, threat decomposition, load-bearing cadence, custody
|
|
|
|
|
closed, consumption as mutation, issuer/freshness, Railiance non-axis).
|
|
|
|
|
SCOPE.md written as first-cut boundary with standard sections. `layer.yaml`
|
|
|
|
|
declared in this repository's own voice. Review filed under `history/`.
|
|
|
|
|
Registered with State Hub (`infotech`, topic custodian). Register's
|
|
|
|
|
bootstrap workplan was discarded: it collided on `APPROVAL-WP-0001` and
|
|
|
|
|
its three tasks are already discharged by this file, `AGENTS.md`, and
|
|
|
|
|
`SCOPE.md`.
|
|
|
|
|
|
|
|
|
|
## T02 — Publish the approval claim contract
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
id: APPROVAL-WP-0001-T02
|
Implement the engine spine: claim, outbox, machine, API
Contracts first (T02–T04): approval claim schema with issuer, freshness,
and binding digest; local transactional outbox wire; load-bearing cadence
as heartbeat or reconciliation (layer.yaml declared).
Then the object (T06–T08): SQLite closed state machine, CAS supersession,
distinct-approver fail-closed, revocation without holder cooperation,
outbox insert in the same transaction. Tests fail the mutation when
emission fails, and revoke while the drain sink is down.
Introspection GET /v1/approvals/{id}/claim is a PIP fact, not a decision.
No public consume (T05 waits on GH-WP-0002-T06). Canon T-06 coverage for
wrong binding, expiry, revoke, and supersede.
FLEX-WP-0017 T03 is unblocked on this object; T05 remains blocked only on
consumption ordering.
Assistant: grok
Assistant-Session: 01a04ceb-2057-7e20-b0f9-c282964d5dd9
2026-08-29 12:52:49 +02:00
|
|
|
status: done
|
2026-08-29 11:58:28 +02:00
|
|
|
priority: high
|
2026-08-29 12:01:16 +02:00
|
|
|
state_hub_task_id: "ca2ec789-b760-525a-9960-95d15760191e"
|
2026-08-29 11:58:28 +02:00
|
|
|
```
|
|
|
|
|
|
Implement the engine spine: claim, outbox, machine, API
Contracts first (T02–T04): approval claim schema with issuer, freshness,
and binding digest; local transactional outbox wire; load-bearing cadence
as heartbeat or reconciliation (layer.yaml declared).
Then the object (T06–T08): SQLite closed state machine, CAS supersession,
distinct-approver fail-closed, revocation without holder cooperation,
outbox insert in the same transaction. Tests fail the mutation when
emission fails, and revoke while the drain sink is down.
Introspection GET /v1/approvals/{id}/claim is a PIP fact, not a decision.
No public consume (T05 waits on GH-WP-0002-T06). Canon T-06 coverage for
wrong binding, expiry, revoke, and supersede.
FLEX-WP-0017 T03 is unblocked on this object; T05 remains blocked only on
consumption ordering.
Assistant: grok
Assistant-Session: 01a04ceb-2057-7e20-b0f9-c282964d5dd9
2026-08-29 12:52:49 +02:00
|
|
|
2026-08-29: `schemas/approval_claim.schema.json`, `docs/approval-claim.md`,
|
|
|
|
|
examples. Native digest is sorted-key JSON of action/actor/principal/purpose/target;
|
|
|
|
|
optional `pdp_digest` records `NewDecisionBinding.request_digest` at issue.
|
|
|
|
|
Yields to Taxonomy §17.
|
|
|
|
|
|
2026-08-29 11:58:28 +02:00
|
|
|
Specify the input claim `access-engine` consumes: approval identifier,
|
|
|
|
|
canonical-binding digest over the same binding the PDP already computes,
|
|
|
|
|
issuer (this engine), and freshness. Schema and examples in-repo.
|
|
|
|
|
|
|
|
|
|
Until Taxonomy's request-claim schema exists (statute §17, ownership
|
|
|
|
|
proposed not assigned), this is the boundary contract. Mark it as yielding
|
|
|
|
|
to Taxonomy; do not treat a local shape as permanent.
|
|
|
|
|
|
|
|
|
|
Acceptance: a document `access-engine` can implement a consumer against
|
|
|
|
|
without reading this engine's source; wrong-action / wrong-target /
|
|
|
|
|
wrong-scope are distinguishable; a PDP can state a deadline for this input
|
|
|
|
|
class.
|
|
|
|
|
|
|
|
|
|
## T03 — Specify the local transactional-outbox contract
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
id: APPROVAL-WP-0001-T03
|
Implement the engine spine: claim, outbox, machine, API
Contracts first (T02–T04): approval claim schema with issuer, freshness,
and binding digest; local transactional outbox wire; load-bearing cadence
as heartbeat or reconciliation (layer.yaml declared).
Then the object (T06–T08): SQLite closed state machine, CAS supersession,
distinct-approver fail-closed, revocation without holder cooperation,
outbox insert in the same transaction. Tests fail the mutation when
emission fails, and revoke while the drain sink is down.
Introspection GET /v1/approvals/{id}/claim is a PIP fact, not a decision.
No public consume (T05 waits on GH-WP-0002-T06). Canon T-06 coverage for
wrong binding, expiry, revoke, and supersede.
FLEX-WP-0017 T03 is unblocked on this object; T05 remains blocked only on
consumption ordering.
Assistant: grok
Assistant-Session: 01a04ceb-2057-7e20-b0f9-c282964d5dd9
2026-08-29 12:52:49 +02:00
|
|
|
status: done
|
2026-08-29 11:58:28 +02:00
|
|
|
priority: high
|
2026-08-29 12:01:16 +02:00
|
|
|
state_hub_task_id: "a2eb2e8f-9b49-598e-b4a1-fb93e65f1bf3"
|
2026-08-29 11:58:28 +02:00
|
|
|
```
|
|
|
|
|
|
Implement the engine spine: claim, outbox, machine, API
Contracts first (T02–T04): approval claim schema with issuer, freshness,
and binding digest; local transactional outbox wire; load-bearing cadence
as heartbeat or reconciliation (layer.yaml declared).
Then the object (T06–T08): SQLite closed state machine, CAS supersession,
distinct-approver fail-closed, revocation without holder cooperation,
outbox insert in the same transaction. Tests fail the mutation when
emission fails, and revoke while the drain sink is down.
Introspection GET /v1/approvals/{id}/claim is a PIP fact, not a decision.
No public consume (T05 waits on GH-WP-0002-T06). Canon T-06 coverage for
wrong binding, expiry, revoke, and supersede.
FLEX-WP-0017 T03 is unblocked on this object; T05 remains blocked only on
consumption ordering.
Assistant: grok
Assistant-Session: 01a04ceb-2057-7e20-b0f9-c282964d5dd9
2026-08-29 12:52:49 +02:00
|
|
|
2026-08-29: `docs/outbox-contract.md`. Classes issuance/use/supersession/revocation/heartbeat.
|
|
|
|
|
Payload is `audit-core.event.v1alpha1`. Synchronous `audit-core` inside the
|
|
|
|
|
mutation transaction is named forbidden.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-08-29 11:58:28 +02:00
|
|
|
Event classes (issuance, use, supersession, revocation, and the heartbeat
|
|
|
|
|
class T04 needs), same transaction as the object mutation, queue local to
|
|
|
|
|
this engine, at-least-once into the outbox (`audit-core` dedupes on event
|
|
|
|
|
id). No synchronous `audit-core` call inside the state-change transaction.
|
|
|
|
|
|
|
|
|
|
Coordinate with `GH-WP-0002-T02`; do not author doctrine this engine does
|
|
|
|
|
not own. INTENT already states the boundary and the locality.
|
|
|
|
|
|
|
|
|
|
Acceptance: a wire contract another repository can review; an implementer
|
|
|
|
|
cannot satisfy it by emitting synchronously to `audit-core`.
|
|
|
|
|
|
|
|
|
|
## T04 — Declare load-bearing cadence as heartbeat or reconciliation
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
id: APPROVAL-WP-0001-T04
|
Implement the engine spine: claim, outbox, machine, API
Contracts first (T02–T04): approval claim schema with issuer, freshness,
and binding digest; local transactional outbox wire; load-bearing cadence
as heartbeat or reconciliation (layer.yaml declared).
Then the object (T06–T08): SQLite closed state machine, CAS supersession,
distinct-approver fail-closed, revocation without holder cooperation,
outbox insert in the same transaction. Tests fail the mutation when
emission fails, and revoke while the drain sink is down.
Introspection GET /v1/approvals/{id}/claim is a PIP fact, not a decision.
No public consume (T05 waits on GH-WP-0002-T06). Canon T-06 coverage for
wrong binding, expiry, revoke, and supersede.
FLEX-WP-0017 T03 is unblocked on this object; T05 remains blocked only on
consumption ordering.
Assistant: grok
Assistant-Session: 01a04ceb-2057-7e20-b0f9-c282964d5dd9
2026-08-29 12:52:49 +02:00
|
|
|
status: done
|
2026-08-29 11:58:28 +02:00
|
|
|
priority: high
|
2026-08-29 12:01:16 +02:00
|
|
|
state_hub_task_id: "fce0df25-0106-5c0a-8187-87b956ca6220"
|
2026-08-29 11:58:28 +02:00
|
|
|
```
|
|
|
|
|
|
Implement the engine spine: claim, outbox, machine, API
Contracts first (T02–T04): approval claim schema with issuer, freshness,
and binding digest; local transactional outbox wire; load-bearing cadence
as heartbeat or reconciliation (layer.yaml declared).
Then the object (T06–T08): SQLite closed state machine, CAS supersession,
distinct-approver fail-closed, revocation without holder cooperation,
outbox insert in the same transaction. Tests fail the mutation when
emission fails, and revoke while the drain sink is down.
Introspection GET /v1/approvals/{id}/claim is a PIP fact, not a decision.
No public consume (T05 waits on GH-WP-0002-T06). Canon T-06 coverage for
wrong binding, expiry, revoke, and supersede.
FLEX-WP-0017 T03 is unblocked on this object; T05 remains blocked only on
consumption ordering.
Assistant: grok
Assistant-Session: 01a04ceb-2057-7e20-b0f9-c282964d5dd9
2026-08-29 12:52:49 +02:00
|
|
|
2026-08-29: `cadence.yaml` + `docs/emission-cadence.md`. `layer.yaml`
|
|
|
|
|
`evidence.cadence_status: declared`. Missing heartbeat and count divergence
|
|
|
|
|
are findings. Rate monitoring forbidden.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-08-29 11:58:28 +02:00
|
|
|
Approval evidence is load-bearing and low-volume. Rate monitoring is the
|
|
|
|
|
wrong form (statute §9.6). Publish the source-side declaration: expected
|
|
|
|
|
classes, the heartbeat (*nothing to report*, signed, itself able to go
|
|
|
|
|
missing) and/or reconciliation of this engine's transitions against
|
|
|
|
|
`audit-core` event counts per class.
|
|
|
|
|
|
|
|
|
|
Coordinate with `GH-WP-0002-T04`, which is the detection surface. This
|
|
|
|
|
task is the source that surface reads.
|
|
|
|
|
|
|
|
|
|
Acceptance: `layer.yaml` `evidence.cadence_status` is no longer
|
|
|
|
|
`undeclared`; a missing heartbeat or a count divergence is specified as a
|
|
|
|
|
finding, not as a log line.
|
|
|
|
|
|
2026-09-01 23:45:48 +02:00
|
|
|
## T05 — Implement the assented consumption ordering contract
|
2026-08-29 11:58:28 +02:00
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
id: APPROVAL-WP-0001-T05
|
2026-09-01 23:45:48 +02:00
|
|
|
status: done
|
2026-08-29 11:58:28 +02:00
|
|
|
priority: high
|
2026-08-29 12:01:16 +02:00
|
|
|
state_hub_task_id: "204bdfeb-a669-569e-a654-10c1a9fcacbc"
|
2026-08-29 11:58:28 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Blocked on `GH-WP-0002-T06` / `access-engine`. The three races (allow never
|
|
|
|
|
consumed; double consumption; consume after failed action) are named in
|
|
|
|
|
statute §9.7.4 and §16. This engine performs the mutation; it does not
|
|
|
|
|
choose the signal, the point relative to the decision, or the handling of
|
|
|
|
|
the three states.
|
|
|
|
|
|
|
|
|
|
Acceptance: a written contract both engines have assented to, recorded
|
|
|
|
|
here, *then* a consume path. Until then, no `consume` endpoint, no inferred
|
|
|
|
|
consumption from a decision record, no demo that "just consumes on allow".
|
|
|
|
|
|
2026-09-01 23:45:48 +02:00
|
|
|
2026-09-01: Gate House resolved the blocker in `GH-DEC-2026-003` and
|
|
|
|
|
`docs/contracts/approval-consumption.md`, with an explicit State Hub handoff
|
|
|
|
|
from gate-house (`2ade6044`). Implemented
|
|
|
|
|
`POST /v1/approvals/{id}/consume`: the PEP presents the PDP decision binding's
|
|
|
|
|
`request_digest` after ALLOW and before the protected side effect. The SQLite
|
|
|
|
|
CAS stores the digest and optional decision id; same-digest retries are
|
|
|
|
|
idempotent success, different digests conflict, and there is no unconsume.
|
|
|
|
|
The `approval.use` outbox row remains in the same transaction. Concurrency,
|
|
|
|
|
rollback, API-shape, legacy-database migration, and consume-side T-06 tests are
|
|
|
|
|
included.
|
|
|
|
|
|
2026-08-29 11:58:28 +02:00
|
|
|
## T06 — Durable object, closed state machine, authenticated entries
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
id: APPROVAL-WP-0001-T06
|
Implement the engine spine: claim, outbox, machine, API
Contracts first (T02–T04): approval claim schema with issuer, freshness,
and binding digest; local transactional outbox wire; load-bearing cadence
as heartbeat or reconciliation (layer.yaml declared).
Then the object (T06–T08): SQLite closed state machine, CAS supersession,
distinct-approver fail-closed, revocation without holder cooperation,
outbox insert in the same transaction. Tests fail the mutation when
emission fails, and revoke while the drain sink is down.
Introspection GET /v1/approvals/{id}/claim is a PIP fact, not a decision.
No public consume (T05 waits on GH-WP-0002-T06). Canon T-06 coverage for
wrong binding, expiry, revoke, and supersede.
FLEX-WP-0017 T03 is unblocked on this object; T05 remains blocked only on
consumption ordering.
Assistant: grok
Assistant-Session: 01a04ceb-2057-7e20-b0f9-c282964d5dd9
2026-08-29 12:52:49 +02:00
|
|
|
status: done
|
2026-08-29 11:58:28 +02:00
|
|
|
priority: high
|
2026-08-29 12:01:16 +02:00
|
|
|
state_hub_task_id: "44c4997b-6833-5540-a554-0e24210809f2"
|
2026-08-29 11:58:28 +02:00
|
|
|
```
|
|
|
|
|
|
Implement the engine spine: claim, outbox, machine, API
Contracts first (T02–T04): approval claim schema with issuer, freshness,
and binding digest; local transactional outbox wire; load-bearing cadence
as heartbeat or reconciliation (layer.yaml declared).
Then the object (T06–T08): SQLite closed state machine, CAS supersession,
distinct-approver fail-closed, revocation without holder cooperation,
outbox insert in the same transaction. Tests fail the mutation when
emission fails, and revoke while the drain sink is down.
Introspection GET /v1/approvals/{id}/claim is a PIP fact, not a decision.
No public consume (T05 waits on GH-WP-0002-T06). Canon T-06 coverage for
wrong binding, expiry, revoke, and supersede.
FLEX-WP-0017 T03 is unblocked on this object; T05 remains blocked only on
consumption ordering.
Assistant: grok
Assistant-Session: 01a04ceb-2057-7e20-b0f9-c282964d5dd9
2026-08-29 12:52:49 +02:00
|
|
|
2026-08-29: SQLite object + closed machine in `approval_engine/store.py`.
|
|
|
|
|
CAS supersession (concurrent test), distinct-approver fail-closed, revocation
|
|
|
|
|
without holder cooperation. `_cas_consume` is unexported.
|
|
|
|
|
|
2026-09-01 23:45:48 +02:00
|
|
|
2026-09-01: the assented T05 contract replaced the private seam with the public
|
|
|
|
|
digest-bound `consume` mutation and added an in-place SQLite column migration.
|
|
|
|
|
|
Implement the engine spine: claim, outbox, machine, API
Contracts first (T02–T04): approval claim schema with issuer, freshness,
and binding digest; local transactional outbox wire; load-bearing cadence
as heartbeat or reconciliation (layer.yaml declared).
Then the object (T06–T08): SQLite closed state machine, CAS supersession,
distinct-approver fail-closed, revocation without holder cooperation,
outbox insert in the same transaction. Tests fail the mutation when
emission fails, and revoke while the drain sink is down.
Introspection GET /v1/approvals/{id}/claim is a PIP fact, not a decision.
No public consume (T05 waits on GH-WP-0002-T06). Canon T-06 coverage for
wrong binding, expiry, revoke, and supersede.
FLEX-WP-0017 T03 is unblocked on this object; T05 remains blocked only on
consumption ordering.
Assistant: grok
Assistant-Session: 01a04ceb-2057-7e20-b0f9-c282964d5dd9
2026-08-29 12:52:49 +02:00
|
|
|
|
|
|
|
|
|
2026-08-29 11:58:28 +02:00
|
|
|
Depends on T02 and T03. Implement the object and the machine in SCOPE:
|
|
|
|
|
identifiers; bindings (action, target, actor, principal, purpose, validity
|
|
|
|
|
window, approvers); authenticated entries; distinct-approver counting;
|
|
|
|
|
CAS supersession; validity/expiry; revocation without holder cooperation.
|
|
|
|
|
|
|
|
|
|
Do not ship a public `consume` until T05 is unblocked. Internal CAS
|
|
|
|
|
consumption may exist behind an unexported seam so T08 can be tested
|
|
|
|
|
without guessing the ordering contract.
|
|
|
|
|
|
|
|
|
|
Acceptance: state transitions are total and reconstructable; two concurrent
|
|
|
|
|
supersessions cannot both succeed; distinct-approver requirements fail
|
|
|
|
|
closed on duplicates; revocation is effective at the next introspection.
|
|
|
|
|
|
|
|
|
|
## T07 — Introspection API as input claims
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
id: APPROVAL-WP-0001-T07
|
Implement the engine spine: claim, outbox, machine, API
Contracts first (T02–T04): approval claim schema with issuer, freshness,
and binding digest; local transactional outbox wire; load-bearing cadence
as heartbeat or reconciliation (layer.yaml declared).
Then the object (T06–T08): SQLite closed state machine, CAS supersession,
distinct-approver fail-closed, revocation without holder cooperation,
outbox insert in the same transaction. Tests fail the mutation when
emission fails, and revoke while the drain sink is down.
Introspection GET /v1/approvals/{id}/claim is a PIP fact, not a decision.
No public consume (T05 waits on GH-WP-0002-T06). Canon T-06 coverage for
wrong binding, expiry, revoke, and supersede.
FLEX-WP-0017 T03 is unblocked on this object; T05 remains blocked only on
consumption ordering.
Assistant: grok
Assistant-Session: 01a04ceb-2057-7e20-b0f9-c282964d5dd9
2026-08-29 12:52:49 +02:00
|
|
|
status: done
|
2026-08-29 11:58:28 +02:00
|
|
|
priority: high
|
2026-08-29 12:01:16 +02:00
|
|
|
state_hub_task_id: "ea51499d-ced5-50fa-b852-396719a8c0f4"
|
2026-08-29 11:58:28 +02:00
|
|
|
```
|
|
|
|
|
|
Implement the engine spine: claim, outbox, machine, API
Contracts first (T02–T04): approval claim schema with issuer, freshness,
and binding digest; local transactional outbox wire; load-bearing cadence
as heartbeat or reconciliation (layer.yaml declared).
Then the object (T06–T08): SQLite closed state machine, CAS supersession,
distinct-approver fail-closed, revocation without holder cooperation,
outbox insert in the same transaction. Tests fail the mutation when
emission fails, and revoke while the drain sink is down.
Introspection GET /v1/approvals/{id}/claim is a PIP fact, not a decision.
No public consume (T05 waits on GH-WP-0002-T06). Canon T-06 coverage for
wrong binding, expiry, revoke, and supersede.
FLEX-WP-0017 T03 is unblocked on this object; T05 remains blocked only on
consumption ordering.
Assistant: grok
Assistant-Session: 01a04ceb-2057-7e20-b0f9-c282964d5dd9
2026-08-29 12:52:49 +02:00
|
|
|
2026-08-29: `GET /v1/approvals/{id}/claim`. Tests forbid decision-shaped
|
2026-09-01 23:45:48 +02:00
|
|
|
keys and `/v1/check` / `/authorize`. Store unavailable → 503.
|
Implement the engine spine: claim, outbox, machine, API
Contracts first (T02–T04): approval claim schema with issuer, freshness,
and binding digest; local transactional outbox wire; load-bearing cadence
as heartbeat or reconciliation (layer.yaml declared).
Then the object (T06–T08): SQLite closed state machine, CAS supersession,
distinct-approver fail-closed, revocation without holder cooperation,
outbox insert in the same transaction. Tests fail the mutation when
emission fails, and revoke while the drain sink is down.
Introspection GET /v1/approvals/{id}/claim is a PIP fact, not a decision.
No public consume (T05 waits on GH-WP-0002-T06). Canon T-06 coverage for
wrong binding, expiry, revoke, and supersede.
FLEX-WP-0017 T03 is unblocked on this object; T05 remains blocked only on
consumption ordering.
Assistant: grok
Assistant-Session: 01a04ceb-2057-7e20-b0f9-c282964d5dd9
2026-08-29 12:52:49 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-08-29 11:58:28 +02:00
|
|
|
Depends on T02 and T06. An API that answers INTENT's question and returns
|
|
|
|
|
the T02 claim. No endpoint answers "may this actor do X". Fail-closed when
|
|
|
|
|
this engine's own store is unavailable.
|
|
|
|
|
|
|
|
|
|
Acceptance: `access-engine` can fetch a claim; a decision rendered against
|
|
|
|
|
approval A for request R cannot be replayed for R' on the digest; tests
|
|
|
|
|
forbid a decision-shaped response.
|
|
|
|
|
|
|
|
|
|
## T08 — Local outbox in the mutation transaction
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
id: APPROVAL-WP-0001-T08
|
Implement the engine spine: claim, outbox, machine, API
Contracts first (T02–T04): approval claim schema with issuer, freshness,
and binding digest; local transactional outbox wire; load-bearing cadence
as heartbeat or reconciliation (layer.yaml declared).
Then the object (T06–T08): SQLite closed state machine, CAS supersession,
distinct-approver fail-closed, revocation without holder cooperation,
outbox insert in the same transaction. Tests fail the mutation when
emission fails, and revoke while the drain sink is down.
Introspection GET /v1/approvals/{id}/claim is a PIP fact, not a decision.
No public consume (T05 waits on GH-WP-0002-T06). Canon T-06 coverage for
wrong binding, expiry, revoke, and supersede.
FLEX-WP-0017 T03 is unblocked on this object; T05 remains blocked only on
consumption ordering.
Assistant: grok
Assistant-Session: 01a04ceb-2057-7e20-b0f9-c282964d5dd9
2026-08-29 12:52:49 +02:00
|
|
|
status: done
|
2026-08-29 11:58:28 +02:00
|
|
|
priority: high
|
2026-08-29 12:01:16 +02:00
|
|
|
state_hub_task_id: "b9267011-71b3-5138-a3f9-5256374a6b3b"
|
2026-08-29 11:58:28 +02:00
|
|
|
```
|
|
|
|
|
|
Implement the engine spine: claim, outbox, machine, API
Contracts first (T02–T04): approval claim schema with issuer, freshness,
and binding digest; local transactional outbox wire; load-bearing cadence
as heartbeat or reconciliation (layer.yaml declared).
Then the object (T06–T08): SQLite closed state machine, CAS supersession,
distinct-approver fail-closed, revocation without holder cooperation,
outbox insert in the same transaction. Tests fail the mutation when
emission fails, and revoke while the drain sink is down.
Introspection GET /v1/approvals/{id}/claim is a PIP fact, not a decision.
No public consume (T05 waits on GH-WP-0002-T06). Canon T-06 coverage for
wrong binding, expiry, revoke, and supersede.
FLEX-WP-0017 T03 is unblocked on this object; T05 remains blocked only on
consumption ordering.
Assistant: grok
Assistant-Session: 01a04ceb-2057-7e20-b0f9-c282964d5dd9
2026-08-29 12:52:49 +02:00
|
|
|
2026-08-29: Outbox insert in the same IMMEDIATE transaction. Test fails the
|
|
|
|
|
transaction when emission fails (no leftover mutation). Revoke succeeds while
|
|
|
|
|
the drain sink is down; the revocation row stays undrained.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-08-29 11:58:28 +02:00
|
|
|
Depends on T03 and T06. Every issuance, use, supersession, and revocation
|
|
|
|
|
inserts the outbox row in the same transaction. Drain is asynchronous.
|
|
|
|
|
`audit-core` outage does not block a revocation.
|
|
|
|
|
|
|
|
|
|
Acceptance: a test that fails the transaction when emission fails, not an
|
|
|
|
|
inspection of the code; a test that revokes while the evidence engine is
|
|
|
|
|
unreachable; no path where the state change commits and the outbox row
|
|
|
|
|
does not.
|
|
|
|
|
|
|
|
|
|
## T09 — Canon T-06 and the FLEX-WP-0017 handoff
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
id: APPROVAL-WP-0001-T09
|
Implement the engine spine: claim, outbox, machine, API
Contracts first (T02–T04): approval claim schema with issuer, freshness,
and binding digest; local transactional outbox wire; load-bearing cadence
as heartbeat or reconciliation (layer.yaml declared).
Then the object (T06–T08): SQLite closed state machine, CAS supersession,
distinct-approver fail-closed, revocation without holder cooperation,
outbox insert in the same transaction. Tests fail the mutation when
emission fails, and revoke while the drain sink is down.
Introspection GET /v1/approvals/{id}/claim is a PIP fact, not a decision.
No public consume (T05 waits on GH-WP-0002-T06). Canon T-06 coverage for
wrong binding, expiry, revoke, and supersede.
FLEX-WP-0017 T03 is unblocked on this object; T05 remains blocked only on
consumption ordering.
Assistant: grok
Assistant-Session: 01a04ceb-2057-7e20-b0f9-c282964d5dd9
2026-08-29 12:52:49 +02:00
|
|
|
status: done
|
2026-08-29 11:58:28 +02:00
|
|
|
priority: medium
|
2026-08-29 12:01:16 +02:00
|
|
|
state_hub_task_id: "b4946568-5dda-5bd7-9941-83a5f0137700"
|
2026-08-29 11:58:28 +02:00
|
|
|
```
|
|
|
|
|
|
Implement the engine spine: claim, outbox, machine, API
Contracts first (T02–T04): approval claim schema with issuer, freshness,
and binding digest; local transactional outbox wire; load-bearing cadence
as heartbeat or reconciliation (layer.yaml declared).
Then the object (T06–T08): SQLite closed state machine, CAS supersession,
distinct-approver fail-closed, revocation without holder cooperation,
outbox insert in the same transaction. Tests fail the mutation when
emission fails, and revoke while the drain sink is down.
Introspection GET /v1/approvals/{id}/claim is a PIP fact, not a decision.
No public consume (T05 waits on GH-WP-0002-T06). Canon T-06 coverage for
wrong binding, expiry, revoke, and supersede.
FLEX-WP-0017 T03 is unblocked on this object; T05 remains blocked only on
consumption ordering.
Assistant: grok
Assistant-Session: 01a04ceb-2057-7e20-b0f9-c282964d5dd9
2026-08-29 12:52:49 +02:00
|
|
|
2026-08-29: `tests/test_t06_replay.py` encodes Canon T-06 for wrong target,
|
|
|
|
|
wrong action, later time, revoked, superseded. Consume-side replay stays out.
|
|
|
|
|
Handoff: `docs/flex-auth-handoff.md`. `FLEX-WP-0017` T03 is unblocked on this
|
|
|
|
|
object; T05 remains blocked only on consumption ordering.
|
|
|
|
|
|
2026-09-01 23:45:48 +02:00
|
|
|
2026-09-01: consume-side replay coverage added after `GH-DEC-2026-003`:
|
|
|
|
|
same-digest retry is idempotent and different-digest replay conflicts. The
|
|
|
|
|
handoff document now records the PEP-before-side-effect protocol.
|
|
|
|
|
|
Implement the engine spine: claim, outbox, machine, API
Contracts first (T02–T04): approval claim schema with issuer, freshness,
and binding digest; local transactional outbox wire; load-bearing cadence
as heartbeat or reconciliation (layer.yaml declared).
Then the object (T06–T08): SQLite closed state machine, CAS supersession,
distinct-approver fail-closed, revocation without holder cooperation,
outbox insert in the same transaction. Tests fail the mutation when
emission fails, and revoke while the drain sink is down.
Introspection GET /v1/approvals/{id}/claim is a PIP fact, not a decision.
No public consume (T05 waits on GH-WP-0002-T06). Canon T-06 coverage for
wrong binding, expiry, revoke, and supersede.
FLEX-WP-0017 T03 is unblocked on this object; T05 remains blocked only on
consumption ordering.
Assistant: grok
Assistant-Session: 01a04ceb-2057-7e20-b0f9-c282964d5dd9
2026-08-29 12:52:49 +02:00
|
|
|
|
|
|
|
|
|
2026-08-29 11:58:28 +02:00
|
|
|
Depends on T07, T08, and T05 (the last only for the consume-side replay
|
|
|
|
|
cases). Point Canon `T-06 — Approval Replay` at a live implementation.
|
|
|
|
|
Hand `access-engine` / `secrets-engine` a claim they can validate before
|
|
|
|
|
privileged production actions (`FLEX-WP-0017` T03/T05).
|
|
|
|
|
|
|
|
|
|
Acceptance: `T-06` passes; T03 is unblocked on the object (not on a hub
|
|
|
|
|
substitute); T05 remains blocked only on consumption ordering if T05 of
|
|
|
|
|
this workplan is still `wait`, never on a missing object or a missing
|
|
|
|
|
digest.
|
2026-09-01 23:45:48 +02:00
|
|
|
|
|
|
|
|
## Closeout
|
|
|
|
|
|
|
|
|
|
Finished 2026-09-01. All nine tasks are complete and the full test suite passes.
|
|
|
|
|
The first-cut engine now has a durable approval object, authenticated-entry
|
|
|
|
|
shape, atomic supersession and consumption, claim introspection, transactional
|
|
|
|
|
outbox, cadence declaration, and complete Canon T-06 replay coverage.
|
|
|
|
|
|
|
|
|
|
Residual production hardening and consumer adoption are carried by
|
|
|
|
|
`APPROVAL-WP-0002`. The unassigned shared Taxonomy request-claim schema is
|
|
|
|
|
carried by residual intake `APPROVAL-IN-0001`; the local claim continues to
|
|
|
|
|
yield rather than claiming permanent vocabulary ownership.
|