Skip to content
Sleep at nightTrust and privacy

Audit trail

A clean record of who did what, and when.

Every important change gets logged automatically: who did it, what changed, when. Admins can browse and export the history. You never build event plumbing yourself.

  • 90 days

    longest export window

  • 10,000

    record cap per export

  • 5

    kinds of actors the log can name

The problem this solves

Without a shared foundation, every team rebuilds these edge cases — differently.

Six months of logs nobody can read

Every feature invents its own log format. Then a customer asks "who deleted this?" and the rows can't even agree on what an actor is.

The same deletion, logged three times

A retried job writes a duplicate entry on every replay. Reviewers stop trusting a trail that repeats itself.

The export that takes down the database

An unlimited download button eventually asks for years of rows in one request. You find out during a compliance review, at the worst possible moment.

How it works

The mechanism end to end, as implemented in the repository.

  1. 1

    Every event goes through one function

    Server code logs events using types from a central registry. Half-built event types throw an error instead of quietly writing junk rows.

  2. 2

    Each event gets a stamped envelope

    Version, actor, resource, outcome, and a hashed IP get added and validated before saving. Raw IP addresses are never stored.

  3. 3

    Admins browse their own history

    Listing checks admin role and plan entitlement on the server, then pages through rows 100 at a time, always scoped to one organization.

  4. 4

    Exports run inside hard limits

    Exports allow up to 90 days and 10,000 records in JSON or NDJSON, and the export itself becomes a new audit event.

Interactive example

See it working

This walkthrough demonstrates the implemented backend contract without using an account, credentials, or provider calls.

Interactive example

Explore the implemented decisions

Choose a sample state
Tenant-scoped events

Deterministic sample data only. No account, provider, or network connection is used by the interaction.

Highlights

Why it matters

One writer, no duplicates

Every event goes through one function, and a retried job can't write the same entry twice.

Admin-only access

Only org admins on plans with the audit feature can browse or export, checked on the server every time.

Exports with guardrails

Exports cap at 90 days and 10,000 records, and every export is itself logged.

Engineering guarantees

What this does and does not promise

Safety boundary

The log records what happened; it doesn't control access, so every browse and export re-checks permissions on its own. Retention periods are declared in the registry, but running the purge job that enforces them is up to your deployment.

Implementation evidence

The boundary above is code, not a claim. These files carry the contract:

  • src/features/enterprise/server.ts
  • src/registries/audit-events.ts
  • src/features/enterprise/contracts.ts
Questions

Frequently asked questions

Build on the audit trail foundation

The docs describe the same contracts this page demonstrates.