T02. deploy/attest-cronjob.yaml: daily at 03:17 UTC against the 168h window,
its own ServiceAccount, and a Role reaching exactly one named ConfigMap —
get/update/patch, no create, no list. audit_core/attest_publish.py does the
publish in stdlib; the image carries no kubectl, and adding one to an audit
receiver's image to write a single file is the worse trade.
Three refusals, all deliberate:
The producer is not the receiver. A receiver that could rewrite its own
attestation could forge it. audit-core-egress is now scoped to
component: receiver and a separate audit-core-attest-egress carries the 6443
rule, so the receiver never gains API-server reach. Asserted by test.
It refuses to publish over a broken chain. A fresh head written over a break
replaces an honest chain_break with a fresh-looking attestation. Stale
degrades the claim visibly; false does not.
Mounted as a directory, not subPath. Found while writing the manifest: a
subPath ConfigMap mount is resolved once at pod start and never updates, so
the daily attestation would land in the ConfigMap and never reach the running
receiver — tamper_evidence would age out to false while the job reported
success every night, silent in both directions.
The offsite copy stays an operator step. audit-core holds no Nextcloud
credential and should not acquire one to publish a hash, so docs/integrity.md
states the bound plainly: until that copy exists the delivered control defends
against a database owner, not a cluster owner, and no stronger claim may be
made from it.
T10. layer.yaml lists four infrastructure contacts — platform-pg, state-hub,
kube-apiserver, the container registry — each with its role and whether another
layer reads it. tooling_contacts stays [], which is true under §5 as written;
the companion's totality request is met by the uncatalogued list rather than by
inventing a Tooling row. tests/test_layer_conformance.py derives the egress
destinations from the manifests and the registry from the pinned digests, so a
new contact appearing in deploy/ without a row fails the test rather than
waiting for a reviewer to notice.
Applying the manifests remains an operator action; nothing here was applied.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nb7Q6ZmXppNDkTWytfYqfv
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 2069992@bnt-lap001
Assistant-Session: 167dd7f8-2a25-4be1-aa46-3b6f1a5f94c6
The standard is accepted at v0.7 and all three of audit-core's v0.6
findings landed in it (§9.6 threat decomposition, cadence MUST for
load-bearing sources with reconciliation/heartbeat for low-volume
classes, §3.3's Evidence row restated as an estate trade).
INTENT.md: layer/role declared in frontmatter as §11 and companion §2
require — layer.yaml alone did not discharge it. Layer section rewritten
for the Evidence role and its obligations. New Evidence Bound section
carrying the §9.6 sound/unsound forms and the three-row threat table,
including the residual nothing in the model prevents.
SCOPE.md: replaced the statehub register stub, which carried no boundary
at all. Statute-fixed prohibitions now live here, separated from the
merely-not-yet — §16 ruled the stronger-custody gap closed, so WORM and
data.archive are not ours rather than not yet.
Assessment found nine gaps. Headline: postgres_backend returns
tamper_evidence=True unconditionally while docs/integrity.md permits it
only against a live external attestation, and the one on record is
2026-08-16 with no job renewing it — audit-core overclaiming its own
bound, the §9.6 defect turned inward. Also: no cadence, heartbeat,
reconciliation, or load-bearing classification exists, so the obligation
audit-core argued up from SHOULD to MUST is not yet dischargeable
against audit-core.
AUDIT-WP-0009 raised, ten tasks.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WpeL68AWHqtqPQZEXY5kFe
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4040362@bnt-lap001
Assistant-Session: 4fd0fd24-2ee8-4413-bd67-43bd79ca73f1
All three v0.4 findings landed in v0.5 (local outbox, machine-readable
declaration, §14 arithmetic). §9.6's load-bearing/attributive split and
§16's ruling on approval custody both improve on what audit-core raised.
Findings, all correcting audit-core's own contribution: (1) the local
outbox closes accidental omission, not the compromised-source case §9.6
opens with — a compromised emitter can decline the insert or drop the row
before drain; §16 rests a ruling on that conflation. (2) cadence is the
only control touching the residual and is a SHOULD, and rate-based
detection is weakest for the rare negative events §9.6 says matter most —
recommend positive reconciliation for load-bearing low-volume classes.
(3) §3.3's Evidence row states an availability/independence trade as a
property of evidence engines.
Adds layer.yaml in ops-warden's reference form, per §11.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WpeL68AWHqtqPQZEXY5kFe
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4040362@bnt-lap001
Assistant-Session: 4fd0fd24-2ee8-4413-bd67-43bd79ca73f1