cboxdk/laravel-audit-chain
Cbox Audit Chain
A tamper-evident, hash-chained audit trail for Laravel.
Every entry carries the SHA-256 of its own content and of the entry before it, so any later change, deletion in the middle, or reordering is detectable. Ed25519-signed checkpoints catch what a chain alone cannot (entries deleted off the end), and an anchor exports each checkpoint to storage your database's writers cannot reach.
use Cbox\AuditChain\Contracts\AuditChain;
use Cbox\AuditChain\ValueObjects\ChainActor;
use Cbox\AuditChain\ValueObjects\ChainEvent;
use Cbox\AuditChain\ValueObjects\ChainKey;
$chain = app(AuditChain::class);
$key = ChainKey::of($tenant->id, 'billing');
$chain->record($key, ChainEvent::by(ChainActor::of('user', $user->id), 'invoice.voided')->on('invoice', $invoice->id));
$chain->verify($key)->valid; // false if anything recorded was changed, removed or reordered
$chain->checkpoint($key); // sign the head, so truncation becomes detectable too
What you get
- Independent chains addressed by
ChainKey(partition, scope): one per tenant, per ledger, per whatever you need. - Safe concurrent appends. Parallel writers to one chain never lose an entry or share a position. Proven with eight forked writers on PostgreSQL 16, MySQL 8.4 and MariaDB 11.8.
- Signed checkpoints (Ed25519 via ext-sodium) with key rotation, and an idempotent
audit-chain:checkpointsweep. - Anchoring to any Laravel disk, including S3 and Cloudflare R2.
audit-chain:verifyfor full or windowed verification, with a non-zero exit on any break.- Contracts for everything: bring your own codec, signer, anchor, tenant context or models, including adopting a chain another implementation wrote without rewriting it.
- Least privilege: run the app as a role that can only SELECT and INSERT, with
append-only triggers behind it.
audit-chain:grantsprints the exact SQL per engine, and the setup is tested on PostgreSQL, MySQL and MariaDB. - A test fake (
FakeAuditChain,InteractsWithAuditChain) with assertions.
Honest scope
This is tamper-evident, not tamper-proof: someone who can rewrite the whole table can recompute every hash. Only checkpoints exported to a store they cannot write stop that. And the chain proves integrity, not completeness: it cannot know about an event nobody recorded. See Guarantees and limits.
Requirements
PHP 8.4+, ext-sodium, Laravel 12 or 13. See Requirements.
Installation
composer require cboxdk/laravel-audit-chain
php artisan vendor:publish --tag=audit-chain-config
php artisan vendor:publish --tag=audit-chain-migrations
php artisan migrate
php artisan audit-chain:keygen
Then read the Quickstart.
Documentation
- Overview and Quickstart
- Getting started: installation, testing
- Core concepts: architecture, hash format, checkpoints, concurrency, guarantees
- Cookbook: anchor to R2, adopt an existing chain, rotate keys, scheduling
- Extension points
- Configuration
- Security
Quality gate
vendor/bin/pint --test
vendor/bin/phpstan analyse --no-progress --memory-limit=1G # level max, no baseline
vendor/bin/pest
composer audit --no-dev
composer license-check
composer sbom && git diff --exit-code sbom.json
Security
Report vulnerabilities privately through GitHub Private Vulnerability Reporting. See SECURITY.md.
License
MIT. See LICENSE.
Related Packages
Universal change history and audit log for Laravel. Tracks who changed what and...
A Tailwind CSS powered UI for the Spatie/laravel-activitylog package that we all...
Structured audit logs for Laravel with actors, targets, and request metadata.
A security-first audit control center for Filament v4 and v5 with tenant isolati...
The only Laravel audit package that ships a complete admin UI — Livewire table,...
Version History
| Version | Released | PHP | Laravel | License |
|---|---|---|---|---|
| v0.1.0 | ^8.4 | ^12.0 | | MIT |