Download the PHP package softartisan/laravel-audit-events without Composer
On this page you can find all versions of the php package softartisan/laravel-audit-events. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download softartisan/laravel-audit-events
More information about softartisan/laravel-audit-events
Files in softartisan/laravel-audit-events
Package laravel-audit-events
Short Description Tamper-evident audit trail for Laravel: automatic Eloquent model auditing, free-standing semantic events, an HMAC hash-chain integrity guarantee, and cold archiving for long-term compliance.
License MIT
Homepage https://github.com/softartisan-inc/laravel-audit-events
Informations about the package laravel-audit-events
Laravel Audit Events
A production-ready Laravel package that automatically audits Eloquent model changes, records free-standing semantic events, guarantees cryptographic integrity of every audit record, and provides a cold archiving strategy for long-term retention — designed for ERP systems and compliance-sensitive applications.
Why another audit package?
spatie/laravel-activitylog and owen-it/laravel-auditing are excellent and, for
most apps, the right choice. Reach for this package when you specifically need:
- Tamper-evidence — an HMAC hash-chain per record with a
verifycommand, not just a log table anyone with DB access can silently edit. (threat model) - One model for everything — automatic model audits and free-standing
semantic events (
user.logged_in,csv.exported,impersonation.started) in a single, queryable table. - Compliance retention built in — cold archiving to a DB table or JSONL files, per-tenant retention, and pruning.
- Multi-tenant by accident, not by coupling — writes to the current connection, zero dependency on any tenancy package (works the same in a plain Laravel app).
If you don't need integrity guarantees or free-standing events, the established packages are lighter. We'd rather you pick the right tool.
v2.0 — breaking changes: Package renamed from
softartisan/laravel-model-auditstosoftartisan/laravel-audit-events. See the Upgrade Guide below.📖 Looking for "how do I do X?" See the scenario-driven Use-Case Cookbook →
USE-CASES.md— every use case (auto-audit, manual/free events, jobs, revert, export, multi-tenant isolation, impersonation, integrity, retention, frontend rendering…) with copy-paste code.
Features
- Automatic audit trail for
created,updated,deleted,restoredEloquent events AuditContext::actingAs()— inject the causer in queue jobs whereAuth::id()isnullModelAudit::record()— record free-standing events (login, export, PDF…) without an Eloquent anchorsaveHistory()— manually record a semantic event bound to a specific modelTracksRelationChanges— track pivot/sync relation changes (many-to-many)- Deep JSON diff — recursively diff array/JSON fields to pinpoint sub-key changes
- Global + per-model attribute masking (passwords, tokens, credit cards…)
- Cryptographic integrity — HMAC-SHA256 signature + hash chain per model, tamper-evident audit trail
- Cold archiving — move old records to a dedicated table or daily JSONL files instead of deleting them
- Configurable pruning with per-tenant retention
audit-events:stats— audit statistics at a glanceaudit-events:verify— bulk integrity verificationaudit-events:archive— archive old records to cold storage- MCP server integration (optional, requires
laravel/mcp) - PHP 8.4 · Laravel 12 · Pest · PHPStan level 5
Table of Contents
- Installation
- Upgrade from v1.x
- Basic Usage
- Querying Audit History
- Restore a Model
- Attribute Masking
- AuditContext — Queue Jobs
- Free Events — ModelAudit::record()
- saveHistory() — Manual Model Events
- TracksRelationChanges
- Deep JSON Diff
- Cryptographic Integrity
- Cold Archiving
- Pruning
- Artisan Commands
- Configuration Reference
- Testing
- Changelog
Installation
Publish the config and run the migrations:
Upgrade from v1.x
Breaking changes in v2.0:
- Package renamed:
softartisan/laravel-model-audits→softartisan/laravel-audit-events- Namespace changed:
SoftArtisan\LaravelModelAudits→SoftArtisan\LaravelAuditEvents- Config key changed:
model-audits→audit-events- Artisan command renamed:
model-audits:stats→audit-events:stats- Audit table renamed:
model_audits→audit_events
Step 1 — update your composer.json:
Step 2 — update all use statements and config references in your app:
Step 3 — publish the new config and run migrations:
The bundled rename_model_audits_to_audit_events_table migration renames model_audits → audit_events safely (checks table existence before acting). To keep the old table name, override the config:
Basic Usage
Attach IsAuditable to a model
Every created, updated, deleted, and restored event now produces an audit record automatically.
Querying Audit History
Query scopes on ModelAudit
For querying across the whole audit_events table (not just one model's audits()
relation), three local scopes are available:
Restore a Model
Roll back a model to the state stored in a previous audit's old_values:
Columns that no longer exist in the table are silently skipped.
Attribute Masking
Globally in config/audit-events.php:
Per model — override getHiddenForAudit():
Masked attributes are stripped from both old_values and new_values before storage.
AuditContext — Queue Jobs
In queue jobs, Auth::id() is null because there is no active session. Use AuditContext::actingAs() to inject the causer manually.
AuditContext is a static class. Reset is mandatory at the end of every job because PHP-FPM/Swoole workers reuse the same process.
Free Events — ModelAudit::record()
Record semantic events that have no Eloquent model anchor:
Signature:
Free events are never filtered by the events whitelist.
saveHistory() — Manual Model Events
Record a custom semantic event bound to a specific model instance:
Signature:
Not subject to the events whitelist.
TracksRelationChanges
Laravel does not emit Eloquent events when pivot tables are modified (sync, attach, detach). Use this trait alongside IsAuditable to track those changes manually.
The audit record event will be relation.synced. The old_values and new_values are keyed by the relation name:
Deep JSON Diff
When a model has a JSON/array column, getDiff() recursively diffs it to pinpoint exact sub-key changes:
Configure in config/audit-events.php:
Cryptographic Integrity
The integrity feature adds a tamper-evident HMAC-SHA256 signature to every audit record, plus a hash chain that links each record to its predecessor within the same model's history.
Setup
Step 1 — run the migration:
Step 2 — enable in config/audit-events.php:
Step 3 (optional) — set a dedicated signing key in .env:
Then reference it in the published config:
How it works
Each new audit record receives:
signature(varchar 64): HMAC over a canonical JSON payload coveringauditable_type,auditable_id,event,user_id,old_values,new_values,context,created_at, andprevious_hash.previous_hash(varchar 64): thesignatureof the immediately preceding record for the same(auditable_type, auditable_id)pair.nullfor the first record.
The hash chain scope is per model instance — two different Invoice records maintain independent chains, avoiding write contention. Free-standing events (no auditable) are chained by user_id.
Verifying a single record
Bulk verification
Exit codes: 0 = all signed records passed · 1 = tampered records found (or integrity disabled).
Records created before the feature was enabled are reported as unsigned (not tampered) and do not affect the exit code.
Key management
- Use a dedicated key (
AUDIT_SIGNING_KEY) separate fromAPP_KEYso that rotating your app key does not invalidate existing audit signatures. - Store the key in a secrets manager (AWS Secrets Manager, HashiCorp Vault). Do not store it only in
.envfor compliance-critical applications. - If you must rotate the signing key, re-sign historical records via a one-off artisan command (not provided — implement in your app with
AuditSignatureService).
Cold Archiving
Archiving moves records older than a configurable threshold to cold storage, preserving them for legal/compliance purposes while keeping the hot audit_events table lean.
Setup
Step 1 — run the migration (database driver):
Step 2 — enable in config/audit-events.php:
Step 3 — schedule the archive command:
Database driver
Moves records in transactional batches (default 500/batch). Each batch:
- Bulk-inserts into
audit_events_archive(witharchived_attimestamp) - Deletes from
audit_events— only if the insert succeeded
The archive table has an identical schema to audit_events, plus archived_at. Signatures and hash chain columns (signature, previous_hash) are preserved.
JSON file driver
Appends records to daily JSONL files (one JSON object per line):
Each line is a complete JSON representation of the audit record plus archived_at. Files can be gzipped and uploaded to S3 for long-term storage.
Archive command options
Hash chain continuity after archiving
After archiving, the live table has a gap at the chain boundary. The next new audit record on the same model will reference the most recent remaining live record's signature as its previous_hash. The archived record retains its signature intact and can be cross-referenced manually.
When running audit-events:verify, a chain break at an archive boundary is expected. The verify command reports it as a gap rather than tampering.
Pruning
Pruning deletes records permanently. Use it for data that has no legal retention obligation.
When enabled is true, the service provider auto-schedules model:prune daily. You can also schedule it manually:
Multi-tenant retention
keep_for_days is read dynamically at every pruning run (never cached), so multi-tenant applications can set different retention periods per tenant:
Pruning vs. Archiving
| Pruning | Archiving | |
|---|---|---|
| Records after operation | Deleted permanently | Preserved in cold storage |
| Compliance-safe | Only if retention period met | Yes |
| Hash chain | Broken at deletion | Intact in archive |
| Recommended for | Non-sensitive operational data | Financial, medical, legal records |
Use pruning for high-volume, low-sensitivity events. Use archiving when records must be retained for legal or compliance reasons.
Artisan Commands
audit-events:stats
Display audit event statistics.
Output includes: total records, breakdown by event type, top 5 audited model classes, date range, table size (MySQL/PostgreSQL), and archive stats when archive.enabled = true.
audit-events:verify
Verify the cryptographic integrity of audit records. Requires integrity.enabled = true.
Exit codes: 0 = pass · 1 = tampered records or feature disabled.
audit-events:archive
Move old audit records to cold storage.
audit-events:stats (archive section)
When archive.enabled = true, the stats command adds an archive section:
Configuration Reference
Testing
Or directly with Pest:
Static analysis:
Testing in your application
Disable integrity in tests to avoid APP_KEY dependency:
Or enable it with a known key:
Changelog
See CHANGELOG.md.
License
MIT. See LICENSE.md.
All versions of laravel-audit-events with dependencies
illuminate/contracts Version ^11.0||^12.0
spatie/laravel-package-tools Version ^1.16