|
<div class="docs-content" data-render>
|
|
# Audit Log
|
|
|
|
The audit log is the authoritative, append-only record of every state-changing action
|
|
on the platform: who acted, in which role, from where, on which objects, what changed,
|
|
and when. It is **administrator-only**: the viewer, its routes, and every monetary
|
|
figure it records are restricted to admins.
|
|
|
|
> This page is visible to administrators only.
|
|
|
|
## Viewing the log
|
|
|
|
- **`/admin/audit-log`** lists events newest-first, 25 per page, with the same
|
|
pagination and table styling as the rest of the admin panel. The sidebar entry sits
|
|
just above Settings.
|
|
- A filter bar narrows the list by free-text search (summary, event key, target),
|
|
category, event key, actor role, origin, result, and a date range. Filters are
|
|
carried through pagination links.
|
|
- **`/admin/audit-log/{uid}`** is the per-event detail page: the full row, the
|
|
old to new value transition, pretty-printed JSON metadata, and a table of related
|
|
objects (actor, target, parent, author, recipient, source, destination,
|
|
schedule, instance, setting, job, and more).
|
|
|
|
Both routes negotiate content: send `Accept: application/json` to receive the
|
|
structured `AuditLogOut` / `AuditEventOut` payload instead of HTML.
|
|
|
|
## What is recorded
|
|
|
|
Every event carries WHO (`actor_kind`, `actor_uid`, `actor_username`, `actor_role`),
|
|
FROM WHERE (`origin`, `via_agent`, `request_method`, `request_path`, `actor_ip`,
|
|
`user_agent`), the primary object (`target_type`, `target_uid`, `target_label`), the
|
|
change (`old_value` to `new_value`), a sanitised `summary`, event-specific `metadata`,
|
|
and a `result` of `success`, `failure`, or `denied`. A second table,
|
|
`audit_log_links`, records each related object with a labelled relation, so an event
|
|
can reference any number of objects.
|
|
|
|
The complete catalogue of event keys (155 across authentication, content, votes,
|
|
projects, files, news, admin, services, containers, ingress, AI, the Devii agent, the
|
|
CLI, rewards, and security) is enumerated in `events.md` at the repository root.
|
|
|
|
## Security model
|
|
|
|
- **Admin-only.** The list and detail routes are gated by `require_admin`; non-admins
|
|
receive a redirect (or a 403 for JSON). Financial values (cost, pricing, spend) are
|
|
recorded for completeness but only surfaced on this admin-only page.
|
|
- **Append-only.** Rows are never updated. The only deletion is the retention sweep.
|
|
- **Best-effort.** Recording never raises into a request handler. A failure to write
|
|
an audit row is logged and swallowed, so the audited action is never blocked.
|
|
- **Failures and denials are events too.** Authentication failures, authorisation
|
|
denials, read-only write attempts, self-role-change and self-disable attempts, and
|
|
quota blocks are all recorded with `result` set to `failure` or `denied`.
|
|
- **Agent attribution.** When the Devii agent performs a platform mutation, the same
|
|
event key is recorded with `origin=devii` and `via_agent=1` (the agent's HTTP client
|
|
sends an `X-Devii-Agent` header), so an auditor can answer "what did the agent do on
|
|
my behalf" without a parallel taxonomy. Mechanics with no HTTP equivalent get
|
|
`devii.*` keys.
|
|
|
|
## Retention
|
|
|
|
Rows older than `audit_log_retention_days` (default 90) are pruned daily by the
|
|
**Audit retention** background service, configurable on the Services page. Set the
|
|
retention to `0` to disable pruning entirely.
|
|
</div>
|