
Know who acted, even when no person was there
Wildo distinguishes a person, a machine, the application itself and an action whose actor could not be resolved. Automated work stays recognizable in the same trail as human activity.
That distinction helps an investigator separate expected background work from an action that deserves a closer look.
Example — Identify who acted, including automated work
A scheduled cleanup removes an expired invitation. Its actor is the system. An invitation declined through a person’s authorized action can retain that person’s attribution, even when an internal service completes the work.
For engineers
Resource lifecycle emitters use resolveAuditActorId. They pass the originating execution context instead of inventing a user for background work. Explicit on-behalf-of attribution has priority, then a signed-in user, then a machine or system sentinel.
Selected source from audit-actor.backend.utils.ts:
export function resolveAuditActorId(executionContext: ExecutionContext<any> | undefined): string {
const onBehalfOfUserId = executionContext?.auditActorUserId;
if (typeof onBehalfOfUserId === 'string' && onBehalfOfUserId.length > 0) {
return onBehalfOfUserId;
}
const initiatorIds = executionContext?.initiatorIds;
const userId = initiatorIds?.userId;
if (typeof userId === 'string' && userId.length > 0) {
return userId;
}
if (initiatorIds?.machineCredential) {
return AuditActorSentinel.MACHINE;
}
return isSystemInitiatedExecution(executionContext?.executionType)
? AuditActorSentinel.SYSTEM
: AuditActorSentinel.UNATTRIBUTED;
}
The resolved value is a user ID or a named AuditActorSentinel. A machine sentinel describes the actor category; the execution context and machine-authentication events identify its credential. Do not query it as though it were a user ID.
Preserve the initiating person across internal work
The internal context’s auditActorUserId carries attribution without granting that person’s permissions to the service. The service still runs under its explicitly authorized execution context. Application extensions should preserve that separation when a user action starts background work.
An UNATTRIBUTED result remains distinguishable from routine system work. Monitoring policy decides how to investigate it; an empty identity should never silently become “the system did it.”