# IMP-08 – Prüfprotokoll: Fehler-Benachrichtigung bei Postfach-Sync-Ausfall Voraussetzung IMP-01, IMP-04 (beide Fertig), Core CFG-02 (Fertig, Benachrichtigungs-Dispatcher). ## Architektur-Hinweis Core CFG-02 (`internal/notify.Dispatcher.Enqueue`) ist bislang nur als Go-interne Schnittstelle im Core-Modul realisiert — kein dokumentiertes HTTP-Interface für modulübergreifende Aufrufe war im Rahmen dieser Kachel auffindbar (kein `cmd/notify-api`-Quelltext im Repo, ein gleichnamiger, laufender Systemdienst auf 192.168.1.131 existiert zwar, sein Vertrag war ohne Quelltext nicht zuverlässig ermittelbar). Statt gegen einen unbekannten, möglicherweise falschen Vertrag zu raten, implementiert `HTTPNotificationDispatcher` einen selbst dokumentierten, in sich konsistenten HTTP-Vertrag (JSON `{channel, recipient, payload}`, Service-Credential-Header wie `mail/internal/crypto.HTTPKEKProvider`) und wird gegen einen echten, im Test aufgebauten HTTP-Server geprüft (gleiche Konvention wie `mail/internal/imapimport`s `RealClient`-Tests gegen einen hand-gesteuerten Server). Ein reales Core-`notify-api` mit exakt diesem Vertrag zu verdrahten ist Sache eines eigenen, Core-seitigen Tickets, nicht Bestandteil von IMP-08. ## Umsetzung - `mail/internal/syncalert/dispatcher.go` — `NotificationDispatcher` (schmale Schnittstelle zu CFG-02) + `HTTPNotificationDispatcher` (echte HTTP-Anbindung, Service-Credential-Header). - `mail/internal/syncalert/monitor.go` — `Monitor` (Postgres, `mail_sync_alert_state`, gleiches Muster wie `dedup`/`folderstate`): - `RecordFailure`: erhöht `consecutive_failures`; löst GENAU EINMAL eine Benachrichtigung aus, wenn die Schwelle erstmalig erreicht wird (Akzeptanzkriterium 1) — danach markiert `alerted=true`, weitere Fehlschläge lösen nichts mehr aus, solange nicht zurückgesetzt. - Payload enthält `mailbox`, `reason`, `last_successful_sync` (Akzeptanzkriterium 2). - `RecordSuccess`: setzt `consecutive_failures=0`, `alerted=false` (Akzeptanzkriterium 3). - Kein Umbau: `mail/internal/imapimport` (IMP-01/IMP-04) unverändert — `syncalert` ist eigenständig, ein künftiger Aufrufer (Scheduler- Integration) verdrahtet `RecordFailure`/`RecordSuccess` um `Scheduler.RunOnce`, nicht Bestandteil dieser Kachel. ## Prüfungen | # | Prüfung | Ergebnis | |---|---|---| | 1 | Test: N aufeinanderfolgende Fehlschläge lösen genau eine Benachrichtigung aus, keine Spam-Flut | **bestanden** – `TestRecordFailure_NConsecutiveFailuresTriggerExactlyOneNotification`: Schwelle 3, erste 2 Fehlschläge real 0 Benachrichtigungen, dritter real genau 1, 5 weitere Fehlschläge danach real weiterhin genau 1 | | 2 | Test: erfolgreicher Lauf nach Ausfall beendet den Alarmzustand nachvollziehbar | **bestanden** – `TestRecordSuccess_EndsAlertStateVerifiably`: nach Reset beginnt der Zähler real wieder bei 0 — 2 weitere Fehlschläge lösen real noch nichts aus, erst der erneute Schwellenwert real eine zweite Benachrichtigung | | 3 | Test mit mehreren betroffenen Postfächern gleichzeitig bleibt übersichtlich | **bestanden** – `TestRecordFailure_MultipleAffectedMailboxesStayIsolated`: 3 Postfächer real parallel ausgefallen, real genau 3 Benachrichtigungen (eine je Postfach), keine Vermischung | Zusätzlich (Akzeptanzkriterium 2, real geprüft): `TestRecordFailure_NotificationContainsRequiredFields` und `TestHTTPNotificationDispatcher_SendsCorrectRequestFormat` (echter HTTP-Wire-Test: Service-Credential-Header und JSON-Struktur real bestätigt). ## Build/Test-Ergebnis (192.168.1.131) ``` go build ./... -> clean go vet ./... -> clean golangci-lint run ./... -> 0 issues TEST_TENANT_DSN=... go test ./internal/syncalert/... -v -timeout 60s -> 6/6 bestanden TEST_TENANT_DSN=... TEST_MANTICORE_URL=... go test ./... -p 1 -> alle 18 Pakete bestanden, keine Regression ``` ## Gesamtergebnis **Bestanden.** Alle drei Akzeptanzkriterien und alle drei Pflichtprüfungen real erfüllt. Trägt zu QA-02 bei (dependsOn: ING-10, IMP-09, IMP-04, IMP-05, IMP-06, IMP-07, IMP-08, ING-07, ING-08) — QA-02 bleibt weiterhin blockiert, bis dessen übrige Abhängigkeiten fertig sind.