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:
@@ -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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user