Skip to content
ricochet

Audit Logging

Ricochet writes an audit log for security-related and administrative operations, including any actions that affect infrastructure or execute code. Audit logging is always enabled and cannot be disabled. Logs are stored in the database in the audit_logs table by default. To also write them to RICOCHET_HOME/logs/audit, set file_logging = true under [audit] in ricochet-config.toml. Records are written in batches every 200ms or every 256 events, whichever comes first.

View audit log summaries on the Audit Log page, or export the logs.

Records are kept for 365 days by default. Set a different window under [audit] in ricochet-config.toml:

[audit]
retention_days = 90
# to enable file logging in addition to DB writes
# file_logging = true
# Enable file logging in addition to database writes.
# file_logging = true

To never prune audit logs, use:

[audit]
retention_days = "forever"

Pruning runs once a day and records what it removed as an audit_pruned event.

When file logging is enabled, logs are written here:

RICOCHET_HOME/
└── logs/
└── audit/
├── audit.log
├── audit-2026-02-22.log.gz
└── audit-2026-02-21.log.gz

The current day’s log is audit.log.

Each record is a JSON object:

{
"id": "01KJNKR4KXV8FCT1432D2CZG0V",
"timestamp": "2026-03-01T21:09:26.781568Z",
"actor": { "api_key": { "short_token": "Pm93AJQNSTG", "owner_id": "344509059241640593" } },
"event": { "api_key_created": { "short_token": "Pm93AJQNSTG", "name": "CLI Authentication" } },
"authority": "direct"
}
FieldDescription
idUnique ID per record (ULID)
timestampUTC timestamp (ISO 8601)
actorWho performed the action (see Actors)
eventWhat happened and any associated details (see Events)
authorityWhether a global admin override was used (see Authority)

The authority field records direct permissions as direct and admin override privileges as global_admin_override. Admin overrides have a visual indicator on the Audit Log page so you can quickly identify them.

AuthorityDescription
directThe actor held the item-level permission for this action
global_admin_overrideThe actor held no item-level role and acted on their server-wide Admin role instead

The actor field identifies who initiated the audited action.

ActorExampleDescription
user{ "user": { "id": "<user_id>" } }An authenticated user, identified by their IDP subject ID
api_key{ "api_key": { "short_token": "...", "owner_id": "..." } }An API key, identified by its short token and owning user
"system""system"Any action initiated by the Ricochet server
"anonymous""anonymous"An unauthenticated request with no identifiable actor

Events with no associated data are serialized as a plain string. Events with data are serialized as a single-key object.

Authentication events cover user login, logout, and account provisioning.

EventExampleDescription
user_created"user_created"A new user account was provisioned
login_succeeded"login_succeeded"A login completed successfully
logout"logout"A user session was terminated
login_failed{ "login_failed": { "reason": "..." } }A login attempt failed
session_created{ "session_created": { "session_id": "..." } }A session was established for a signed-in user
first_admin{ "first_admin": { "user_id": "..." } }The first user was automatically promoted to Admin

API key events are recorded when keys are created or deleted.

EventExampleDescription
api_key_created{ "api_key_created": { "short_token": "...", "name": "..." } }An API key was created
api_key_deleted{ "api_key_deleted": { "short_token": "..." } }An API key was deleted

Access control events track permission changes and denied requests.

EventExampleDescription
role_changed{ "role_changed": { "target_user_id": "...", "old_role": "...", "new_role": "..." } }A user’s system role was changed
acl_granted{ "acl_granted": { "id": "...", "target_user_id": "...", "role": "..." } }A user was granted access to a content item
acl_revoked{ "acl_revoked": { "id": "...", "target_user_id": "..." } }A user’s access to a content item was revoked
access_denied{ "access_denied": { "resource": { ... } } }A request was denied due to insufficient permissions

Content events are recorded whenever content is deployed, modified, invoked, or removed.

EventExampleDescription
content_deployed{ "content_deployed": { "id": "..." } }Content was deployed
content_deleted{ "content_deleted": { "id": "..." } }Content was deleted
content_invoked{ "content_invoked": { "id": "..." } }A content item was invoked
env_vars_updated{ "env_vars_updated": { "id": "..." } }Environment variables for a content item were updated
scaling_config_changed{ "scaling_config_changed": { "id": "..." } }Scaling configuration for a content item was changed
schedule_changed{ "schedule_changed": { "id": "..." } }A content item’s schedule was changed
visibility_changed{ "visibility_changed": { "id": "...", "old_access": "...", "new_access": "..." } }A content item’s visibility was changed
instance_started{ "instance_started": { "id": "...", "instance_id": "..." } }A worker was started to serve a content item
instance_stopped{ "instance_stopped": { "id": "..." } }A running app instance was stopped
bundle_deleted{ "bundle_deleted": { "id": "...", "deployment_id": "..." } }A deployment bundle was removed by the retention reaper
git_fetched{ "git_fetched": { "id": "...", "commit": "...", "previous_commit": "..." } }A git-backed item was polled and its upstream commit read

An instance_started record names whoever’s request caused the worker to start. Requests to an already-running worker are not audited. A git_fetched record is written on every poll, whether or not the commit moved.

Git credential events are recorded when credentials used for content deployment are created or deleted.

EventExampleDescription
git_credential_created{ "git_credential_created": { "id": "..." } }A git credential was created
git_credential_deleted{ "git_credential_deleted": { "id": "..." } }A git credential was deleted

Reading and expiring the log are themselves audited.

EventExampleDescription
audit_pruned{ "audit_pruned": { "removed": 412, "retention_days": 365 } }Records past the retention window were deleted
audit_exported{ "audit_exported": { "format": "csv", "records": 2048 } }A server admin downloaded the log

A server admin can download the whole log from the Audit Log page as CSV or JSON. Both are served gzipped from GET /api/audit/export?format=csv|json.

The access_denied event includes a resource field identifying what was being accessed.

ResourceExampleDescription
api_key"api_key"An API key
content{ "content": { "id": "..." } }A content item
exec_env{ "exec_env": { "id": "..." } }An execution environment
user{ "user": { "id": "..." } }A user account

The id field is null when the resource ID is not available (e.g. listing operations).