mohammed94 / compliance-export
Turn your Laravel audit logs into signed, PII-redacted, regulator-ready compliance reports (GDPR DSAR, SOC 2, HIPAA) — tamper-evident via a hash chain.
Requires
- php: ^8.2
- illuminate/console: ^10.0|^11.0|^12.0
- illuminate/contracts: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0|^10.0
- pestphp/pest: ^2.0|^3.0
This package is auto-updated.
Last update: 2026-06-22 15:55:38 UTC
README
Turn your Laravel audit logs into signed, PII-redacted, regulator-ready compliance reports — GDPR DSARs, SOC 2 evidence, HIPAA exports — that an auditor can prove were never tampered with.
Every serious app logs activity. But when a regulator or auditor comes knocking — "give this EU user all their data" (GDPR), "prove who accessed this record" (SOC 2 / HIPAA) — there's a painful gap between a raw activity_log row and a signed, redacted, regulation-shaped document. Teams either build it by hand every time or pay Drata / Vanta.
Compliance Export closes that gap in one call: it pulls a subject's audit trail from your existing sources, redacts the PII, and seals the result with a tamper-evident hash chain + signature.
Features
- 🧾 Regulator-ready exports — one report per data subject, as JSON or CSV (GDPR DSAR style)
- 🛡️ Tamper-evident — a SHA-256 hash chain sealed with an HMAC signature;
verify()fails if a single record changed - 🙈 PII redaction engine — declarative, field-based rules (
email,partial,hash,mask,redact) - 🔌 Source adapters, zero hard deps — reads from spatie/laravel-activitylog and mohammed94/ai-ledger when present, or any array/custom
Source - 🧰 Artisan command —
php artisan compliance:export user:123 --regulation=gdpr
Installation
composer require mohammed94/compliance-export php artisan vendor:publish --tag=compliance-export-config
Set a stable signing key in .env:
COMPLIANCE_SIGNING_KEY=base64:your-long-random-secret
Usage
Generate a report
use Mohammed94\ComplianceExport\Facades\Compliance; $report = Compliance::for(subject: 'user:123', regulation: 'gdpr') ->from($source) // a Source, or a raw array of records ->generate(); $report->toJson(); // manifest + redacted records + cryptographic proof $report->toCsv(); // DSAR-friendly spreadsheet $report->save(storage_path('app/compliance/user-123.json'));
Prove it wasn't tampered with
Compliance::verify($report); // true — recomputes the hash chain + signature // change any record after the fact → verify() returns false
From the command line
php artisan compliance:export user:123 --regulation=gdpr --source=activitylog --format=csv
Redaction
PII is redacted by configurable, field-name rules (see config/compliance-export.php):
'rules' => [ 'email' => 'email', // john.doe@x.com → j***@x.com 'phone' => 'partial', // +9647701234567 → **********4567 'national_id' => 'hash', // → sha256:1f3a... 'password' => 'redact', // → [REDACTED] ],
Add one-off rules per export with ->redact(['notes' => 'mask']).
How the proof works
Records are folded into a SHA-256 hash chain (each hash includes the previous one), then the manifest + chain are signed with HMAC-SHA256 using your secret key. The signature is embedded in the report. Re-running verify() recomputes everything from the records present — so adding, removing or editing any record breaks the seal. An auditor can trust the export reflects exactly what was issued.
Roadmap
-
#[Redact]PHP attributes on Eloquent models - SOC 2 (JSON-LD) and HIPAA (FHIR) formatters
- Control-attestation table (which control was active, who approved access)
- Livewire dashboard for previewing & issuing exports
- Asymmetric (Ed25519) signatures for third-party verification
Testing
composer test
License
The MIT License (MIT). See LICENSE.