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:
2026-03-25 21:12:49 +01:00
parent 12a837bda9
commit 0c351f6aff
176 changed files with 2157 additions and 834 deletions

View File

@@ -1,6 +1,6 @@
# Notifications Modul (V1)
Letzte Aktualisierung: 2026-03-19
Letzte Aktualisierung: 2026-03-25
## Ziel
@@ -45,6 +45,41 @@ Kanonische Quelle: `modules/notifications/module.php`
5. `NotificationRepository` persistiert in `user_notifications`.
6. Bell-Endpunkte lesen tenant-scoped Daten und aktualisieren den Session-`unread_count`.
## Producer-Contract (fuer Core + andere Module)
Stabile Erzeugung erfolgt ueber:
- `MintyPHP\Module\Notifications\Service\NotificationMessage`
- `MintyPHP\Module\Notifications\Service\NotificationService::createFromMessage(...)`
- `NotificationService::createForTenantUsersFromMessage(...)`
- `NotificationService::createForTenantAdminUsersFromMessage(...)`
Beispiel (locale-neutral, mit i18n-Key):
```php
use MintyPHP\Module\Notifications\Service\NotificationMessage;
use MintyPHP\Module\Notifications\Service\NotificationService;
$message = NotificationMessage::localized(
'user.created',
'New user: %s',
[$displayName],
null,
[],
'admin/users/edit/' . $uuid,
['user_id' => $userId, 'uuid' => $uuid]
);
$notificationService->createForTenantAdminUsersFromMessage(
$tenantId,
$message,
$actorUserId,
$allowedAdminSet
);
```
Plain/Fallback-Erzeugung bleibt moeglich mit `NotificationMessage::plain(...)`.
## Datenvertrag Notification
Persistierter Kernvertrag:
@@ -55,6 +90,16 @@ Persistierter Kernvertrag:
- `link` (nullable string)
- `data` (nullable JSON)
Erweiterung fuer locale-neutrale Texte:
- `data.__message.title_key` (string)
- `data.__message.title_params` (array)
- `data.__message.body_key` (string, optional)
- `data.__message.body_params` (array, optional)
Wenn `__message` vorhanden ist, wird der Anzeigetext beim Lesen in der aktuellen
Empfaenger-Locale gerendert (Fallback auf persistiertes `title`/`body` bleibt erhalten).
Dedupe-Metadaten (intern):
- `dedupe_fingerprint`
@@ -112,4 +157,3 @@ Dedupe-Metadaten (intern):
2. Actor fuehrt User-Aktion aus.
3. Zweiter Admin sieht Bell-Badge + Listeneintrag.
4. Wiederholung innerhalb 30 Minuten erzeugt kein Duplikat.