Actors

Every event the trail records names the principal that caused it. There are five kinds, and which one an event carries is what most queries filter on first.

The five

Actor typeWho
userAn authenticated person
serviceA service account or a CI token
systemAn internal job. No external actor
anonymousAn unauthenticated request
control-planeA management client, calling in under the control-plane strategy

actorId is the principal’s stable id — a user id, a service or token name. Null for system and anonymous, because there is nobody to name.

Why the control plane is its own kind

It could have been a flavor of service. It is not, and the reason is the question an adopter actually asks.

“What did the management client do” is a different question from “what did my users do.”

A control-plane caller is not a user of the application at all — it holds no session and owns no user row. Folding it into user or service would make that question unanswerable from the trail, and it is precisely the question somebody asks after granting a dashboard access to their production environment.

Filtering the trail on actorType: "control-plane" is what separates a management client’s actions from the adopter’s own users’.

Outcome is not severity

Two orthogonal axes, and conflating them loses information both ways.

Outcome — what happened:

successIt worked
failureIt was attempted and errored
deniedAn authorization gate blocked it

denied is first class. Blocked attempts are recorded, not only successes — which is the entire value of a security trail. A trail of things that worked cannot show you somebody trying.

Severity — how serious:

infoRoutine
warningNotable
criticalAlert-worthy

A successful action can be critical (a production secret rotated). A failure can be routine (a mistyped password). Neither axis predicts the other, which is why both are stored.

Correlation fields

Field
sessionIdTies a chain of actions together
ipThe client address, for correlation
userAgentThe client string
requestIdTies this event to one request or trace
resourceType, resourceIdWhat the action targeted

All nullable. Null means not known, not zero and not empty. The reference has each column with its type.

What a denied event should carry

The code, not a sentence. Auth’s sign-in refusals record only the Better Auth error code — never the message, which can carry the submitted email address or other request context.

That is the general rule for this trail: no personal data in the reason. The reason is a discriminator; the identity lives in the actor and tenant columns where it is scoped by a read scope.

ESC