Skip to content
DockBoard
Browse the documentation
TEAM & ACCESS

The audit trail

Every state-changing action, who did it, from where, and what it touched.

Every state-changing action on the install leaves a row: who did it, when, from which IP, on what, and whether it succeeded. Admin → Audit, gated by the audit:view platform permission.

What is recorded

Every POST, PATCH, PUT and DELETE that reaches the API. Not a list of instrumented endpoints — a floor that a new module cannot forget to opt into, because it is enforced above the controllers rather than inside each one.

An entry carries:

FieldHolds
ActorThe signed-in user — or empty for a system or anonymous event, such as a failed login on an address matching no account.
ActionA dotted name derived from the whole route, not the verb alone: application.restart, application.env.update, user.role.change.
ResourceWhat it touched, and that object’s id.
Target userWho it was performed on, when that differs from the actor.
OriginIP address, user agent, and the route called.
OutcomeSuccess, or the failure with its status code and message.
The target user field is what makes a person’s own detail page able to say “an administrator reset your password”. Filtering on the actor alone only ever answers “what did this user do”, never “what was done to them”.

Failures are recorded too, and they matter more than successes. A rejected request never reaches the controller, so it is captured before that point — a burst of 403s from one address on one resource is the shape of someone mapping out what they can reach, and it would otherwise leave no trace at all.

What is deliberately left out

  • Reads. A GET changes nothing, and logging every one would bury the mutations under machine traffic.
  • Machine chatter — token refresh, agent heartbeats, health checks, marking a notification read. High volume, no signal.
  • Flood rejections. A banned IP is refused on every request; the ban itself is already recorded once. Rate-limit 429s are the limiter working, not an operator action.
Audit writes are best effort. The action being logged already happened, so a logging failure is a warning in the server log — never an error thrown back at the user. The trail must not be able to fail a deployment.

Request bodies and secrets

The body of a mutation is the interesting part — it says *what* changed, not merely that something did. It also carries passwords, tokens, private keys and environment values, so field names matching a secret pattern are redacted before the entry is stored, and the payload is capped in size.

The redaction is deliberately precise rather than greedy. A blunt filter on code would have swallowed exitCode, and exitCode: 137 is the out-of-memory kill signature — exactly the detail the trail exists to preserve. Over-redacting starves the log as effectively as under-redacting leaks from it.

Reading the trail

The table filters on actor, target user, action, resource, resource id, IP address, free text, a date range, and failures only. The action list is offered from the names actually present, so you filter on what your install really does rather than on a fixed menu.

The three questions it answers fastest:

  • “Who broke production at 14:12?” — a date range plus the application’s resource id.
  • “Is someone probing us?” — failures only, grouped by IP.
  • “What did this contractor touch?” — filter by actor, over their whole engagement.

Entries are kept for 365 days by default and pruned hourly in small batches. The retention is a platform setting — an audit table that grows without bound becomes a disk problem long before it becomes a useful archive, and one unbounded delete would lock the table against every mutation on the install.

If you must keep records beyond your retention window — a compliance obligation, a post-incident file — export the range you need before it ages out. Pruning is unconditional and does not consult what you were about to read.

Calls made with an API key appear like any other, attributed to the key’s owner, with the route recorded. A key is not a way to act without leaving a trail.

The audit trail — DockBoard