refactor(audit): extract audit domain into self-contained module
Move the entire audit subsystem (system audit, API audit, import audit, user lifecycle audit, frontend telemetry) from core into modules/audit/. Core decoupling via interface-based injection: - AuditRecorderInterface replaces SystemAuditService in 10+ core services - UserLifecycleAuditInterface / ImportAuditInterface for specialized flows - NullAuditRecorder fallback when audit module is disabled - ApiBootstrap/ApiResponse use null-safe callable resolvers Module structure (modules/audit/): - Manifest with routes, permissions, scheduler jobs, authorization policy - 9 services, 8 repositories, 6 domain enums, 4 job handlers - 33 page files, 4 JS files, 8 test files, migration scripts, i18n Core cleanup: - OperationsAuthorizationPolicy, UiCapabilityMap, PermissionService surgically cleaned of audit-specific constants - Sidebar template cleared of hardcoded audit navigation - AuditModuleIsolationContractTest ensures no future core→module coupling All quality gates pass: 1346 tests (19,276 assertions), PHPStan level 5 clean, architecture contracts verified. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,7 @@ use MintyPHP\Http\SessionStoreInterface;
|
||||
use MintyPHP\Repository\User\UserReadRepositoryInterface;
|
||||
use MintyPHP\Repository\User\UserWriteRepositoryInterface;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
use MintyPHP\Service\Audit\SystemAuditService;
|
||||
use MintyPHP\Service\Audit\AuditRecorderInterface;
|
||||
use MintyPHP\Service\Auth\AuthService;
|
||||
use MintyPHP\Service\Auth\AuthSessionTenantContextService;
|
||||
use MintyPHP\Service\Auth\EmailVerificationService;
|
||||
@@ -265,7 +265,7 @@ class AuthServiceTest extends TestCase
|
||||
$tenantCtxService = $this->createMock(AuthSessionTenantContextService::class);
|
||||
$tenantCtxService->expects($this->once())->method('hydrateForUser')->with(5);
|
||||
|
||||
$audit = $this->createMock(SystemAuditService::class);
|
||||
$audit = $this->createMock(AuditRecorderInterface::class);
|
||||
$audit->expects($this->once())->method('record')
|
||||
->with('auth.login.success', 'success', $this->anything());
|
||||
|
||||
@@ -301,7 +301,7 @@ class AuthServiceTest extends TestCase
|
||||
return $default;
|
||||
});
|
||||
|
||||
$audit = $this->createMock(SystemAuditService::class);
|
||||
$audit = $this->createMock(AuditRecorderInterface::class);
|
||||
$audit->expects($this->once())->method('record')
|
||||
->with('auth.login.failed', 'failed', $this->anything());
|
||||
|
||||
@@ -360,7 +360,7 @@ class AuthServiceTest extends TestCase
|
||||
'email_verified_at' => null,
|
||||
]);
|
||||
|
||||
$audit = $this->createMock(SystemAuditService::class);
|
||||
$audit = $this->createMock(AuditRecorderInterface::class);
|
||||
$audit->expects($this->once())->method('record')
|
||||
->with('auth.login.failed', 'failed', $this->callback(function (array $ctx): bool {
|
||||
return ($ctx['error_code'] ?? '') === 'email_not_verified';
|
||||
@@ -398,7 +398,7 @@ class AuthServiceTest extends TestCase
|
||||
$rememberMeService = $this->createMock(RememberMeService::class);
|
||||
$rememberMeService->expects($this->never())->method('forgetCurrentUser');
|
||||
|
||||
$audit = $this->createMock(SystemAuditService::class);
|
||||
$audit = $this->createMock(AuditRecorderInterface::class);
|
||||
$audit->expects($this->once())->method('record')
|
||||
->with('auth.session.timeout', 'success', $this->callback(function (array $context): bool {
|
||||
return (int) ($context['actor_user_id'] ?? 0) === 5
|
||||
@@ -432,7 +432,7 @@ class AuthServiceTest extends TestCase
|
||||
['current_tenant', [], ['id' => 11]],
|
||||
]);
|
||||
|
||||
$audit = $this->createMock(SystemAuditService::class);
|
||||
$audit = $this->createMock(AuditRecorderInterface::class);
|
||||
$audit->expects($this->once())->method('record')
|
||||
->with('auth.logout', 'success', $this->callback(function (array $context): bool {
|
||||
return (int) ($context['actor_user_id'] ?? 0) === 5
|
||||
@@ -462,7 +462,7 @@ class AuthServiceTest extends TestCase
|
||||
?PermissionService $permissionService = null,
|
||||
?TenantSsoService $tenantSsoService = null,
|
||||
?AuthSessionTenantContextService $authSessionTenantContextService = null,
|
||||
?SystemAuditService $systemAuditService = null,
|
||||
?AuditRecorderInterface $systemAuditService = null,
|
||||
?SessionStoreInterface $sessionStore = null
|
||||
): AuthService {
|
||||
return new AuthService(
|
||||
@@ -475,7 +475,7 @@ class AuthServiceTest extends TestCase
|
||||
$permissionService ?? $this->createMock(PermissionService::class),
|
||||
$tenantSsoService ?? $this->createMock(TenantSsoService::class),
|
||||
$authSessionTenantContextService ?? $this->createMock(AuthSessionTenantContextService::class),
|
||||
$systemAuditService ?? $this->createMock(SystemAuditService::class),
|
||||
$systemAuditService ?? $this->createMock(AuditRecorderInterface::class),
|
||||
$sessionStore ?? $this->createMock(SessionStoreInterface::class)
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user