Auditing
Every guarded mutation in Snitcher is captured automatically — there's nothing to opt into or instrument by hand.
What gets captured
An EF Core SaveChanges interceptor records every change made through a guarded command as an audit
entry:
- Actor — who made the change.
- Action — a dotted, past-tense name (e.g.
resource.created,scout.revoked). - Category —
Management,Auth, orData. - Outcome —
Success,Failure, orDenied. - Target — what was changed.
- Field-level diff — before/after values for every changed field.
- Correlation ID, source IP, and user agent, for cross-request tracing.
Denied authorization attempts are captured too, with outcome Denied, even though the underlying
action never ran — so the audit log also doubles as a record of who tried to do what they weren't
allowed to.
Sensitive values are redacted
Before a diff is stored, values are scrubbed by:
- A deny-list of key names (
password,token,secret, and similar). - Structural "Secret" flags on fields that are known to hold sensitive data (e.g. secret headers).
- Detection of the
enc:-prefix used by encrypted-at-rest values.
So a before/after diff never leaks a credential, even if the field itself wasn't specifically deny-listed.
Storage & retention
Audit entries are stored in a TimescaleDB hypertable. Retention is configured independently from check-result retention (default 2 years) under Settings → Data Retention.
Querying
Administration → Audit Log gives a filter toolbar over a collapsible timeline — filter by actor, action, resource type, target label, category, outcome, free text, or time range, with cursor pagination for large result sets. Expanding an entry shows the full diff table and metadata (correlation ID, source IP, user agent).
Export the current filtered view to CSV or JSON. CSV export guards against formula injection — any
cell starting with =, +, -, or @ gets a leading quote so it can't execute as a formula when
opened in a spreadsheet.
Permission
Reading the audit log requires the AuditLog Read permission — see
Users & Groups.