202 lines
8 KiB
Markdown
202 lines
8 KiB
Markdown
|
|
---
|
|||
|
|
id: AUDIT-WP-0009
|
|||
|
|
type: workplan
|
|||
|
|
title: "Evidence-role conformance under Security Layer Model v0.7"
|
|||
|
|
domain: infotech
|
|||
|
|
repo: audit-core
|
|||
|
|
status: ready
|
|||
|
|
owner: claude
|
|||
|
|
topic_slug: railiance
|
|||
|
|
created: "2026-08-29"
|
|||
|
|
updated: "2026-08-29"
|
|||
|
|
depends_on:
|
|||
|
|
- AUDIT-WP-0007
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# AUDIT-WP-0009 — Evidence-role conformance under Security Layer Model v0.7
|
|||
|
|
|
|||
|
|
## Goal
|
|||
|
|
|
|||
|
|
Make audit-core dischargeable as the estate's **Evidence engine** under
|
|||
|
|
NetKingdom Security Layer Model v0.7 (accepted), and stop it claiming a property
|
|||
|
|
its own contract does not permit.
|
|||
|
|
|
|||
|
|
Two things drive this workplan.
|
|||
|
|
|
|||
|
|
**First, a live overclaim.** `audit_core/postgres_backend.py` returns
|
|||
|
|
`tamper_evidence=True` as a constant, while `docs/integrity.md` permits that
|
|||
|
|
claim only when a live external chain-head attestation exists. The one
|
|||
|
|
attestation on record is 2026-08-16 and nothing renews it. Audit Core is
|
|||
|
|
currently telling every sender it has a property whose precondition is
|
|||
|
|
unverified — the §9.6 defect it twice corrected in gate-house's doctrine, turned
|
|||
|
|
inward.
|
|||
|
|
|
|||
|
|
**Second, an obligation audit-core argued for and cannot yet support.** v0.7
|
|||
|
|
§9.6 makes a declared emission cadence a **MUST** for load-bearing sources, with
|
|||
|
|
reconciliation or a heartbeat as the required form for low-volume classes.
|
|||
|
|
audit-core raised both, moving cadence from SHOULD to MUST. A source cannot
|
|||
|
|
declare a cadence to a system with nowhere to put it. Having won the obligation,
|
|||
|
|
audit-core owes the surface.
|
|||
|
|
|
|||
|
|
Full assessment: `history/2026-08-29-v0.7-alignment-and-scope-assessment.md`.
|
|||
|
|
Standard: `net-kingdom/canon/standards/security-layer-model_v0.7.md`, companion
|
|||
|
|
`net-kingdom/SECURITY-COMPANION.md`.
|
|||
|
|
|
|||
|
|
## Non-goals
|
|||
|
|
|
|||
|
|
Fixed by the statute; not deferred, not ours:
|
|||
|
|
|
|||
|
|
- No authorization decision surface, and no approval-validity query (§6, §9.4).
|
|||
|
|
- No operative approval state (§9.4).
|
|||
|
|
- No WORM, object lock, or ITC-CAP `data.archive` — §16 ruled the
|
|||
|
|
stronger-custody gap closed, a different store with a different owner.
|
|||
|
|
- Emission atomicity at the source, which is the emitter's obligation (§9.6).
|
|||
|
|
|
|||
|
|
## Tasks
|
|||
|
|
|
|||
|
|
```task
|
|||
|
|
id: AUDIT-WP-0009-T01
|
|||
|
|
status: todo
|
|||
|
|
priority: high
|
|||
|
|
```
|
|||
|
|
Make `tamper_evidence` conditional on live attestation state. Derive the flag
|
|||
|
|
rather than hard-coding it: the backend reports `True` only when a chain-head
|
|||
|
|
attestation exists, verifies against the live chain, and is within a declared
|
|||
|
|
freshness window. Stale or absent attestation degrades the claim — it does not
|
|||
|
|
leave it standing. Assert the degradation with a test, and state the freshness
|
|||
|
|
window in `docs/integrity.md` alongside the two existing preconditions, which
|
|||
|
|
today are documented but unenforced.
|
|||
|
|
|
|||
|
|
```task
|
|||
|
|
id: AUDIT-WP-0009-T02
|
|||
|
|
status: todo
|
|||
|
|
priority: high
|
|||
|
|
```
|
|||
|
|
Schedule chain-head attestation so the precondition T01 enforces is normally
|
|||
|
|
met. `attest-chain` exists and is operator-run; `deploy/` has no job. Add one,
|
|||
|
|
write the attestation to the logical-offsite path already used by
|
|||
|
|
`RESOURCE-WP-0002-T06` (`rapp-postgres` / Nextcloud + age) and **not** the
|
|||
|
|
Barman prefix, per `docs/integrity.md` — that copy is restored with the table
|
|||
|
|
and proves nothing. Record the cadence in `docs/integrity.md`.
|
|||
|
|
|
|||
|
|
```task
|
|||
|
|
id: AUDIT-WP-0009-T03
|
|||
|
|
status: todo
|
|||
|
|
priority: high
|
|||
|
|
```
|
|||
|
|
Represent the §9.6 evidence kind per source. Add `evidence_kind`
|
|||
|
|
(`load-bearing` | `attributive`) to `SenderIdentity` and the sender registration
|
|||
|
|
schema, defaulting to `attributive` — a source that has not declared is not
|
|||
|
|
silently treated as load-bearing. Where a source declares `attributive` and has
|
|||
|
|
deliberately traded away atomicity, carry the declared trade with it, because
|
|||
|
|
§9.6 requires the trade be declared where the trail is documented. Prerequisite
|
|||
|
|
for T04–T06.
|
|||
|
|
|
|||
|
|
```task
|
|||
|
|
id: AUDIT-WP-0009-T04
|
|||
|
|
status: todo
|
|||
|
|
priority: high
|
|||
|
|
```
|
|||
|
|
Heartbeat ingestion and missing-heartbeat findings. The required form for
|
|||
|
|
low-volume load-bearing classes, and the only control covering adversarial
|
|||
|
|
omission for exactly the rare negative events — revocation, denial, containment
|
|||
|
|
— where suppression is most valuable and least visible. Accept a signed
|
|||
|
|
*nothing to report* assertion per source and class; raise a finding when an
|
|||
|
|
expected heartbeat does not arrive. The point is a positive claim that can
|
|||
|
|
itself go missing, which rate monitoring can never produce.
|
|||
|
|
|
|||
|
|
```task
|
|||
|
|
id: AUDIT-WP-0009-T05
|
|||
|
|
status: wait
|
|||
|
|
priority: medium
|
|||
|
|
```
|
|||
|
|
Accept and evaluate a declared emission cadence per source, and raise a finding
|
|||
|
|
when the stream falls below it. **Waiting on** the §17 emission-cadence
|
|||
|
|
declaration schema, which `kings-guard` is drafting and Taxonomy will own; do
|
|||
|
|
not invent a competing shape. Cadence covers high-volume streams; T04 covers the
|
|||
|
|
low-volume load-bearing case, and the two are complementary rather than
|
|||
|
|
alternatives.
|
|||
|
|
|
|||
|
|
```task
|
|||
|
|
id: AUDIT-WP-0009-T06
|
|||
|
|
status: todo
|
|||
|
|
priority: medium
|
|||
|
|
```
|
|||
|
|
Reconciliation surface: per-source, per-class event counts over a bounded
|
|||
|
|
window, readable by the source itself, so an emitter can compare audit-core's
|
|||
|
|
count against its own state transitions and treat divergence as a finding.
|
|||
|
|
`GH-WP-0002-T04` is the reference instance on the `approval-engine` side; this
|
|||
|
|
is its counterpart here. Respect the existing read model — `may_read`, tenant
|
|||
|
|
scoping, and no payloads in a counts response.
|
|||
|
|
|
|||
|
|
```task
|
|||
|
|
id: AUDIT-WP-0009-T07
|
|||
|
|
status: todo
|
|||
|
|
priority: medium
|
|||
|
|
```
|
|||
|
|
Give stream-completeness findings a home. `/v1/dead-letters` and
|
|||
|
|
`/v1/secret-findings` exist; a cadence miss (T05) and a missing heartbeat (T04)
|
|||
|
|
have nowhere to surface. INTENT principle 10 already says a degraded audit
|
|||
|
|
stream is itself an audit and operations event — the principle is in place and
|
|||
|
|
the mechanism is not. Follow the existing findings-surface conventions rather
|
|||
|
|
than adding a new shape.
|
|||
|
|
|
|||
|
|
```task
|
|||
|
|
id: AUDIT-WP-0009-T08
|
|||
|
|
status: todo
|
|||
|
|
priority: medium
|
|||
|
|
```
|
|||
|
|
Assert the §9.4 approval-validity prohibition with a negative test. It is
|
|||
|
|
currently honoured by absence, which is not the estate's idiom: §6.4 obligation
|
|||
|
|
3 requires a PEP's published stance map equal shipped behaviour *asserted by
|
|||
|
|
test*. A prohibition worth stating in `INTENT.md`, `SCOPE.md`, and `layer.yaml`
|
|||
|
|
is worth asserting in `tests/`.
|
|||
|
|
|
|||
|
|
```task
|
|||
|
|
id: AUDIT-WP-0009-T09
|
|||
|
|
status: todo
|
|||
|
|
priority: low
|
|||
|
|
```
|
|||
|
|
Register `approval-engine` as a distinct source under §9.4 and `AUDIT-IN-0001`:
|
|||
|
|
sender registration, the four event classes (issuance, use, supersession,
|
|||
|
|
revocation), tenancy mapping, retention profile, `secret_policy`, and
|
|||
|
|
`evidence_kind: load-bearing` from T03. Onboarded under INTENT principle 4 —
|
|||
|
|
declared ownership, retention, access, export and evidence policy, not merely
|
|||
|
|
events arriving. Not blocking: `approval-engine` is not yet emitting.
|
|||
|
|
|
|||
|
|
```task
|
|||
|
|
id: AUDIT-WP-0009-T10
|
|||
|
|
status: todo
|
|||
|
|
priority: low
|
|||
|
|
```
|
|||
|
|
Make the §5 conformance check total. `layer.yaml` declares
|
|||
|
|
`tooling_contacts: []`, true under §5 as written — audit-core is an Engine and
|
|||
|
|
holds no `key-cape` or OpenBao client. Companion §4 asks that uncatalogued
|
|||
|
|
infrastructure be listed anyway, and that carve-out sunsets within two review
|
|||
|
|
intervals for a store another layer reads, which `platform-pg` is. List it and
|
|||
|
|
the State Hub now. Add a conformance script and test in the shape ops-warden
|
|||
|
|
offered estate-wide.
|
|||
|
|
|
|||
|
|
## Acceptance
|
|||
|
|
|
|||
|
|
- No custody claim is returned unconditionally where `docs/integrity.md`
|
|||
|
|
conditions it, and a stale attestation visibly degrades the claim.
|
|||
|
|
- A source can declare its evidence kind, and a load-bearing source can
|
|||
|
|
discharge the §9.6 cadence MUST against a real audit-core surface.
|
|||
|
|
- A suppressed low-volume load-bearing class produces a finding rather than
|
|||
|
|
silence.
|
|||
|
|
- The approval-validity prohibition is asserted by test, not by absence.
|
|||
|
|
- `layer.yaml` lists every infrastructure contact, catalogued or not, and a test
|
|||
|
|
checks it.
|
|||
|
|
|
|||
|
|
## Notes
|
|||
|
|
|
|||
|
|
T01 and T02 are separable and T01 is the one that matters: scheduling
|
|||
|
|
attestation without making the claim conditional would leave the overclaim in
|
|||
|
|
place whenever the job fails, which is precisely the case the claim is supposed
|
|||
|
|
to cover.
|
|||
|
|
|
|||
|
|
T05's dependency is real and should not be worked around. audit-core argued the
|
|||
|
|
cadence obligation up to a MUST; inventing a local cadence shape ahead of the
|
|||
|
|
Taxonomy schema would fragment the very interface it asked for.
|