artisanpack-ui / compliance
Compliance toolkit for Laravel — GDPR / CCPA / LGPD consent management, data subject rights (erasure + portability), DPIA / processing-activity records, data minimization (anonymization + pseudonymization), retention policies, compliance monitoring + reporting.
Requires
- php: ^8.3
- artisanpack-ui/core: ^1.0
- illuminate/support: ^10.0|^11.0|^12.0|^13.0
Requires (Dev)
- artisanpack-ui/ai: ^1.0
- artisanpack-ui/code-style: ^1.1
- artisanpack-ui/code-style-pint: ^1.1
- dealerdirect/phpcodesniffer-composer-installer: ^1.0
- friendsofphp/php-cs-fixer: ^3.75
- laravel/pint: ^1.26
- livewire/livewire: ^3.6
- orchestra/testbench: ^10.2|^11.0
- pestphp/pest: ^3.8|^4.0
- pestphp/pest-plugin-laravel: ^3.2|^4.0
Suggests
- artisanpack-ui/ai: Recommended ^1.0 — enables the high-stakes compliance AI agents (privacy-policy draft, DPIA assistance, consent-text suggestion). Without it the `aiFeatures()` service-provider hook is a no-op and the AI trigger surfaces (Livewire component + REST endpoints) stay hidden.
This package is auto-updated.
Last update: 2026-07-09 20:23:57 UTC
README
Compliance toolkit for Laravel: GDPR / CCPA / LGPD consent management, data subject rights (erasure + portability), DPIA + processing-activity records, data minimization (anonymization + pseudonymization), retention policies, plus compliance monitoring and reporting.
This package is part of the ArtisanPack UI Security 2.0 split — the privacy / compliance features previously bundled inside artisanpack-ui/security 1.x live here in 2.0+.
Features
- Consent management — versioned
ConsentPolicyper purpose, per-userConsentRecordwith status (granted / withdrawn / expired), immutableConsentAuditLog,ConsentManagerservice,CookieConsentHandler,check.consentmiddleware - Data subject rights
- Erasure:
ErasureServiceorchestrating pluggableErasureHandlerInterfaceimplementations, with logged outcomes per handler and exemption tracking - Portability:
PortabilityServicewith pluggableDataExporterInterfaceproviders and downloadable JSON / XML / CSV exports
- Erasure:
- DPIA + processing activities — Article 30
ProcessingActivityrecords, Article 35DataProtectionAssessmentwith risk + mitigation tracking,RiskCalculatorfor inherent + residual scoring - Data minimization —
AnonymizationEngine,PseudonymizationEngine,DataMinimizerService,data.minimizationmiddleware - Retention policies —
RetentionPolicy+CollectionPolicymodels,PurgeExpiredDataconsole command, configurable deletion strategy (delete / anonymize / archive) - Compliance monitoring —
ComplianceMonitorruns pluggableComplianceCheckInterfaceimplementations, persistsComplianceCheckResultrows, raisesComplianceViolationrecords, computesComplianceScoresnapshots - Reporting —
ReportGeneratorwith pluggableReportTypeInterfaceproviders,ScheduledComplianceReportmodel for cron-driven delivery, multi-format output (PDF / HTML / CSV / JSON) - Console commands —
compliance:run-checks,compliance:process-erasure-requests,compliance:process-portability-requests,compliance:purge-expired-data,compliance:generate-report - HTTP controllers —
ConsentController,ErasureController,PortabilityController,ComplianceDashboardController - Events —
ConsentGranted,ConsentWithdrawn,ErasureRequested,ErasureCompleted,DataExportRequested,DataExportCompleted,ComplianceCheckCompleted,ComplianceViolationDetected(auto-logged out of the box)
Installation
composer require artisanpack-ui/compliance
Run the migrations to create the 17 compliance tables:
php artisan migrate
(Optional) Publish the config to override table names, route prefix, deletion strategies, or default formats:
php artisan vendor:publish --tag=compliance-config
Quick start
Record consent
use ArtisanPackUI\Compliance\Compliance\Consent\ConsentManager; $manager = app( ConsentManager::class ); $record = $manager->grant( $user->id, 'analytics', [ 'collection_method' => 'banner', 'ip_address' => request()->ip(), 'user_agent' => request()->userAgent(), ] );
Check consent in a route
Route::post( '/track', [TrackingController::class, 'store'] ) ->middleware( 'check.consent:analytics' );
Process an erasure request
use ArtisanPackUI\Compliance\Models\ErasureRequest; use ArtisanPackUI\Compliance\Compliance\Erasure\ErasureService; use Illuminate\Support\Str; $request = ErasureRequest::create( [ 'request_number' => 'ER-' . (string) Str::ulid(), 'user_id' => $user->id, 'requester_type' => 'self', 'scope' => 'full', 'deadline_at' => now()->addDays( 30 ), ] ); app( ErasureService::class )->process( $request );
Run compliance checks
php artisan compliance:run-checks
The default service provider listeners log every consent / erasure / data-export / check / violation event to your application log, so you get an out-of-the-box audit trail without wiring anything up yourself.
Models
| Model | Table | Purpose |
|---|---|---|
ConsentPolicy |
consent_policies |
Versioned legal text + processing details per purpose |
ConsentRecord |
consent_records |
Per-user consent state with policy reference |
ConsentAuditLog |
consent_audit_logs |
Immutable consent change history |
ProcessingActivity |
processing_activities |
GDPR Art. 30 record of processing activities |
DataProtectionAssessment |
data_protection_assessments |
Art. 35 DPIA |
AssessmentRisk |
assessment_risks |
Single risk within a DPIA |
RiskMitigation |
risk_mitigations |
Mitigation measure against a risk |
ErasureRequest |
erasure_requests |
Art. 17 right-to-be-forgotten request |
ErasureLog |
erasure_logs |
Per-handler audit row for an erasure run |
PortabilityRequest |
portability_requests |
Art. 20 data portability request |
ExportSchema |
export_schemas |
Schema definition for portable exports |
RetentionPolicy |
retention_policies |
Rule for how long a category is retained |
CollectionPolicy |
collection_policies |
Rule for what fields may be collected per purpose |
ComplianceViolation |
compliance_violations |
Violation raised by a check |
ComplianceCheckResult |
compliance_check_results |
Single execution of a check |
ComplianceScore |
compliance_scores |
Aggregate compliance posture snapshot |
ScheduledComplianceReport |
scheduled_compliance_reports |
Cron-driven recurring report |
Extending
The package ships pluggable interfaces so you can add organization-specific behaviour without forking:
ComplianceCheckInterface— define new automated compliance checksErasureHandlerInterface— wipe a custom data store as part of erasureDataExporterInterface— surface a custom data source in portability exportsReportTypeInterface— emit a custom compliance report typeConsentStorageInterface— back consent records with an alternative store
Register implementations in your service provider; the orchestrators discover them via the container.
AI features
The compliance package ships three optional AI trigger surfaces powered by artisanpack-ui/ai. Every one of these is high-stakes — output must be reviewed by qualified legal counsel before it goes anywhere near production.
| Feature key | Agent | Default model | Purpose |
|---|---|---|---|
compliance.privacy_policy_draft |
PrivacyPolicyDraftAgent |
claude-opus-4-7 |
Draft a starter privacy policy from declared processing activities. |
compliance.dpia_assistance |
DpiaAssistanceAgent |
claude-opus-4-7 |
Enumerate risks, mitigations, and stakeholder impacts for a DPIA. |
compliance.consent_text |
ConsentTextSuggestionAgent |
claude-sonnet-4-6 |
Suggest plain-language consent text with reading-level score and jurisdiction notes. |
Non-negotiable guardrails
Every host that surfaces these agents MUST:
- Render an un-dismissable "requires legal review" banner on every draft. The banner is not decorative — every agent output carries
requires_legal_review: trueand areview_checklistarray, and both must be shown to the user before they can view the body. - Gate viewing the draft behind an acknowledgement checkbox. Users cannot see the generated content until they confirm they understand the draft is not legal advice.
- Never overwrite an existing draft. Persist every run as a new
AiDraftrow — the model itself blocks updates via abooted()guard. This preserves the full version history for legal review.
Installing the AI dependency
artisanpack-ui/ai is a soft dependency — the compliance package boots without it, and the AI surfaces stay unregistered. To enable them:
composer require artisanpack-ui/ai
Then set your provider credentials (see the ai package README) and toggle the features in config/artisanpack/ai.php:
'features' => [ 'compliance.privacy_policy_draft' => [ 'enabled' => true ], 'compliance.dpia_assistance' => [ 'enabled' => true ], 'compliance.consent_text' => [ 'enabled' => true ], ],
Triggering an agent from Livewire
<livewire:ap-compliance-ai-tools /> <button wire:click="$dispatch('compliance-ai:suggest-consent-text', { payload: { purpose: 'Send weekly product update emails', data_categories: ['email address', 'engagement metrics'], audience: 'general public', jurisdiction: 'EU', } })" >Suggest consent text</button>
Listen for the result on the browser side:
Livewire.on('compliance-ai:compliance.consent_text:success', ({ output }) => { // Render the "requires legal review" banner first. // Then render the acknowledgement checkbox. // Only reveal `output.consent_text` after the user acknowledges. });
Saving a draft after acknowledgement:
Livewire.dispatch('compliance-ai:save-draft', { featureKey: 'compliance.consent_text', output: agentOutput, subjectKey: 'marketing-email-consent', metadata: { acknowledged: true, reviewer: 'jane@acme.example' }, });
The Livewire component rejects any save where metadata.acknowledged is not true.
Triggering from React or Vue
Hit the REST endpoints directly — they are mounted at /api/v1/compliance/ai/* and gated by auth:sanctum:
| Endpoint | Method | Purpose |
|---|---|---|
/api/v1/compliance/ai/features |
GET | Feature-toggle state map. |
/api/v1/compliance/ai/privacy-policy-draft |
POST | Run PrivacyPolicyDraftAgent. |
/api/v1/compliance/ai/dpia-assistance |
POST | Run DpiaAssistanceAgent. |
/api/v1/compliance/ai/consent-text |
POST | Run ConsentTextSuggestionAgent. |
Every response follows the shape { feature: string, output: object } on success or { feature: string, error: string, message: string } on failure. Error codes: feature_disabled (403), missing_credentials (503), invalid_input (422), internal_error (500).
Documentation
Requirements
- PHP 8.3+
- Laravel 10 / 11 / 12 / 13
Sibling packages
| Package | Scope |
|---|---|
artisanpack-ui/security-full |
Meta-package — pulls in the full security suite (all seven packages below) in a single require |
artisanpack-ui/security |
Core: input sanitization, output escaping, KSES, CSP, security headers |
artisanpack-ui/rbac |
Roles, permissions, hierarchy, Blade directives, Gate integration |
artisanpack-ui/security-auth |
2FA, password complexity, account lockout, sessions |
artisanpack-ui/security-advanced-auth |
WebAuthn, SSO, social login, biometric, device fingerprinting |
artisanpack-ui/secure-uploads |
File validation, malware scanning, signed-URL serving |
artisanpack-ui/security-analytics |
Event logging, anomaly detection, SIEM, dashboards |
License
MIT — see LICENSE.
Contributing
As an open-source project, this package is open to contributions from anyone. Please read through the contributing guidelines to learn more about how you can contribute to this project.