Pro Edition
The audit log records security-relevant actions as structured events. Each record carries:
event_type— the dotted name below;user— the authenticated actor, or the system/actor name;account_id— the affected account when the event has exactly one, otherwisenull;payload— event-specific JSON (target ids, counts, reasons, request ids);prev_hashand the chain fields covered in Audit Log & Integrity.
Use GET /api/v1/audit-log to query and GET /api/v1/audit-log/{record_id}/detail for one record.
Events forwarded to SIEM
SIEM forwarding is category-based. These are the categories and the events each contains.
login
| Event | Meaning |
|---|---|
user.login | Password login |
ldap.login / ldap.login_failed | LDAP bind success / failure |
sso.login / sso.logout | OIDC login and RP-initiated logout |
mfa.enabled / mfa.disabled | User changed TOTP state |
mfa.reset_by_admin | Administrator reset a user's MFA |
delete
| Event | Meaning |
|---|---|
email.deleted / email.batch_deleted | Single / bulk message deletion |
retention.purged | Scheduled retention sweep removed messages (account, count, cutoff, window) |
account.removed | Account deleted |
user.removed | User deleted |
role.removed | Custom role deleted |
access_token.removed | API token revoked |
oauth2.removed / proxy.removed | Provider / proxy deleted |
saved_search.deleted | Saved search deleted |
mailbox.removed | Mailbox removed from tracking |
export
| Event | Meaning |
|---|---|
export.started / export.completed / export.failed / export.cancelled | Export job lifecycle |
export.downloaded | Artifact downloaded |
export.verified | Compliance verification finished |
email.exported | Individual message exported |
repair
| Event | Meaning |
|---|---|
email.repaired | Message content re-fetched and repaired in place |
admin
| Event | Meaning |
|---|---|
user.created / user.updated | User created / changed |
role.created / role.updated / role.delegated / role.delegation_removed | Role and delegation changes |
access_token.created | API token created |
account.created / account.updated | Account created / changed |
retention.policy_changed | Retention or minimum-retention window changed, with before/after values |
account.download_started / account.download_stopped | Manual sync started / cancelled |
account.role_assigned | Account role granted in bulk |
oauth2.created / oauth2.updated / oauth2.token_stored | OAuth provider and token changes |
proxy.created / proxy.updated | Proxy changes |
integrity.check_started / check_completed / check_cancelled | Integrity job lifecycle |
integrity.report_downloaded | Integrity report downloaded |
legal.hold.placed / legal.hold.released | Legal-hold changes |
approval.requested / approved / rejected / expired / executed / execution_failed | Dual-control lifecycle |
gdpr.erasure_requested | GDPR Art. 17 erasure request record (runs with admin so it stays with its approval trail) |
license.uploaded | License installed |
settings.changed | Runtime configuration changed |
branding.updated | Branding changed |
timestamp.anchored | Timestamp anchor created |
import.performed | Import completed |
saved_search.created / saved_search.renamed | Saved search created / renamed |
search.performed | Search executed |
Events recorded but not forwarded
These events remain in audit.db and are queryable, but category_of() returns no category, so SIEM forwarding never sends them:
| Event | Why it is local-only |
|---|---|
email.viewed | Routine read; kept out of admin to avoid noise |
email.restored | Restore-to-IMAP, not a deletion |
email.tagged / attachment.tagged | Metadata change |
attachment.downloaded / attachment.previewed | Read activity |
audit.log_queried | Reading the audit log itself |
backup.config_updated | Backup policy change |
compliance.config_updated | Compliance runtime overrides |
remote_cleanup.previewed / run_finished / message_moved / blocked | Source-mailbox cleanup activity |
siem.config_updated / siem.forward_failed | Excluded deliberately to prevent a forwarding feedback loop |
Payload conventions
Payloads vary by event, but several conventions are stable:
approval.*carriesrequest_id,op, and — on approval —requested_by,succeeded/failedcounts when known. A background operation approved before execution has no counts yet; they appear onapproval.executed.email.batch_deletedexternalizes per-item detail to a file under<root>/audit/detail/when the batch exceedsBICHON_AUDIT_DETAIL_THRESHOLD(default 100); the row keeps a reference.gdpr.erasure_requestedcarriessubject,criteria,assessment,messages,account_ids,queued, andrequest_id.license.uploadedcarries the licensee and edition.siem.*events never trigger another forward.
The full schema is available in the OpenAPI spec at /api-docs and in the audit record detail endpoint.