Evaluate declared emission cadence and close AUDIT-WP-0009 (T05)
The contract T05 waited on is published: info-tech-canon emission-cadence wire schema 0.1, contract digest b08b4d95fc4b0bd3. A source-owned declaration now travels as emission_cadence on the sender registration; expected-rate entries raise below_declared_cadence on /v1/stream-findings from the same counts /v1/reconciliation returns. heartbeat-or-reconciliation entries are validated and left to T04/T06. Records the observer evaluation of net-kingdom's local-identity declaration: structurally clean, not operationally evaluated, one heartbeat event_class mapping incompatibility. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 151986@bnt-lap001 Assistant-Session: ccd02b6b-80ae-48e5-8cad-9c8f74d21a67
This commit is contained in:
parent
3b7bedc8e0
commit
01468ffc41
8 changed files with 645 additions and 22 deletions
|
|
@ -98,7 +98,7 @@ absence of one proves it did not. Completeness at the boundary is
|
|||
| `T02` attestation scheduling | **No** | Evidence *quality*, not custody. See below. |
|
||||
| `T04` heartbeat / missing-heartbeat findings | No | Detection of adversarial omission for rare classes — the one that matters most for revocation |
|
||||
| `T06` reconciliation counts | No | The source's own ability to detect divergence |
|
||||
| `T05` declared cadence | No | Held deliberately on the §17 Taxonomy schema |
|
||||
| `T05` declared cadence | No | Done 2026-09-22: `emission_cadence` on the registration, info-tech-canon wire schema 0.1 |
|
||||
|
||||
**T02 is an evidence-quality gate, not an admission or deployment blocker.**
|
||||
Admission depends on identity, scope, ingress and a token. Attestation freshness
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Stream completeness: heartbeats, reconciliation, and findings
|
||||
|
||||
`AUDIT-WP-0009` T04, T06, T07. Statute §9.6.
|
||||
`AUDIT-WP-0009` T04, T05, T06, T07. Statute §9.6.
|
||||
|
||||
The chain proves records held were not altered or truncated. It says nothing
|
||||
about a record that never arrived — and §9.6 is explicit that **omission** is
|
||||
|
|
@ -16,6 +16,7 @@ cadence to a system with nowhere to put it, so this is the surface owed.
|
|||
| --- | --- | --- |
|
||||
| Heartbeat (`POST /v1/events`, class `audit-core.heartbeat`) | A class going silent — including one that is *legitimately* silent, which rate monitoring can never distinguish | A compromised source emitting a truthful-looking heartbeat while suppressing the event |
|
||||
| Reconciliation (`GET /v1/reconciliation`) | Loss, outage, drain failure — divergence between what a source emitted and what arrived | A compromised source suppressing the event and its own count together |
|
||||
| Declared rate (`emission_cadence` on the registration) | A high-volume class falling below the rate its source declared | A class that may legitimately be silent — that is the heartbeat's job; and a rate held proves nothing about completeness |
|
||||
| Findings (`GET /v1/stream-findings`) | Surfacing the above where an operator sees them | Anything the two above do not detect |
|
||||
|
||||
**The bound is the same in both rows and it is not a footnote.** Where the
|
||||
|
|
@ -52,14 +53,12 @@ security-relevant one — and the quiet class is the only reason heartbeats
|
|||
exist. `informed-decision` raised this shape first for presentations versus
|
||||
dispositions; it generalises.
|
||||
|
||||
### Not the §17 cadence schema
|
||||
### Heartbeat and cadence are complementary
|
||||
|
||||
`AUDIT-WP-0009-T05` waits on the emission-cadence declaration `kings-guard` is
|
||||
drafting for Taxonomy, and this does not pre-empt it. Cadence describes a
|
||||
stream's expected **rate**; a heartbeat is a registration property saying how
|
||||
often a source promises to say *nothing to report* for a class that may
|
||||
legitimately be silent. Complementary, not alternatives, and audit-core is not
|
||||
inventing a competing rate shape while the real one is being written.
|
||||
A heartbeat is a registration property saying how often a source promises to
|
||||
say *nothing to report* for a class that may legitimately be silent. Cadence
|
||||
describes a stream's expected **rate**. They are not alternatives, and the rate
|
||||
shape is not audit-core's — see [Declared emission cadence](#declared-emission-cadence).
|
||||
|
||||
### Findings
|
||||
|
||||
|
|
@ -114,3 +113,57 @@ Two refusals worth knowing:
|
|||
The response carries a `means` field stating that agreement proves neither
|
||||
completeness nor that any event occurred — because this is the number most
|
||||
likely to be quoted out of context in someone else's conformance argument.
|
||||
|
||||
## Declared emission cadence
|
||||
|
||||
`AUDIT-WP-0009-T05`. The contract is info-tech-canon's EmissionCadence
|
||||
declaration, **wire schema 0.1**, read at contract digest `b08b4d95fc4b0bd3`
|
||||
(standard document 0.2.0, candidate). audit-core did not invent the shape; it
|
||||
waited for it. `audit_core/emission_cadence.py` validates a declaration against
|
||||
that schema by hand — the receiver stays stdlib-only — and refuses what the
|
||||
schema refuses rather than relaxing a rule to admit a declaration.
|
||||
|
||||
The source owns and publishes its declaration. It reaches audit-core as
|
||||
`emission_cadence` on the sender registration (the declaration object, as
|
||||
JSON). An invalid declaration refuses the registration. The ConfigMap scope
|
||||
overlay may not set or change it: a partial overlay has no sound merge with a
|
||||
digest-pinned declaration, and a wholesale replacement could widen a window or
|
||||
drop a class without anyone deciding to.
|
||||
|
||||
What each declared form gets here:
|
||||
|
||||
| Form | What audit-core does |
|
||||
| --- | --- |
|
||||
| `expected-rate` | Evaluated. For each permitted source, events of the class in the trailing `window` ending now are counted; fewer than `expected_min` is a `below_declared_cadence` finding on `GET /v1/stream-findings`. The count is the one `/v1/reconciliation` returns, so a finding and a count cannot disagree. |
|
||||
| `heartbeat-or-reconciliation` | Validated and kept, not re-evaluated. The reconciliation half is `/v1/reconciliation`, whose count is the `compare_observed` side; `compare_local` belongs to the source. The heartbeat half is evaluated from `heartbeat_classes` (see below). |
|
||||
|
||||
Refusals, same as for heartbeats: a wildcard source is not held to a rate, and
|
||||
two `expected-rate` entries for one class are refused — each would be satisfied
|
||||
by the other's events.
|
||||
|
||||
Every cadence finding carries a `means` field: fewer events than declared says
|
||||
the source may have stopped **or the declaration is wrong**, and is not proof of
|
||||
suppression; a rate held would not prove completeness.
|
||||
|
||||
### Observer evaluation, 2026-09-22
|
||||
|
||||
info-tech-canon asked whether audit-core would evaluate the one published
|
||||
source-owned declaration, net-kingdom `local-identity/emission-cadence.yaml`
|
||||
(commit `116643f`, pinned to the earlier digest `972c0b6701d1693f`; the wire
|
||||
schema is identical). The result, stated at no more than it is:
|
||||
|
||||
- **Structural: clean.** Both entries (`serve/token.token_issued`,
|
||||
`revoke-token`) validate as `heartbeat-or-reconciliation` with a
|
||||
reconciliation block. Asserted in `tests/test_emission_cadence.py`.
|
||||
- **Operational: not evaluated.** audit-core registers no `local-identity`
|
||||
sender and holds none of its events, so there is no observed count behind
|
||||
`compare_observed` here either. This is not an observer result on the stream,
|
||||
and nobody should count it as one.
|
||||
- **One incompatibility, recorded.** The contract's `heartbeat.event_class`
|
||||
names the heartbeat event's own class (e.g. `flex-auth.decision.heartbeat`).
|
||||
audit-core's heartbeat is a single class, `audit-core.heartbeat`, carrying
|
||||
the vouched-for class in `data.class`, declared per class in
|
||||
`heartbeat_classes`. A declaration's heartbeat block therefore does not map
|
||||
onto audit-core's evaluation by itself: a source needs `heartbeat_classes` on
|
||||
its registration too, and the two can drift apart. That is fixable on
|
||||
either side and has not been fixed on either.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue