@@ -35,6 +35,7 @@ The package uses a high-performance direct logging architecture with optional qu
3535- [ Performance Optimization] ( #performance-optimization )
3636- [ Testing] ( #testing )
3737- [ Security Best Practices] ( #security-best-practices )
38+ - [ Audit Log Retention] ( #audit-log-retention )
3839- [ Migration & Upgrade Guide] ( #migration--upgrade-guide )
3940- [ Troubleshooting] ( #troubleshooting )
4041- [ Contributing] ( #contributing )
@@ -54,6 +55,7 @@ The package uses a high-performance direct logging architecture with optional qu
5455- ** Enhanced Query Scopes** : Comprehensive filtering capabilities with dedicated scopes for different query patterns.
5556- ** Extensible Drivers** : Supports multiple storage drivers (currently MySQL) with the ability to implement custom drivers.
5657- ** Automatic Migration** : Seamlessly creates audit tables for new models when enabled.
58+ - ** Smart Retention System** : Comprehensive retention policies with delete, anonymize, and archive strategies for compliance and performance.
5759- ** Static Analysis** : Level 5 PHPStan compliance for maximum code quality and reliability.
5860
5961## Requirements
@@ -137,13 +139,29 @@ return [
137139 'resolver' => null, // custom resolver class
138140 ],
139141
142+ // Retention configuration for automatic cleanup
143+ 'retention' => [
144+ 'enabled' => env('AUDIT_RETENTION_ENABLED', false),
145+ 'days' => env('AUDIT_RETENTION_DAYS', 365),
146+ 'strategy' => env('AUDIT_RETENTION_STRATEGY', 'delete'), // 'delete', 'archive', 'anonymize'
147+ 'batch_size' => env('AUDIT_RETENTION_BATCH_SIZE', 1000),
148+ 'anonymize_after_days' => env('AUDIT_ANONYMIZE_DAYS', 180),
149+ 'archive_connection' => env('AUDIT_ARCHIVE_CONNECTION', null),
150+ 'run_cleanup_automatically' => env('AUDIT_AUTO_CLEANUP', false),
151+ ],
152+
140153 // Registered entities for centralized configuration
141154 'entities' => [
142155 // Example entity configuration:
143156 // \App\Models\User::class => [
144157 // 'table' => 'users',
145158 // 'exclude' => ['password'],
146159 // 'include' => ['*'],
160+ // 'retention' => [
161+ // 'days' => 730,
162+ // 'strategy' => 'anonymize',
163+ // 'anonymize_after_days' => 365,
164+ // ],
147165 // ],
148166 ],
149167];
@@ -168,6 +186,15 @@ AUDIT_QUEUE_DELAY=0
168186
169187# Migration Configuration
170188AUDIT_AUTO_MIGRATION=true
189+
190+ # Retention Configuration
191+ AUDIT_RETENTION_ENABLED=false
192+ AUDIT_RETENTION_DAYS=365
193+ AUDIT_RETENTION_STRATEGY=delete
194+ AUDIT_RETENTION_BATCH_SIZE=1000
195+ AUDIT_ANONYMIZE_DAYS=180
196+ AUDIT_ARCHIVE_CONNECTION=null
197+ AUDIT_AUTO_CLEANUP=false
171198```
172199
173200### Database Schema
@@ -186,12 +213,14 @@ CREATE TABLE audit_{model_name}_logs (
186213 metadata JSON NULL ,
187214 source VARCHAR (255 ) NULL ,
188215 created_at TIMESTAMP NOT NULL ,
216+ anonymized_at TIMESTAMP NULL ,
189217
190218 INDEX idx_entity_id (entity_id),
191219 INDEX idx_causer (causer_type, causer_id),
192220 INDEX idx_created_at (created_at),
193221 INDEX idx_source (source),
194- INDEX idx_action (action)
222+ INDEX idx_action (action),
223+ INDEX idx_anonymized_at (anonymized_at)
195224);
196225```
197226
@@ -897,6 +926,252 @@ final class AuditLogPolicy
897926}
898927```
899928
929+ ## Audit Log Retention
930+
931+ The Laravel Audit Logger package includes a powerful retention system that helps you manage the lifecycle of your audit logs. This system supports automatic cleanup, anonymization, and archiving of old audit data to help with compliance requirements and database performance.
932+
933+ ### Features
934+
935+ - ** Multiple Retention Strategies** : Delete, anonymize, or archive old audit logs
936+ - ** Per-Model Configuration** : Override global settings for specific models
937+ - ** Batch Processing** : Efficient processing of large datasets
938+ - ** Smart Anonymization** : Automatically detect and anonymize sensitive fields
939+ - ** Flexible Scheduling** : Run manually or via scheduled jobs
940+ - ** Dry Run Mode** : Preview changes before execution
941+
942+ ### Configuration
943+
944+ #### Global Configuration
945+
946+ Configure retention settings in your ` config/audit-logger.php ` :
947+
948+ ``` php
949+ 'retention' => [
950+ 'enabled' => env('AUDIT_RETENTION_ENABLED', false),
951+ 'days' => env('AUDIT_RETENTION_DAYS', 365),
952+ 'strategy' => env('AUDIT_RETENTION_STRATEGY', 'delete'), // 'delete', 'archive', 'anonymize'
953+ 'batch_size' => env('AUDIT_RETENTION_BATCH_SIZE', 1000),
954+ 'anonymize_after_days' => env('AUDIT_ANONYMIZE_DAYS', 180),
955+ 'archive_connection' => env('AUDIT_ARCHIVE_CONNECTION', null),
956+ 'run_cleanup_automatically' => env('AUDIT_AUTO_CLEANUP', false),
957+ ],
958+ ```
959+
960+ #### Environment Variables
961+
962+ ``` env
963+ AUDIT_RETENTION_ENABLED=true
964+ AUDIT_RETENTION_DAYS=365
965+ AUDIT_RETENTION_STRATEGY=delete
966+ AUDIT_RETENTION_BATCH_SIZE=1000
967+ AUDIT_ANONYMIZE_DAYS=180
968+ AUDIT_ARCHIVE_CONNECTION=archive_db
969+ AUDIT_AUTO_CLEANUP=false
970+ ```
971+
972+ #### Per-Entity Configuration
973+
974+ Configure retention settings for specific entities:
975+
976+ ``` php
977+ 'entities' => [
978+ \App\Models\User::class => [
979+ 'table' => 'users',
980+ 'retention' => [
981+ 'enabled' => true,
982+ 'days' => 730, // Keep for 2 years
983+ 'strategy' => 'anonymize',
984+ 'anonymize_after_days' => 365, // Anonymize after 1 year
985+ ],
986+ ],
987+ \App\Models\Order::class => [
988+ 'table' => 'orders',
989+ 'retention' => [
990+ 'days' => 2555, // Keep for 7 years (compliance)
991+ 'strategy' => 'archive',
992+ ],
993+ ],
994+ ],
995+ ```
996+
997+ #### Per-Model Configuration
998+
999+ Configure retention directly in your model:
1000+
1001+ ``` php
1002+ <?php
1003+
1004+ declare(strict_types=1);
1005+
1006+ namespace App\Models;
1007+
1008+ use Illuminate\Database\Eloquent\Model;
1009+ use iamfarhad\LaravelAuditLog\Traits\Auditable;
1010+
1011+ final class User extends Model
1012+ {
1013+ use Auditable;
1014+
1015+ // Per-model retention configuration
1016+ protected array $auditRetention = [
1017+ 'enabled' => true,
1018+ 'days' => 730,
1019+ 'strategy' => 'anonymize',
1020+ 'anonymize_after_days' => 365,
1021+ ];
1022+ }
1023+ ```
1024+
1025+ ### Retention Strategies
1026+
1027+ #### 1. Delete Strategy
1028+
1029+ Permanently removes old audit logs from the database.
1030+
1031+ ``` php
1032+ 'strategy' => 'delete',
1033+ 'days' => 365, // Delete records older than 1 year
1034+ ```
1035+
1036+ ** Use Case** : When you want to minimize storage usage and don't need historical data beyond a certain period.
1037+
1038+ #### 2. Anonymize Strategy
1039+
1040+ Replaces sensitive information with anonymized values while keeping the audit structure intact.
1041+
1042+ ``` php
1043+ 'strategy' => 'anonymize',
1044+ 'days' => 180, // Anonymize records older than 6 months
1045+ ```
1046+
1047+ ** Anonymized Fields** : email, phone, address, ip_address, user_agent, name, first_name, last_name, full_name
1048+
1049+ ** Use Case** : Compliance requirements where you need to maintain audit trail structure but remove personally identifiable information.
1050+
1051+ #### 3. Archive Strategy
1052+
1053+ Moves old audit logs to a separate database connection for long-term storage.
1054+
1055+ ``` php
1056+ 'strategy' => 'archive',
1057+ 'days' => 365, // Archive records older than 1 year
1058+ 'archive_connection' => 'archive_db',
1059+ ```
1060+
1061+ ** Use Case** : Long-term compliance requirements where you need to maintain historical data but keep the primary database lean.
1062+
1063+ #### 4. Combined Strategy
1064+
1065+ You can combine anonymization with deletion or archiving:
1066+
1067+ ``` php
1068+ 'strategy' => 'delete', // or 'archive'
1069+ 'days' => 730, // Final action after 2 years
1070+ 'anonymize_after_days' => 365, // Anonymize after 1 year
1071+ ```
1072+
1073+ ### Usage
1074+
1075+ #### Manual Execution
1076+
1077+ ``` bash
1078+ # Run cleanup for all entities
1079+ php artisan audit:cleanup --force
1080+
1081+ # Run cleanup for specific entity
1082+ php artisan audit:cleanup --entity=" App\Models\User" --force
1083+
1084+ # Dry run to see what would be processed
1085+ php artisan audit:cleanup --dry-run
1086+
1087+ # Process specific number of records
1088+ php artisan audit:cleanup --limit=1000 --force
1089+ ```
1090+
1091+ #### Queue Processing
1092+
1093+ ``` php
1094+ use iamfarhad\LaravelAuditLog\Jobs\RetentionCleanupJob;
1095+
1096+ // Dispatch cleanup job for all entities
1097+ RetentionCleanupJob::dispatch();
1098+
1099+ // Dispatch cleanup job for specific entity
1100+ RetentionCleanupJob::dispatch('App\Models\User');
1101+ ```
1102+
1103+ #### Scheduled Execution
1104+
1105+ Add to your ` app/Console/Kernel.php ` :
1106+
1107+ ``` php
1108+ protected function schedule(Schedule $schedule): void
1109+ {
1110+ // Run retention cleanup weekly
1111+ $schedule->command('audit:cleanup --force')
1112+ ->weekly()
1113+ ->environments(['production']);
1114+
1115+ // Or run for specific entities
1116+ $schedule->command('audit:cleanup --entity="App\Models\User" --force')
1117+ ->daily()
1118+ ->at('02:00');
1119+ }
1120+ ```
1121+
1122+ #### Service Usage
1123+
1124+ ``` php
1125+ <?php
1126+
1127+ declare(strict_types=1);
1128+
1129+ use iamfarhad\LaravelAuditLog\Contracts\RetentionServiceInterface;
1130+ use iamfarhad\LaravelAuditLog\DTOs\RetentionConfig;
1131+
1132+ final class AuditMaintenanceService
1133+ {
1134+ public function __construct(
1135+ private readonly RetentionServiceInterface $retentionService
1136+ ) {}
1137+
1138+ public function cleanupUserAudits(): void
1139+ {
1140+ $config = new RetentionConfig(
1141+ enabled: true,
1142+ days: 365,
1143+ strategy: 'anonymize',
1144+ batchSize: 1000,
1145+ anonymizeAfterDays: 180
1146+ );
1147+
1148+ $result = $this->retentionService->processRetention(
1149+ entityClass: 'App\Models\User',
1150+ config: $config,
1151+ dryRun: false
1152+ );
1153+
1154+ // Handle results...
1155+ }
1156+ }
1157+ ```
1158+
1159+ ### Best Practices
1160+
1161+ 1 . ** Start with Dry Runs** : Always test your retention policies with ` --dry-run ` before applying
1162+ 2 . ** Monitor Performance** : Use appropriate batch sizes for your database performance
1163+ 3 . ** Backup Strategy** : Ensure you have backups before running retention operations
1164+ 4 . ** Compliance Review** : Review your retention policies with legal/compliance teams
1165+ 5 . ** Gradual Implementation** : Start with longer retention periods and adjust based on requirements
1166+ 6 . ** Queue Processing** : Use queued processing for large datasets to avoid timeouts
1167+
1168+ ### Security Considerations
1169+
1170+ - ** Access Control** : Ensure only authorized users can execute retention commands
1171+ - ** Audit the Audit** : Consider logging retention operations themselves
1172+ - ** Data Recovery** : Have procedures for data recovery in case of mistakes
1173+ - ** Anonymization Verification** : Test that anonymized data meets your privacy requirements
1174+
9001175## Migration & Upgrade Guide
9011176
9021177### Upgrading from Version 1.2.x to 1.3.x
0 commit comments