Skip to content

v2.0.0

Choose a tag to compare

@RomaLytar RomaLytar released this 14 Jun 11:41
· 4 commits to master since this release
d4b32ae

Application-level provenance and change history for queue-heavy, distributed Laravel apps. Every change is recorded with the real actor, the origin that survives the queue, and a correlation chain back to the one action that caused it — with a verifiable, tamper-evident history on top.

Provenance (the core)

  • Multi-level actor attribution: user / job / command / scheduler / system, resolved by an extensible provider chain.
  • Origin that survives the queue: a job dispatched by a user keeps that user, serialized into the payload across real workers — proven by a database-worker test.
  • Correlation id + cross-model trace: one id per request / command / job cascade, drawn as a ladder indented by job-nesting depth.
  • Impersonation-aware: "Jane Doe (impersonated by Support Admin)" — login-as is attributed to both, not just the victim.
  • Foreign-key label snapshots ("John Doe", not user_id: 5), captured at event time and surviving row deletion.

Forensics and compliance

  • Time machine: reconstruct the exact state a record had at any past date, read-only.
  • Tamper evidence: SHA-256 hash chain + audit-log:verify; pruning keeps a chain anchor so verification stays strict.
  • Signed integrity digests (CloudTrail-style): detect deletion of a whole signed segment or the entire table.
  • GDPR subject reports in one command (audit-log:subject-report, NDJSON / HTML).
  • Recursive secret redaction (passwords, tokens, api keys, including nested JSON) before values reach the database.
  • Access logging (who viewed a record) and change reason (withReason, covered by the hash chain).

Operations

  • Anomaly detection: change burst, mass delete, off-hours, cascade weight (write-amplification), plus detection-as-code custom rules; alerts to Slack, signed webhook or mail, on demand or on a cron.
  • SIEM streaming to Splunk / Datadog / Elastic / generic HTTP — off the request path, queued, fail-soft.
  • Native multi-tenancy: tenant stamped at capture (survives the queue), every read auto-scoped.
  • Retention with archive-before-delete to any disk (S3 included), and an optional dedicated database connection with a transfer-data command.

Governance

  • AuditPolicy per model: ignore() noisy fields, capture when() a condition holds, sample() a fraction of high-churn models.
  • Sampling decided per correlation, so one record's history within a unit of work is kept or dropped together — never left with holes.
  • event_version schema contract on every record (and in the API / SIEM payloads) so consumers can branch on the layout.
  • Fluent query DSL (AuditLog::query()->field('status')->from('pending')->to('paid')->get()) over the same filter path as the array API.

Analytics and performance

  • Indexed changed-keys table: field-level searches seek an index instead of scanning the JSON of every row; audit-log:backfill-changed-keys covers existing rows (chunked, resumable).
  • Correlation analytics: "Top cascades" ranks the heaviest root actions (writes / models / depth), each linking to its trace.
  • Change hotspots: most-changed models and most-changed fields, scoped to the current filters.
  • Deliberate write path: one record insert plus one batched changed-key insert; capture is fail-open and never blocks the host.

Dashboard and developer experience

  • Optional dashboard (audit-log:ui enable): filters, value-transition search, statistics with heatmap, pagination, anomalies, trace, time machine — vendored assets, no CDN.
  • In-app documentation page covering every feature, plus a live facade Playground.
  • Facades for everything the dashboard shows, and an opt-in JSON API for your own admin panels.

Non-goals (permanent boundaries)

No event sourcing or state replay, no backpressure engine, no in-package search engine, no distributed observability platform, no query profiler. Each would force the audit log to become a source of truth or a real-time system, breaking the invariant that makes it safe to install: capture is fail-closed, off your write path, additive, and never changes your data.

Requirements

PHP 8.1 / 8.2 / 8.3, Laravel 9–13. CI: Pint, PHPStan level 8, the unit suite across the PHP matrix, and a 90%+ line-coverage gate.