3.6 KiB
3.6 KiB
Notifications Modul (V1)
Letzte Aktualisierung: 2026-03-19
Ziel
Referenz fuer das Modul notifications: Event-Registrierung, Erzeugungsregeln, Guardrails, Frontend-Vertrag und Testbarkeit.
Scope v1
- In-App Notifications (Bell + Dropdown), kein E-Mail-Channel.
- Core-5 Eventtypen:
user.createduser.deleteduser.activateduser.deactivateduser.assignment_changed
- Dedupe fuer diese Typen mit 30 Minuten Fenster.
Modul-Verkabelung
Kanonische Quelle: modules/notifications/module.php
event_listeners- mappt Eventtyp -> Listenerklasse + Methode
handle.
- mappt Eventtyp -> Listenerklasse + Methode
ui_slotstopbar.right_item: Bell-Templatelayout.head_style: Modul-CSS fuer Topbar + Dropdownruntime.component: Bell-JS (initNotificationBell)
permissionsnotifications.view
authorization_policiesNotificationsAuthorizationPolicy
layout_context_providers- liefert
notifications.nav.unread_countin den Layout-Context
- liefert
session_providers- synchronisiert
module.notifications.unread_countaus DB
- synchronisiert
Event -> Notification Fluss
- Ein User-Lifecycle-Workflow dispatcht ein Domain-Event (z. B.
user.activated). - Der in
module.phpregistrierte Listener verarbeitet das Payload. - Listener ruft
NotificationServiceauf. NotificationServiceorchestriert Empfaenger/Fan-out und Dedupe-Metadaten.NotificationRepositorypersistiert inuser_notifications.- Bell-Endpunkte lesen tenant-scoped Daten und aktualisieren den Session-
unread_count.
Datenvertrag Notification
Persistierter Kernvertrag:
type(string)title(string)body(nullable string)link(nullable string)data(nullable JSON)
Dedupe-Metadaten (intern):
dedupe_fingerprintdedupe_bucketdedupe_until
Guardrails (Server)
- Alle Bell-Endpunkte erzwingen:
- Login
- Ability
notifications.view
- POST-Endpunkte (
mark-read,delete) pruefen CSRF. - Tenant-Scope wird serverseitig aus
current_tenanterzwungen. - SQL ausschliesslich im Repository (
NotificationRepository), Service nur Orchestrierung.
Guardrails (Frontend)
- Endpunkte werden mit App-Base-URL gebaut (kein harter Root-Pfad).
- Fehlerpfade laufen ueber zentrale Telemetrie (
warn_once). - A11y-Klickzeilen im Dropdown sind lokal gestylt, damit globale
[role="button"]Regeln nicht durchschlagen. - Default-
details/summary-Chevron wird pro Komponente ueberdata-summary-chevron="none"deaktiviert.
Template/Partial Best Practice
- Core-Partials immer ueber
templatePath('partials/...')einbinden. - Keine fragilen relativen Tiefenpfade auf Core-Templates verwenden.
- Modulinterne Templates bleiben lokal relativ zum Modul.
CSS Token Best Practice (Module)
- Modul-CSS soll auf Core-Variablen aufsetzen (z. B.
--app-color,--app-muted-color,--app-dropdown-*,--app-action-danger-*). - Modul-spezifische Aliase sind ok (
--app-notification-*), solange sie auf Core-Tokens mappen. - Harte Hex-Fallbacks nur als Ausnahme; Standard ist tokenbasiert.
Tests
Unit
- Listener-Tests fuer alle Core-5 Typen:
- Empfaengerregeln
- Actor-Exclusion
- ungultige/leere Payloads
- Service-Tests fuer Dedupe (created vs suppressed)
- Policy-Tests fuer
notifications.view
Integration/Flow
- End-to-End fuer create/delete/activate/deactivate/assignment-change.
- Bell-Endpunkte mit Tenant-Scope und Permission-Pruefung.
- Bulk-Flows dispatchen konsistent.
Manueller Smoke
- Zwei Admins im selben Tenant, einer als Actor.
- Actor fuehrt User-Aktion aus.
- Zweiter Admin sieht Bell-Badge + Listeneintrag.
- Wiederholung innerhalb 30 Minuten erzeugt kein Duplikat.