Files
breadcrumb-the-shire/docs/reference-notifications-module.md

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.created
    • user.deleted
    • user.activated
    • user.deactivated
    • user.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.
  • ui_slots
    • topbar.right_item: Bell-Template
    • layout.head_style: Modul-CSS fuer Topbar + Dropdown
    • runtime.component: Bell-JS (initNotificationBell)
  • permissions
    • notifications.view
  • authorization_policies
    • NotificationsAuthorizationPolicy
  • layout_context_providers
    • liefert notifications.nav.unread_count in den Layout-Context
  • session_providers
    • synchronisiert module.notifications.unread_count aus DB

Event -> Notification Fluss

  1. Ein User-Lifecycle-Workflow dispatcht ein Domain-Event (z. B. user.activated).
  2. Der in module.php registrierte Listener verarbeitet das Payload.
  3. Listener ruft NotificationService auf.
  4. NotificationService orchestriert Empfaenger/Fan-out und Dedupe-Metadaten.
  5. NotificationRepository persistiert in user_notifications.
  6. 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_fingerprint
  • dedupe_bucket
  • dedupe_until

Guardrails (Server)

  • Alle Bell-Endpunkte erzwingen:
    • Login
    • Ability notifications.view
  • POST-Endpunkte (mark-read, delete) pruefen CSRF.
  • Tenant-Scope wird serverseitig aus current_tenant erzwungen.
  • 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 ueber data-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

  1. Zwei Admins im selben Tenant, einer als Actor.
  2. Actor fuehrt User-Aktion aus.
  3. Zweiter Admin sieht Bell-Badge + Listeneintrag.
  4. Wiederholung innerhalb 30 Minuten erzeugt kein Duplikat.