approval-engine/docs/emission-cadence.md
tegwick 2bd2d19a98 Implement approval engine production readiness
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a05e2e-805b-7042-a750-71f473bceea2
2026-09-02 00:52:04 +02:00

2.2 KiB

Emission cadence — source declaration

Statute §9.6: approval evidence is load-bearing and low-volume. Rate monitoring is the wrong form. A handful of revocations a month has no rate to drop below; suppression is indistinguishable from a quiet month.

This file is the source side of GH-WP-0002-T04. That task is the detection surface; this declaration is what it reads. Machine-readable copy: ../cadence.yaml.

Form

Heartbeat, plus reconciliation counts. Not a rate.

Heartbeat

An authenticated positive claim: nothing to report, together with cumulative per-class committed transition counts. The claim can itself go missing, which is the point — silence becomes a missing positive rather than a quiet month.

Field Value
Class heartbeat
Interval 24 hours (SHOULD also be emittable on demand)
Assertion nothing-to-report
Counts {issuance, use, supersession, revocation} of committed outbox rows
Missing heartbeat finding

Reconciliation

Compare this engine's committed outbox counts per class to audit-core's accepted event counts for source=approval-engine and the corresponding action. Divergence is a finding, not a log line.

This engine audit-core action
issuance approval.issuance
use approval.use
supersession approval.supersession
revocation approval.revocation
heartbeat approval.heartbeat

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.

What is a finding

  • No heartbeat arrives for more than one interval.
  • audit-core count for a class is less than this engine's drained count for that class.
  • Outbox depth or age exceeds the lag bound in cadence.yaml (drain stuck).

None of these are rate drops. None of these are informational logs.

Residual

Atomicity prevents accidental omission (crash between mutation and emit). Cadence and reconciliation detect adversarial omission after the fact. Nothing in the model prevents a compromised source from suppressing. That residual is stated, not closed.