Skip to content

Audit log

Every sensitive action (creation / deletion / privilege escalation, adding a cloud connector, licence change, OIDC configuration, account deletion…) is recorded in the audit_logs table and viewable via /admin/audit.

Recorded fields

Field Content
id internal id (auto-increment)
created_at UTC timestamp
actor_user_id user who performed the action (or null = system)
actor_ip source IP (from X-Forwarded-For behind the proxy)
action action code — e.g. user.create, org.delete, oauth.attach, license.activate
target_type type of target object (user, org, cloud_connection…)
target_id id of the target object
metadata free-form JSON (e.g. {"old_role": "member", "new_role": "admin"})

Pseudonymisation: no email, no RAG query content is stored in the log. Only numeric user_ids are kept. See app/utils/logger.py.

Search & filters

/admin/audit provides:

  • Filter by action (autocomplete)
  • Filter by user (id or email — resolved to id at submission)
  • Date range
  • CSV export (capped at 10,000 rows per export)

Off-host archival

The archive_audit_log cron (Sundays 03:30 UTC) **archives entries

180 days to an S3 bucket (server-side encrypted, Glacier IR class or equivalent). Archived rows are then deleted** from the main table to limit growth.

Configuration via .env:

AUDIT_S3_BUCKET=myeline-audit-archive
AUDIT_S3_ENDPOINT=https://s3.fr-par.scw.cloud
AUDIT_S3_ACCESS_KEY=AUDIT_S3_SECRET_KEY=AUDIT_S3_RETENTION_DAYS=180   # default: 180

Without AUDIT_S3_BUCKET the cron is a no-op (no data loss, just no archiving). In pure sovereign, point at an internal MinIO rather than a cloud S3.

13 months active + archive up to 5 years for actions related to personal data (GDPR, art. 30 — processing registry). Adjust AUDIT_S3_RETENTION_DAYS upward depending on your internal policy.