symfonic.platform.audit¶
audit ¶
AUD-1..4 — one narrow seam, and what happens when it breaks.
AUD-4 is the clause with teeth and it is the platform-side answer to T3.4.5's
finding F-1: a broken objector that never reaches degraded_stages, i.e.
a monitoring surface reporting health while a guard is down. So a failing sink
does two things it does not do today — it raises a degradation signal, and for
a destructive operation it fails the operation closed. An erasure that
proceeds after its intent record was dropped is an untraceable destruction, and
"we tried to log it" is not a trail.
AuditSeam ¶
AuditSeam(sink: AuditSink | None = None, *, on_degraded: Callable[[AuditRecord], None] | None = None)
The one path platform services write audit facts through.
Handlers do not construct sinks and do not reach for a module-level emitter; they are handed a seam. That is what makes "every administrative operation is audited before it mutates" (ADM-6) checkable rather than conventional.
Source code in src/symfonic/platform/audit.py
degraded
property
¶
True once a record failed to land. Sticky: it describes the host.
record
async
¶
Emit. On failure, degrade loudly — and for destruction, fail closed.
Source code in src/symfonic/platform/audit.py
AuditSinkError ¶
NullAuditSink ¶
Drops records. The default only because a host that wants none says so.