givanov95/laravel-activity-log
Laravel package for recording activity logs and audit trails. Track user actions and model changes to see who did what and when, with a simple, configurable logging layer for your application.
Actor::user, model, guest, system), role capture, and stored labels mean you can answer "who did what, to what, and under which role" without designing your own schema or backfilling denormalized name columns later.ActivityLog::scrub() is the decision-enabler for GDPR/DSAR work: erasure removes the model's fields from entries about it while retaining the entries it authored (minus IP), which is the shape most legal teams actually want — you keep the audit trail's integrity and lose the personal data. retention_days with activity-log:prune (off by default) gives you a defensible data-retention policy knob you can turn on per environment. Encrypted casts being masked like hidden attributes means you don't have to audit every model before logging it.inScope, forSubject, involving, byActor, byRole, action, and between scopes are a ready-made timeline API. This is the difference between "we can investigate a customer complaint in an hour" and "we can't reconstruct what happened at all." The batch uuid per request/job is the highest-leverage feature here — it lets support correlate every write from a single web request or queued job, which is where most "how did this record get into this state" tickets actually end.ActivityLog::forgetScope() plus actor roles and stored labels support tenant-scoped visibility rules ("admins see everything in their org; users see only their own entries") without custom query plumbing.Changes API (fromModel(), created(), deleted(), snapshot()->diff() with only/except/mask/merge) directly serves the "diff view" UI that makes these features feel finished rather than raw.Adopt when:
fromModel, hidden/encrypted masking that mirrors model behavior) remove the usual week of schema debate.snapshot()->diff() on Laravel 11.Look elsewhere or wait when:
Changes::fromModel(). It throws a LogicException there — Model::getPrevious() arrives in 12. snapshot()->diff() is a real workaround, but you should verify diff fidelity for your models before committing it to a spec.by() plus the configurable resolver does give you an escape hatch, but verify it).retention_days is off by default — if retention is a requirement, that's a configuration task on your side, not a delivered control. Treat it as a launch checklist item.snapshot() diffs carry cost. Validate on representative models before assuming it's free.Migration/risk notes: v1.0.0 establishes the schema and public API surface, so pin the version and treat ActivityLogEntry as a contract from day one. Decide scrub() semantics with legal before you need them — specifically that erasure is asymmetric (subject fields removed, authored entries retained with IP stripped) — because retrofitting that expectation after an incident is expensive.
For executives: This is a small, focused addition that closes three expensive gaps at once — audit/compliance evidence, customer-facing transparency, and incident investigation — without a bespoke build. It gives us defensible GDPR erasure and data-retention controls (both configurable, retention deliberately opt-in so nothing silently expires), and it writes audit records inside the same transaction as the business change, so we can state in security reviews that a committed change is a logged change. The cost is a dependency plus a configuration and legal review, not a project.
For engineering: Laravel-native activity logging with a fluent builder and an explicit actor model (user/model/guest/system plus role and stored label), so we stop hand-rolling created_by/updated_by and denormalizing names into five tables. Append-only immutable entries, a request/job batch uuid for correlation, and a complete scope set (forSubject, involving, byActor, byRole, action, between) that covers the admin feed and the support timeline without new query code. The Changes API mirrors Eloquent's own comparison rules, masks hidden and encrypted attributes, and supports only/except/mask/merge — so diffs are safe by default. Two caveats to plan around: writes are synchronous on our connection (good for integrity, a cost on hot paths, and we should measure it) and Changes::fromModel() requires Laravel 12 — on 11 it throws, so use snapshot()->diff() or upgrade first. scrub() and activity-log:prune give us erasure and retention as commands, not one-off scripts; retention is off until we set retention_days.
For security/legal: Erasure is asymmetric by design — entries about a model lose its fields; entries the model authored are retained with the IP removed, preserving audit-trail integrity while satisfying the access-rights requirement. Confirm that this reading matches your erasure opinion. Encrypted casts are masked like hidden attributes and unchanged hidden fields are never reported, which reduces the risk of sensitive data leaking into the log by default. Immutability is enforced at the model layer, not cryptographically — if we need tamper evidence or external retention, that's a separate investment.
How can I help you explore Laravel packages today?