Add bounded source reconciliation counts and clarify receiver dependencies

Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a1046e-fdbf-7b93-a267-5f72b9b24526
This commit is contained in:
tegwick 2026-10-04 11:34:42 +02:00
parent 1044a5f36d
commit 24a5ecd56b
8 changed files with 231 additions and 17 deletions

View file

@ -40,7 +40,9 @@ accepted event counts for `source=approval-engine` and the corresponding
| `revocation` | `approval.revocation` |
| `heartbeat` | `audit-core.heartbeat` |
Undrained local rows are this engine's lag, not yet a divergence. A row
Account for occurrence versus receiver acceptance time as specified below;
identical window bounds alone do not align those populations. Undrained local
rows are this engine's lag, not yet a divergence. A row
with `drained_at` set that `audit-core` does not hold is the omission
case §9.6 names.
@ -111,3 +113,33 @@ uv run tools/emission-cadence-profile/emission_cadence_profile.py \
This supplies an owner-authored instance to NK-WP-0035; it does not accept the
proposed NetKingdom profile or claim receiver admission/observed cadence.
## Bounded source snapshot — 2026-10-04
`GET /v1/cadence?since=<timestamp>&until=<timestamp>` requires approval:observe
and the exact store tenant. Supply exactly one timezone-aware since and until,
with since earlier than until; encode plus signs in timezone offsets. Bounds
are inclusive since, exclusive until. The existing query-free lifetime response
is preserved; it cannot substitute for a bounded reconciliation.
The response identifies source, tenant, normalized UTC bounds and window_basis
created_at. Each class has committed, drained and pending counts for rows created
in that window, plus acknowledged_in_window for local drain acknowledgments in
that window regardless of creation time. All counts come from one database
statement snapshot. Zero classes are explicit; no payloads or identities are
selected or returned, and the source performs no receiver calls.
Audit Core's published `/v1/reconciliation` uses **receiver acceptance time**,
not occurrence time. Local drained_at is acknowledgment time and may follow
acceptance, especially if an accepted event's response was lost and a duplicate
was acknowledged later. Equal textual since/until bounds alone do not align
those populations. The observer must account for delayed delivery, acknowledgment
boundaries and duplicate acceptance, or use independently correlated event ids
and an agreed settled window before treating a count mismatch as omission.
Pending occurrence rows are lag; neither count agreement nor this source
snapshot proves completeness or resistance to source compromise.
This implements T04's missing bounded source computation. Receiver registration,
observed lag/findings and native reconciliation remain blocked owner acceptance;
no existing live image is promoted by this change.

View file

@ -29,7 +29,7 @@ object mutation.
| `use` | public CAS accepts first `request_digest` and object becomes `consumed` | `approval.use` |
| `supersession` | object becomes `superseded` | `approval.supersession` |
| `revocation` | object becomes `revoked` | `approval.revocation` |
| `heartbeat` | signed *nothing to report* plus counts | `approval.heartbeat` |
| `heartbeat` | authenticated per-class *nothing to report* plus counts | `audit-core.heartbeat` |
Expiry is a clock crossing, persisted on observation, and is **not** an
emitted class. The validity window is already on the object.
@ -116,7 +116,7 @@ So `approval.issuance` and `approval.use` both carry a `threshold` object in
| `required_count` | the threshold in force on the object at that moment |
| `distinct_approver_count` | distinct subjects who had recorded an entry |
| `threshold_met` | whether the evaluation passed |
| `approvers` | `subject_id`, `approved_at`, and `assurance` / `evidence_ref` when recorded |
| `approvers` | `subject_id`, `approved_at`, `principal_type`, nullable verified `tenant_source`, and `assurance` / `evidence_ref` when recorded |
An auditor holding only the `use` row can recompute the evaluation without
reading live rows — which matters because those rows may since have been

View file

@ -6,7 +6,7 @@ the workplan remains `blocked` after completing reachable source work.
| Task | Owner return required | Evidence that clears the wait |
| --- | --- | --- |
| T01 — authenticated approver evidence | key-cape and informed-decision; founder for release rollout | Exact deployed issuer revision and client/profile receipt for requester and human paths; human sub/type, tenant/source, resource audience, scopes and assurance captured as non-secret facts and correlated with a stored human-control entry. Promote scanned schema-v6 image under per-change approval, back up/migrate once, then verify native entry and issuance/use provenance. No tokens or secrets in receipts. |
| T04 — delivery and reconciliation | audit-core, with railiance-platform for deployed sender/custody acceptance | Accept current cadence.yaml inventory for source approval-engine and tenant tenant:platform, explicit redact policy and four transition heartbeat classes at the requested 172800s bound. Return actual lifecycle event ids/drain acknowledgment and independent accepted counts for the same bounded time window, with pending rows accounted separately. Prove startup beats, missing-class and lag findings (depth 100 / age 3600s), and scoped sender bearer revocation. |
| T04 — delivery and reconciliation | audit-core, with railiance-platform for deployed sender/custody acceptance | Accept current cadence.yaml inventory for source approval-engine and tenant tenant:platform, explicit redact policy and four transition heartbeat classes at the requested 172800s bound. Return actual lifecycle event ids/drain acknowledgment and independent accepted counts for an agreed bounded comparison, accounting for occurrence versus receiver acceptance time, delayed delivery, duplicate acknowledgments and boundary crossings; source pending rows remain lag. Prove startup beats, missing-class and lag findings (depth 100 / age 3600s), and scoped sender bearer revocation. |
| T05 — live PEP consumption | secrets-engine, with informed-decision for the act-specific human review and access-engine for decision binding | Name the served PEP route/workload, immutable component revision, engine image/endpoint, authenticated caller identities and exact binding. Prove claim-before-decision and CAS consume after ALLOW before protected side effect; same-digest retry, different-digest conflict, spent-on-failure, revoked/expired/superseded/wrong-binding/unavailable denial with no protected callback. Preserve the native approval and decision digests, declared human_control where required, and consumer-owned side-effect/refusal evidence. |
For live whitehat T-06 only, T05's named surface must additionally be covered by
@ -60,3 +60,19 @@ The [deployment runbook](../deploy/README.md) and
APPROVAL-IN-0001 also remains open for the unassigned shared Taxonomy schema
owner. It does not block this workplan's local claim contract and is not a
substitute for the three owner returns above.
## Reconciliation follow-up review — 2026-10-04
T04 source preparation now includes authenticated bounded cadence snapshots,
with committed/drained/pending occurrence counts and separate local
acknowledgment-window counts. The older lifetime-only surface did not satisfy
the source declaration's bounded-window requirement. The local implementation
is complete; source schema remains v6 and awaits the existing release gate.
Audit Core docs/stream-completeness.md explicitly defines receiver
acceptance-time windows. The required owner return must state the temporal
population and reconcile lag/duplicate/boundary cases; matching since/until
strings against occurrence counts is insufficient. Existing owner task bindings
remain key-cape (T01), audit-core (T04) and secrets-engine (T05). No new owner
receipt or named live T-06 surface arrived since the preceding review.