Audit (cross-cutting)
Audit is a cross-cutting surface, not a service. It has no container of its own: the producer is a shared library (StellaOps.Audit.Emission) adopted by essentially every WebService in the platform, and the system of record is the Timeline service.
Documents
| Document | Read it when |
|---|---|
| Architecture | You need the contract, the trust boundary, the guarantees (and the non-guarantees), or you are deciding where an audit record should live. |
| Audit Event Emission Guide | You are adding audit emission to a service or endpoint. |
The one-paragraph version
A service tags an endpoint with AuditActionAttribute + AuditActionFilter (src/__Libraries/StellaOps.Audit.Emission/). After the endpoint responds, the filter builds an AuditEventPayload — actor and tenant from the caller’s claims, resource from the route, request body PII-redacted — and HttpAuditEventEmitter POSTs it fire-and-forget to Timeline POST /api/v1/audit/ingest. Timeline persists it into timeline.unified_audit_events under a per-tenant SHA-256 hash chain, with per-classification retention and GDPR right-to-erasure that keeps the chain verifiable.
Three things that catch people out:
- Emission is best-effort. No retry, no spool, no dead-letter. A missing audit row is not proof that the action did not happen — see architecture §9.
- Timeline is the system of record, not EvidenceLocker. EvidenceLocker owns sealed evidence packs; Timeline owns the hash-chained audit log.
- An unknown
?modules=filter is silently ignored, not rejected — so it returns every module’s rows rather than none. The emission-side and query-side module lists have drifted; see architecture §12.1.
Related
- Timeline — the audit sink (store, retention, classification, anomaly detection).
- Module index → Cross-Cutting Concepts — audit vs eventing.
