AUDIT-WP-0009 T02/T10 — schedule attestation, and make the §5 check total
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
This commit is contained in:
parent
3c2cdcdf79
commit
de9e3abe5f
9 changed files with 666 additions and 8 deletions
33
layer.yaml
33
layer.yaml
|
|
@ -30,9 +30,13 @@ approval_validity_query: forbidden
|
|||
|
||||
# §5 applies to Staff. audit-core is an Engine and holds no §4 Tooling contact
|
||||
# (key-cape, OpenBao). Companion §4 asks that UNCATALOGUED infrastructure be
|
||||
# listed anyway so the check is total, and that carve-out sunsets within two
|
||||
# review intervals for a store another layer reads. Completing this list and
|
||||
# adding a conformance test is AUDIT-WP-0009-T10.
|
||||
# listed anyway so the check is total rather than vacuous, and that carve-out
|
||||
# sunsets within two review intervals for a store another layer reads.
|
||||
#
|
||||
# Completed 2026-09-10 (AUDIT-WP-0009-T10). The list below is asserted total by
|
||||
# `tests/test_layer_conformance.py`, which fails when a new infrastructure
|
||||
# contact appears in `deploy/` without a row here — the check is mechanical
|
||||
# rather than a promise to remember.
|
||||
tooling_contacts: []
|
||||
uncatalogued_infrastructure:
|
||||
- id: platform-pg
|
||||
|
|
@ -41,6 +45,29 @@ uncatalogued_infrastructure:
|
|||
read_by_other_layers: true # subject to the companion §4 sunset
|
||||
note: >-
|
||||
Not a §4 Tooling row. Listed for totality, not as a declared gap.
|
||||
- id: state-hub
|
||||
system: Custodian State Hub
|
||||
role: >-
|
||||
Work coordination only. Reads and writes workplans, tasks, intakes and
|
||||
progress events. Carries no audit event, no sender credential and no
|
||||
custody role, and audit-core's runtime does not contact it — this is a
|
||||
development-time contact, listed because §5 totality does not distinguish.
|
||||
read_by_other_layers: false
|
||||
- id: kube-apiserver
|
||||
system: k3s API server on railiance01
|
||||
role: >-
|
||||
Written by the audit-core-attest CronJob to publish the chain-head
|
||||
attestation into one named ConfigMap (AUDIT-WP-0009-T02). The receiver
|
||||
has no API-server egress: a receiver able to rewrite its own attestation
|
||||
could forge it, so the reach belongs to the attest workload alone.
|
||||
read_by_other_layers: false
|
||||
- id: forgejo.coulomb.social
|
||||
system: Container registry
|
||||
role: >-
|
||||
Image source, pinned by digest in deploy/. Build-time contact; no runtime
|
||||
call. Listed because a registry that can change what runs is an
|
||||
infrastructure contact whether or not §5 catalogues it.
|
||||
read_by_other_layers: false
|
||||
|
||||
# §9.6 — the bound audit-core delivers, stated so no doctrine rests on more.
|
||||
evidence_bound:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue