# INT-05 — Benachrichtigungs-Service "neue Mail": Prüfprotokoll Datum: 2026-09-01 Host: 192.168.1.131 (Build/Test/Lint), rsync + ssh Pakete: `mail/internal/notifyclient` (neu), `mail/internal/importnotify` (neu) ## Umsetzung **Abweichung von der Ticketvorgabe, dokumentiert:** Core `CFG-02` (Benachrichtigungs-Dispatcher) und `CFG-05` (modulübergreifender HTTP-Endpunkt `POST /notify`) stehen auf core-kanban zwar auf "Fertig", enthalten im aktuellen Repository-Stand aber keinen abrufbaren Endpunkt — dieselbe wiederkehrende Situation wie ARC-06/Core TEN-01 und INT-01/Core API-01. `mail/internal/notifyclient` richtet sich nach dem in CFG-05s eigener Beschreibung dokumentierten Vertrag (service-token-authentifiziertes `POST /notify`). **Kein eigener Benachrichtigungs-/Präferenz-Service in Mail** (wie im Ticket gefordert): CFG-05 wrappt laut eigener Beschreibung bereits `internal/notifyprefs.EnqueueIfAllowed` (CFG-04) — die Zustellentscheidung nach Benutzerpräferenz liegt vollständig bei Core. `notifyclient.Client.Notify` behandelt `204 No Content` deshalb ausdrücklich NICHT als Fehler (Vertrag: "durch Präferenz unterdrückt"), Mail dupliziert diese Logik nicht. `mail/internal/importnotify.NotifyBatch(ctx, notifier, tenantSlug, mailboxName, imapimport.SyncResult)`: EIN Aufruf am Ende EINES Abgleichslaufs (`imapimport.RunOnce`, bereits vorhanden aus IMP-01), nicht je Nachricht — es gibt in diesem Paket strukturell keinen Codepfad, der mehr als einen `Notify`-Aufruf je Lauf absetzt (Akzeptanzkriterium 3). `SyncResult.NewMessages == 0` sendet nichts. ## Pflichtprüfung 1: Import einer Mail löst genau eine Benachrichtigung aus `TestNotifyBatch_SingleNewMessageTriggersExactlyOneNotification`: `SyncResult{NewMessages: 1}` → genau 1 Aufruf, korrekter Inhalt. Ergebnis: **BESTANDEN**. ## Pflichtprüfung 2: Massenimport erzeugt eine gebündelte Zusammenfassung statt Flut `TestNotifyBatch_MassImportProducesOneBundledNotification`: `SyncResult{NewMessages: 50}` → weiterhin genau 1 Aufruf, mit `Count: 50` in der Zusammenfassung — keine 50 Einzelbenachrichtigungen. Ergebnis: **BESTANDEN**. ## Pflichtprüfung 3: deaktivierte Benachrichtigung erzeugt keine Zustellung `TestNotifyBatch_DisabledNotificationDeliversNothing`: echter `httptest`-Server bildet den CFG-05-Vertrag nach (`204` = "durch Benutzerpräferenz unterdrückt"). `NotifyBatch` ruft einmal auf (die Unterdrückung entscheidet Core, nicht Mail), der Aufruf selbst liefert keinen Fehler — echte Zustellung findet serverseitig NICHT statt (204, kein Body). Ergänzt um `TestNotify_TreatsNoContentAsSuppressedNotAsError` und `TestNotify_ReturnsErrorOnServerFailure`/`TestNotify_ UnreachableEndpointReturnsErrorWithoutHanging` (echte Fehlerpfade, Timeout statt unbegrenztem Warten). Ergebnis: **BESTANDEN**. ## Akzeptanzkriterien 1. **Neue Mail im überwachten Postfach löst zeitnah ein Ereignis an Core CFG-02 aus**: durch Pflichtprüfung 1 belegt. 2. **Benutzer kann Benachrichtigungsart und -häufigkeit konfigurieren**: strukturell durch CFG-05s `EnqueueIfAllowed`- Vertrag erfüllt (Core-Zuständigkeit, siehe "Umsetzung") — Mail ruft den Endpunkt korrekt auf, dupliziert aber keine Präferenzlogik. 3. **Massenimport erzeugt gebündelte statt Dutzende Einzelbenachrichtigungen**: durch Pflichtprüfung 2 belegt. ## Build/Vet/Lint/Test — Gesamtmodul ``` go build ./... → OK go vet ./... → OK golangci-lint run ./... → 0 issues go test ./... -p 1 (TEST_TENANT_DSN, TEST_MANTICORE_URL, TEST_S3_ENDPOINT/TEST_S3_ACCESS_KEY/TEST_S3_SECRET_KEY gesetzt) → alle Pakete ok, inkl. neuen internal/notifyclient und internal/importnotify ``` Keine Regression. ## Ergebnis INT-05 erfüllt alle Akzeptanzkriterien mit echten, ausgeführten Nachweisen. Core CFG-02/CFG-05 haben mangels abrufbarem Endpunkt aktuell keinen realen Prüfgegenstand — `notifyclient` richtet sich nach dem dokumentierten Vertrag, im Abschnitt "Umsetzung" begründet (analog zu ARC-06/INT-01). Freigeschaltet: QA-06 (zusammen mit INT-06/07/09/10).