Assistant: claude-code Assistant-Model: opus Assistant-Process: 4040362@bnt-lap001 Assistant-Session: 4fd0fd24-2ee8-4413-bd67-43bd79ca73f1
212 lines
8.6 KiB
Markdown
212 lines
8.6 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
|
||
state_hub_workstream_id: "46a96b03-bc08-53b5-9c93-4071adabf734"
|
||
---
|
||
|
||
# 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
|
||
state_hub_task_id: "f545b0e4-8c99-5186-affd-ce9a41209ed7"
|
||
```
|
||
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
|
||
state_hub_task_id: "6de9945f-4dd1-57dd-898a-f59c35b1df6c"
|
||
```
|
||
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
|
||
state_hub_task_id: "acae6085-ada7-51b2-8dc0-4abac7f7e7b3"
|
||
```
|
||
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
|
||
state_hub_task_id: "f36470af-4019-54b2-96d7-e049d867c7db"
|
||
```
|
||
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
|
||
state_hub_task_id: "382575ca-1801-5a32-a93d-90a8b9c8adbf"
|
||
```
|
||
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
|
||
state_hub_task_id: "0a8d6eed-75dd-5aaa-bf86-60be9dadca03"
|
||
```
|
||
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
|
||
state_hub_task_id: "f572dfeb-0d1b-58d6-be83-405125189028"
|
||
```
|
||
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
|
||
state_hub_task_id: "f7b513ee-af48-5c5a-a34e-3e9922d29b76"
|
||
```
|
||
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
|
||
state_hub_task_id: "fd4a4ac3-e525-57c1-9179-e0fcd0226913"
|
||
```
|
||
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
|
||
state_hub_task_id: "ac3464fd-3df9-51a1-b1f4-3bf3c60e4265"
|
||
```
|
||
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.
|