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 logs entry appears in the Organization sidebar only when the entitlement is on for your organization. Inside, you'll find:
- Filterable list — narrow by actor, action category, target type, and date range. Future dates are blocked and the upper bound is always ≥ the lower bound.
- Infinite scroll — newest events first; older events load as you scroll.
- Detail sheet — click any row to see the full metadata, request ID, IP, and user agent.
- Refresh — pulls the latest events without losing your filter selection. 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 is hidden 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 target type or target ID to scope down.
- No live tail. The list refreshes on demand or when you click Refresh — there's no WebSocket stream.
