Audit Logs
Audit logs record every state-changing action in your organization — role assignments, engine edits, API key issuance, billing changes — and surface them in a searchable, filterable timeline. Available on the Enterprise plan alongside Roles & Permissions.
The log is append-only at the database level: the application's connection cannot update, delete, or truncate audit rows. What gets written, stays written.
What's recorded#
Each event captures the actor, action, target, and the HTTP context the request arrived on.
| Field | Notes |
|---|---|
| Actor | The user or API key that performed the action |
| Action | A typed value like engine.created or member.role_changed |
| Target | The entity that was touched (e.g. an engine, a role, a glossary item) |
| Metadata | IDs of related entities — never names, emails, or content snippets |
| Request context | request_id, IP address, user agent — captured when the call came in over HTTP |
| Timestamp | UTC, plus a monotonic sequence number for gap detection |
IDs only, by design
The metadata column stores IDs, not human-readable values. The UI joins to current names at read time, so renaming an engine or user doesn't rewrite history. It also keeps audit rows out of GDPR right-to-erasure conflicts — there's no content to redact.
Actions covered#
Events are grouped into categories that match the filter in the dashboard.
| Category | Actions wired today |
|---|---|
| Organization | org.created, org.settings_updated, org.ownership_transferred, org.deleted |
| Members | member.invited, member.removed, member.role_changed |
| Roles | role.created, role.updated, role.deleted |
| Engines | engine.created, engine.updated, engine.deleted |
| API keys | api_key.created, api_key.revoked |
| Content | glossary_item.*, instruction.*, brand_voice.* (singular operations only) |
Accessing the log#
The Audit log entry always appears in Settings, under Admin. Without the entitlement, the page shows "Audit log is not on your plan" instead of the timeline. Inside, you'll find:
- Filterable list — narrow by Action, Actor, and Period (a preset such as Last 7 days, or a From / To date range). Future dates are blocked.
- Load older events — newest events first; click Load older events at the foot of the list to fetch the next page.
- Event detail — click any row to expand it in place and see the full metadata, request ID, IP, and user agent.
- Shareable views — filters and the open event are reflected in the URL, so any view is shareable.
Who can view#
Two gates control access to the page:
- Entitlement — the audit-logs feature must be enabled for the organization (Enterprise plan).
- Permission — the viewer's role must include
org:view_audit_logs. The seeded Full Access role includes it by default; Owners always have it.
Members without the permission see a "no access" page instead of the timeline. Members of an organization without the entitlement see a paywall.
If your Enterprise plan lapses
Audit logs are part of the same RBAC-tier entitlement. Past events stay in the database, but the page shows "Audit log is not on your plan" and the read endpoints return 403 until the plan is restored.
Tamper-evidence#
Audit logs aren't just a record — they're meaningfully hard to alter after the fact.
- Append-only at the database level. The migration that installs the table runs
REVOKE UPDATE, DELETE, TRUNCATEon the API role. Any future code path — bug, new endpoint, even SQL injection — is rejected by Postgres before it can change a row. - Monotonic sequence. Every row carries a strictly increasing
seqcolumn. An auditor scanning the sequence can detect deletions as gaps.
This is sufficient for SOC 2-style controls. It does not defend against an attacker with direct production database credentials — stronger postures (separate-owner role, WORM mirror) are available on request.
Retention#
Audit events live indefinitely by default. Custom retention windows — typically 1, 3, or 7 years — are available on Enterprise. Reach out if you need a specific retention policy for compliance or security questionnaires.
What's not covered#
A few deliberate v1 boundaries to be aware of:
- Best-effort emit, not transactional. Transactional emit is on the near-term roadmap. The audit event is written after the action it describes — not inside the same database transaction. In rare failure modes (an action that succeeds and then the audit insert fails) the action can happen without a corresponding event.
- Some action types aren't wired yet. Engine membership changes, integration connect / update / disconnect, model-config edits, billing subscription changes, and bulk content operations (CSV upload,
createMany/updateMany/deleteMany) don't yet produce events. The action vocabulary is reserved so they show up under the existing filter categories once wired. - Reads are not audited. Viewing the audit log itself, browsing engine request logs, or downloading a glossary does not produce events. Only state-changing actions do.
- No exports yet. Audit data is surfaced through the dashboard. CSV export, SIEM webhook, and S3 mirror are on the roadmap — let us know if you need them.
- No engine-scoped view. All audit events for the organization live on a single timeline. Filter by action or actor to scope down.
- No live tail. There's no Refresh button and no WebSocket stream — reload the page to pick up newer events.