# Benachrichtigungen Das Modul `apps/backend/src/notifications` stellt persoenliche In-App- Benachrichtigungen bereit. Es gibt bewusst keinen E-Mail-Versand, keine Push Notifications, keine WebSockets, keine Server-Sent Events, keine Queue, kein Redis und keine Hintergrundjobs. Neue Benachrichtigungen werden beim Laden der Anwendung und per Frontend-Polling abgerufen. ## Datenmodell Die Entity `NotificationEntity` wird in der Tabelle `notifications` gespeichert. Jede Benachrichtigung gehoert genau einem Benutzer. Felder: - `id`: UUID - `userId`: Foreign Key auf `users.id` - `type`: technischer Typ aus `NotificationType` - `title`: kurzer Plain-Text-Titel, maximal 150 Zeichen - `message`: Plain-Text-Nachricht, maximal 1000 Zeichen - `link`: optionale interne Angular-Route, maximal 500 Zeichen - `metadata`: optionale JSON-Metadaten, maximal 4096 Bytes serialisiert - `readAt`: `null`, solange ungelesen - `createdAt`: UTC-Erstellungszeit - `deletedAt`: Soft Delete Indizes: - `user_id, created_at` - `user_id, read_at` - `user_id, deleted_at` Die Migration liegt unter `apps/backend/src/database/migrations/1720000001000-AddNotifications.ts` und wird nicht automatisch beim App-Start ausgefuehrt. ## Typen Benachrichtigungstypen sind Code, keine Datenbankdaten: - `system` - `item.created` - `item.updated` - `user.role-changed` Neue Module erweitern `apps/backend/src/notifications/notification-types.ts` und nutzen anschliessend `NotificationsService`. ## Permissions - `notifications.readOwn`: eigene Benachrichtigungen lesen - `notifications.updateOwn`: eigene Benachrichtigungen markieren oder loeschen - `notifications.manage`: administrativ Benachrichtigungen erzeugen Die Systemrolle `user` erhaelt `notifications.readOwn` und `notifications.updateOwn`. Die Rolle `admin` erhaelt ueber `allPermissions` zusaetzlich `notifications.manage`. ## API Alle Endpunkte liegen unter dem bestehenden API-Praefix `/api`. - `GET /notifications`: eigene Benachrichtigungen, mit `page`, `pageSize` und `status=all|read|unread` - `GET /notifications/unread-count`: Anzahl ungelesener eigener Benachrichtigungen - `PATCH /notifications/:id/read`: idempotent als gelesen markieren - `PATCH /notifications/:id/unread`: idempotent als ungelesen markieren - `PATCH /notifications/read-all`: alle eigenen Benachrichtigungen als gelesen markieren - `DELETE /notifications/:id`: Soft Delete einer eigenen Benachrichtigung - `POST /admin/notifications`: administrative Erzeugung mit `notifications.manage` Normale Benutzer koennen keine fremde `userId` uebergeben. Der aktuelle Benutzer wird serverseitig aus der Session bestimmt. ## Interner Service Andere Backend-Module erzeugen Benachrichtigungen ueber `NotificationsService`, nicht direkt ueber ein Repository: ```ts await notifications.createForUser({ userId, type: NotificationType.ItemCreated, title: 'Neuer Eintrag', message: 'Der Eintrag "Beispiel" wurde erstellt.', link: '/items/123', metadata: { itemId: '123' }, }); ``` Verfuegbare Methoden: - `createForUser` - `createForUsers` - `getForCurrentUser` - `getUnreadCount` - `markAsRead` - `markAsUnread` - `markAllAsRead` - `softDelete` `createForUsers` begrenzt Bulk-Erzeugung auf 100 Zielbenutzer. ## Integrationen `ItemsService` benachrichtigt beim Erstellen eines Items den ersten aktiven Administrator, sofern dieser nicht der Ersteller ist. Das ist eine bewusst kleine Beispielregel und keine vollstaendige fachliche Eskalationslogik. `UsersService` benachrichtigt betroffene Benutzer nach erfolgreicher Rollenaenderung. Fehler beim Erzeugen werden geloggt; die bereits erfolgreiche sicherheitsrelevante Rollenaenderung wird dadurch nicht unkontrolliert zurueckgerollt. Administrative Erzeugung wird im Audit-Log als `NOTIFICATION_CREATED` protokolliert. Geloggt werden Actor, Zielbenutzer, Notification-ID, Typ und Request-ID, nicht die vollstaendige Nachricht oder Metadata. ## Frontend `NotificationStore` verwendet Angular Signals fuer lokalen State und RxJS fuer HTTP und Polling. Header-Panel und Seite `/notifications` verwenden denselben Store, damit keine doppelten Requests fuer dieselben Daten entstehen. Polling: - Standardintervall: 60 Sekunden ueber `NOTIFICATION_POLL_INTERVAL_MS` - nur bei angemeldetem Benutzer - pausiert bei unsichtbarem Tab - aktualisiert sofort beim Sichtbarwerden - verhindert ueberlappende Count-Requests - stoppt und leert State beim Logout Links werden im Frontend nur navigiert, wenn sie interne relative Routen sind. Titel und Nachricht werden normal interpoliert und nicht per `innerHTML` gerendert. ## Spaetere Echtzeitkommunikation Wenn spaeter echte Echtzeitkommunikation noetig wird, sollte das als separate Architekturentscheidung erfolgen. Dann waeren Transport, Skalierung, Authentifizierung, Backpressure und Betrieb gemeinsam zu entscheiden, statt WebSockets oder Queues nebenbei in das In-App-Modul einzubauen.