The starter includes an audit logging system that tracks user actions and data changes throughout your application, providing a historical record for compliance, security investigations, and debugging.
The system also logs custom events for critical operations:
Role Assignment & Removal
When roles are assigned to or removed from users:
User receiving the role change
Role being assigned/removed
Before state (previous roles)
After state (new roles)
User who made the change
Timestamp of the change
Permission Syncing
When a role’s permissions are modified:
Role whose permissions changed
Old permission set
New permission set
User who made the change
Timestamp of the sync
Impersonation Sessions
When an administrator starts impersonating a user, LogImpersonationAccess (listening for TakeImpersonation) writes an ImpersonationLog to the user_impersonation_logs table with:
Who started the impersonation
Who is being impersonated
When it started
Nothing records when an impersonation ends. Audit entries for changes made while impersonating carry the administrator’s ID in impersonator_user_id.
API Credentials
OAuth clients and tokens have UUID or string keys, which the audits table can’t store, so their changes are recorded as custom events on a person instead:
Audit entries are kept forever by default. Set AUDIT_RETENTION_DAYS to delete older entries; the scheduler’s daily model:prune removes them. Impersonation logs work the same way with IMPERSONATION_LOG_RETENTION_DAYS. Check your record-keeping requirements before setting either. See Data Retention.
For actions that don’t fit standard CRUD operations, log custom audit events. Each one is a case of App\Domains\Core\Enums\AuditEvent, which also says how it’s shown: its label, icon and color in the audit tables, the record timeline and exports, and its place in the Event filter. Add a case for a new event:
caseReportExported='report_exported';
A model with the RecordsAuditEvents trait, as User and Role have, records one in a line:
The audit’s user is whoever is signed in. tags are stored with the audit, and each context entry is added as a key: value tag, as AuditsRoles does with the modification origin and a reason. An event with nothing before or after isn’t recorded.
By default, Laravel Auditing disables audit logging for console commands (the audit.console config is false). Seeders that create or update Auditable models, such as RoleSeeder and PermissionSeeder, would not produce audit entries by default.
For production seeders that manage security-relevant data (roles, permissions, stakeholder assignments), this creates a gap in the audit trail. The AuditsSeederChanges trait solves this by registering the AuditableObserver directly on specified models.