The Audit package provides a tamper-proof activity logging and audit trail system. It tracks model changes, user actions, and system events with built-in integrity verification.
- Automated Tracking: Automatically log model creation, updates, and deletions via traits.
- Tamper Detection: Secure SHA-256 HMAC checksums for every log entry to prevent database manipulation.
- Granular Control: Easily exclude sensitive attributes like passwords or tokens from logs.
- Contextual Metadata: Automatically captures user IDs, IP addresses, and user-agent strings.
- Retention Management: Built-in cleanup tools to manage log growth based on configurable periods.
- Advanced Querying: Fluent API for retrieving changes and history for any model or user.
Audit is a package that requires installation before use.
php dock package:install Audit --packagesThis will automatically:
- Run the migration for Audit tables.
- Register the
AuditServiceProvider. - Publish the configuration file.
Configuration file: App/Config/audit.php
return [
'enabled' => env('AUDIT_ENABLED', true),
'events' => [
'created' => true,
'updated' => true,
'deleted' => true,
'restored' => true,
],
'retention_days' => 90,
'checksum' => [
'enabled' => true,
'algorithm' => 'sha256',
],
'excluded_attributes' => [
'password', 'remember_token', 'api_token', 'two_factor_secret',
],
'queue' => [
'enabled' => env('AUDIT_QUEUE_ENABLED', false),
'connection' => env('AUDIT_QUEUE_CONNECTION', 'default'),
'queue' => env('AUDIT_QUEUE_NAME', 'audit'),
],
];Add the HasAuditTrail trait to any model:
use Audit\Traits\HasAuditTrail;
class Project extends BaseModel
{
use HasAuditTrail;
// Optional: Exclude specific fields
protected array $auditExclude = ['internal_notes'];
}Use the fluent LogBuilder for descriptive manual entries:
use Audit\Audit;
// Fluent, expressive logging
Audit::make()
->event('payment.verified')
->metadata(['amount' => 500, 'gateway' => 'stripe'])
->with('processor_id', 'ch_12345')
->log();
// Log against a specific resource (Auditable)
Audit::make()
->event('document.signed')
->on($document)
->by($user)
->log();Ensure logs haven't been modified externally:
$log = Audit::history()->find($id);
if (!Audit::verify($log)) {
throw new SecurityException("Audit log integrity compromised!");
}Monitor system activity and security health:
$analytics = Audit::analytics();
// Get event distribution (created vs updated vs deleted)
$stats = $analytics->getEventStats();
// Identify high-activity users
$activeUsers = $analytics->getTopUsers(5);In a legal application, every time a document is signed, we need a tamper-proof record of the user, their IP, and the document version.
use Helpers\DateTimeHelper;
public function signDocument(Document $doc, User $user)
{
$doc->update([
'status' => 'signed',
'signed_at' => DateTimeHelper::now()
]);
Audit::make()
->event('legal.document_signature')
->on($doc)
->by($user)
->metadata([
'version' => $doc->version,
'agreement_type' => 'NDA',
'hash_verified' => true
])
->log();
}What is actually stored in the audit_log table:
{
"refid": "aud_secure_987654321",
"event": "legal.document_signature",
"user_id": 42,
"user_ip": "192.168.1.105",
"auditable_type": "App\\Models\\Document",
"auditable_id": 1024,
"old_values": { "status": "pending" },
"new_values": { "status": "signed" },
"metadata": {
"version": "v2.1",
"agreement_type": "NDA",
"hash_verified": true
},
"checksum": "8f3e2... (HMAC-SHA256)",
"created_at": "2026-01-02 10:25:00"
}| Method | Description |
|---|---|
make() |
Start a fluent LogBuilder. |
log($event, $data) |
records a custom audit entry (Legacy/Simple). |
verify($log) |
Validates the checksum integrity of a log. |
history() |
Returns a query builder for all audit logs. |
cleanup($days) |
Purges logs older than the specified retention. |
analytics() |
Returns the AuditAnalytics service. |
| Method | Description |
|---|---|
auditLogs() |
Relationship returning all logs for the model. |
lastAuditLog() |
Returns the most recent audit entry. |
getAuditChanges() |
Compares old/new values from the last update. |
| Attribute | Type | Description |
|---|---|---|
event |
string |
created, updated, deleted, or custom. |
old_values |
array |
State of attributes before the change. |
new_values |
array |
State of attributes after the change. |
user_ip |
string |
Originating IP address of the action. |
The Audit package includes an automated cleanup task that is registered in the framework scheduler. This ensures logs are purged based on your retention configuration.
// packages/Audit/Schedules/AuditCleanupSchedule.php
namespace Audit\Schedules;
use Cron\Interfaces\Schedulable;
use Cron\Schedule;
class AuditCleanupSchedule implements Schedulable
{
public function schedule(Schedule $schedule): void
{
$schedule->task()
->signature('audit:cleanup')
->weekly();
}
}| Error/Log | Cause | Solution |
|---|---|---|
| "Integrity Check Failed" | Log entry data modified in DB directly. | Investigate potential DB breach. |
| "Missing old_values" | Initial 'created' event has no history. | Normal behavior for first entry. |
| "High Disk Usage" | Large volume of logs not being purged. | Run php dock audit:cleanup or adjust TTL. |
- Restrict Exclusions: Ensure sensitive PII and credentials are explicitly added to
auditExclude. - External Storage: For high-security environments, periodically export and sign logs to an external immutable storage.
- Proactive Monitoring: Use
Audit::verify()in sensitive admin areas to alert on any tampering.