# Audit log

Read-only view of `audit.events` per ADR-0013. Every query run on this page emits its own `admin.audit.query` row — read access is itself auditable.

## Filters

Event type Actor id hash Audience
Outcome
Subject prefix From To Page size
@if (tab() === 'table') { @if (loading()) { Loading… } @else if (error(); as msg) { {{ msg }} } @else if (page(); as p) { {{ resultRange() }} } } @else { @if (statsLoading()) { Loading statistics… } @else if (statsError(); as msg) { {{ msg }} } @else if (stats(); as s) { {{ s.total }} matching event(s) aggregated } }
@if (stats(); as s) { @if (hasChartData()) {

Aggregations are computed across the full filtered set (server-side), not just the events on the current page. Results are cached for 5 minutes per filter combination.

} @else {

No audit events match the current filters.

} } @else if (!statsLoading() && !statsError()) {

Switch to this tab to load statistics.

}
@if (page(); as p) { @if (p.items.length === 0) {

No audit events match the current filters.

} @else {

Timestamp | Event | Audience / outcome | Actor / subject | Trace | Payload
--- | --- | --- | --- | --- | ---
@for (event of p.items; track event.id) {
{{ formatTimestamp(event.createdAt) }} | {{ event.eventType }} | {{ event.audience }} {{ event.outcome }} | @if (event.actorIdHash; as hash) { } @else { (anonymous) } @if (event.subject; as subject) { {{ subject }} } | @if (event.traceId; as traceId) { {{ traceId }} } @else { — } | @if (event.payload) { view
    {{ formatPayload(event.payload) }}
} @else { — }
}

} }