# RET-07 – Prüfprotokoll: Fristablauf-Benachrichtigungen Voraussetzung RET-02, CFG-05 – beide bereits Fertig. ## Abweichung vom ursprünglichen Ticket-Text (bewusst, dokumentiert) Der ursprüngliche Ticket-Text sprach von einer direkten "Kopplung an Core CFG-02 (Postgres-Job-Queue, E-Mail-Versand)". Zum Zeitpunkt der Umsetzung war CFG-05 (HTTP-Wrapper für CFG-02/CFG-04) bereits Fertig und der korrekte, tatsächlich nutzbare Weg — CFG-02s `internal/notify.Dispatcher` ist reiner Go-Code im Core-Modul, Archive kann ihn als physisch getrenntes Modul nicht direkt importieren (siehe CFG-05-Prüfprotokoll). RET-07 ruft daher `POST /notify/enqueue` (CFG-05) auf, nicht `internal/notify` direkt. Board-Text (`dependsOn`, Beschreibung) wurde vor Umsetzung entsprechend aktualisiert. **Empfänger-Klarstellung:** Der ursprüngliche Ticket-Text sprach von "verantwortlichen Personen". `retention_objects` (RET-01) führt bewusst KEINE Objekt-Owner-Beziehung. Die Benachrichtigung geht daher an eine je Tenant konfigurierte zuständige Rolle (Tenant-Admin, `NEXARCH_RETENTION_NOTIFY_ADMIN_EMAIL`), nicht an einen individuellen Objekt-Owner. Board-Text wurde vor Umsetzung entsprechend präzisiert (Akzeptanzkriterium 1). ## Umsetzung - `archive/migrations/0006_retention_notify.up/down.sql` – `retention_class_rules.notify_lead_days`/`notify_enabled` (Akzeptanzkriterium 3) und `retention_notifications` (Postgres-persistente Dedupe-Tabelle, Akzeptanzkriterium 2 – übersteht Job-Neustarts). - `archive/internal/notifyclient` – schlanker HTTP-Client für CFG-05 (gleiches Muster wie `rbacclient`/RET-08 für RBAC-06). - `archive/internal/retentionnotify.Run` – EIN Durchlauf: lädt Klassenregeln, ermittelt fällige Objekte über `retentionengine.ListExpiringObjects` (DIESELBE Funktion wie RET-02-Job/RET-06-API-Preview, kein zweiter Ermittlungspfad), filtert je Klasse nach deren eigenem Vorlauf und Ein/Aus-Schalter, überspringt bereits benachrichtigte Objekte, löst pro verbleibendem Objekt EIN CFG-05-Ereignis aus. Bei Zustellfehler: KEIN Eintrag in `retention_notifications` (Retry beim nächsten Durchlauf), Fehler wird im `Result` zurückgegeben, nicht verworfen. - `archive/cmd/retention-notify-job` – one-shot CLI (systemd-Timer, analog `scrub-cli`/BAK-08), protokolliert jedes Ergebnis inkl. Fehler über `log.Printf`. - `deploy/systemd/nexarch-archive-retention-notify.{service,timer}.tmpl`. ## Prüfungen | # | Prüfung | Ergebnis | |---|---|---| | 1 | Testfrist mit kurzem Vorlauf löst genau eine Benachrichtigung aus | **bestanden** – `TestRun_ShortLeadTimeTriggersExactlyOneNotification`: fake-CFG-05-Server zählt Aufrufe, genau 1; real auf 131: Testobjekt mit 1-Tage-Frist/1-Tage-Vorlauf, Job manuell gestartet, `journalctl` zeigt genau eine Benachrichtigung mit echter `job_id`, echte Zeile in Core-`notification_jobs` (Status `pending`) bestätigt | | 2 | Deaktivierte Benachrichtigung verschickt nachweislich nichts | **bestanden** – `TestRun_DisabledNotificationSendsNothing`: `notify_enabled=false`, 0 Ergebnisse, 0 CFG-05-Aufrufe (Zähler geprüft, nicht nur "kein Fehler") | | 3 | Fehlgeschlagener Versand wird protokolliert und nicht stillschweigend verworfen | **bestanden** – `TestRun_FailedDeliveryIsReportedNotSwallowed`: fake-CFG-05-Server liefert 500, `Result.Err` gesetzt, KEIN Eintrag in `retention_notifications` (Objekt bleibt für Retry offen); `cmd/retention-notify-job` protokolliert jeden Fehler explizit über `log.Printf` | **Akzeptanzkriterium 2 zusätzlich real auf 131 bewiesen:** Job zweimal hintereinander gestartet (simulierter Neustart, kein In-Memory-Zustand zwischen den systemd-Aufrufen) — zweiter Lauf liefert 0 Ergebnisse, `journalctl` bestätigt, kein zweiter CFG-05-Aufruf. ## Echte Verdrahtung auf 192.168.1.131 - Migration `0006_retention_notify` real auf `dms_tenant_test` angewendet. - `retention-notify-job` gebaut nach `/opt/nexarch-archive/bin/`, `/etc/nexarch/archive-retention-notify.env` (0600). - `nexarch-archive-retention-notify.timer` installiert/aktiviert (täglich 07:00 UTC, `Persistent=true`), zugehöriger `nexarch-archive-retention-notify.service` (`Type=oneshot`). - Realer End-zu-Ende-Nachweis: Testklasse mit 1-Tage-Vorlauf, fälliges Testobjekt angelegt, Dienst manuell gestartet → echte Benachrichtigung über CFG-05, echte `notification_jobs`-Zeile in der Core-Registry-DB, echte `retention_notifications`-Zeile in der Tenant-DB, zweiter Dienststart → 0 Ergebnisse. Alle Testdaten anschließend entfernt. ## Build/Test-Ergebnis (192.168.1.131) ``` go build ./... -> clean go vet ./... -> clean golangci-lint run ./... -> 0 issues go test ./... -p 1 -> alle Archive-Pakete bestanden (inkl. retentionnotify, objectbackup, restoretest) ``` ## Gesamtergebnis **Bestanden.** Alle drei Akzeptanzkriterien und alle drei Pflichtprüfungen real erfüllt, inklusive echtem systemd-Timer-Deploy und End-zu-Ende-Nachweis über zwei physisch getrennte Module (Archive → CFG-05 → Core-Queue) sowie eines simulierten Job-Neustarts ohne Doppelversand.