audit-core/layer.yaml
codex 40fc7d694c
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Answer flex-auth B3: the emitter is the section 4 source, not the archive
AUDIT-IN-0005. flex-auth produces the decision record, declares no §11
emission guarantee, and declined to take the reading that moves the
obligation to audit-core. audit-core declines it too, on its own authority:
class, cadence and detection surface are properties of emitting; audit-core
cannot detect non-production; the obligations already sit on each sender
registration; archive-as-source would make §11's check vacuous; and no
access-engine sender is registered at all.

Binds audit-core, does not rule §11 — gate-house still owns that, so
flex-auth's G2 stays open.

Reflexive half: audit-core's own chain-head attestation emission is now
declared in layer.yaml rather than only in docs/integrity.md prose, and
asserted against the CronJob and the contract by test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 63291@bnt-lap001
Assistant-Session: 8bd77868-ca68-4f49-bb1e-d539ecc0d703
2026-09-21 02:09:47 +02:00

133 lines
6.4 KiB
YAML

# audit-core — NetKingdom security layer declaration
#
# Framework: net-kingdom/canon/standards/security-layer-model_v0.7.md
# Assent: AUDIT-IN-0001 (audit-core's own voice, per §11 "who must declare")
# history/2026-08-28-approval-evidence-assent.md
# history/2026-08-29-security-layer-model-v0.6-review.md
# history/2026-08-29-v0.7-alignment-and-scope-assessment.md
#
# Reference form offered by ops-warden and adopted here, so §11's declaration
# check is mechanical rather than a reader's judgment about prose. audit-core
# raised that defect; adopting the form is the other half of raising it.
schema_version: "0.1"
framework: netkingdom-security-layer-model
standard_version: "0.7"
repository: audit-core
layer: engine
role: evidence # §3.3 engine typing
declared_by: intakes/intakes.md AUDIT-IN-0001
declared_at: "2026-08-29"
# §3.3: an Evidence engine records what happened and proves integrity of what
# it holds. It is explicitly not a decision point (§6, §9.4).
decision_surfaces_exposed: none
# §9.4 — normative and permanent. audit-core exposes no verdict on whether an
# approval is still valid; a consumer branching on such an answer would route an
# authorization decision through the audit fabric.
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 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
system: CNPG PostgreSQL on railiance01
role: audit-core's own operational custody store
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:
proves:
- records held were not altered after arrival
- records held were not truncated after arrival
does_not_prove:
- that a record was ever sent
- absence of a record as evidence of non-occurrence
conditional_on:
- external chain-head attestation stored outside platform-pg
contract: docs/integrity.md
not_claimed: [WORM, object-lock, archival-custody]
# §11 emission guarantee — AUDIT-IN-0005, docs/section-4-source-of-evidence.md
#
# §11 requires the declaration from a repository catalogued in §4 as a SOURCE of
# evidence. audit-core is catalogued as the Evidence engine — the custody and
# detection half — and emits no event into another repository's custody. The
# emission guarantee for an event belongs to the repository that emits it; that
# is audit-core's standing boundary (AUDIT-IN-0001, AUDIT-WP-0009 non-goals) and
# the reason audit-core declines the source role for access-engine's decision
# record.
#
# The one artifact audit-core does produce on its own behalf is declared anyway,
# in the same spirit as uncatalogued_infrastructure above: stated so the check is
# total rather than vacuous, not because §11 is read to compel it. Prose in
# docs/integrity.md is not a machine-readable declaration — the defect audit-core
# raised against another repository, so not one it leaves standing in its own.
source_of_evidence: false
source_of_evidence_note: >-
audit-core holds custody and the detection surface. Emission class, cadence and
detection obligations sit on each sender's registration
(deploy/senders-scope.{json,yaml}, heartbeat_classes per class), never on the
archive. audit-core cannot detect non-production by a source and claims no
ability to — AUDIT-IN-0003, GH-DEC-2026-014 limit 3.
emission_guarantee:
- id: chain-head-attestation
emits: external chain-head attestation for the audit event chain
class: load-bearing
rarity: rare # one scheduled artifact per day, never volume
rate_monitoring: forbidden # §11 / emission-cadence profile, rare class
cadence:
form: scheduled
interval: daily
schedule: "17 3 * * *" # UTC, deploy/attest-cronjob.yaml
producer: CronJob audit-core-attest-chain, its own ServiceAccount
published_to: ConfigMap audit-core-chain-head
detection_surface:
form: freshness-window
window_hours: 168 # 7x the cadence; widens, never removes
on_absence: >-
tamper_evidence degrades to False with the reason recorded, and a missing,
unreadable, undated or stale attestation is treated the same as absent.
Non-production is detected deterministically at read time by the consumer
of the claim, not inferred from a rate.
surfaces: ["GET /v1/integrity", "GET /readyz (last-known, no chain walk)"]
contract: docs/integrity.md
bound: >-
The attestation proves the head it cites; it is not WORM and does not prove
any record was ever sent. An operator-run offsite copy is a separate lane
and is not claimed as part of this guarantee.