From 2a61864e7549bf7aa660b696600e572d082770f4 Mon Sep 17 00:00:00 2001 From: Joachim Hummel Date: Fri, 17 Apr 2026 17:51:55 +0000 Subject: [PATCH] =?UTF-8?q?docs:=20ADR=20f=C3=BCr=20recipientEmail=20in=20?= =?UTF-8?q?BullMQ-Jobs=20(Finding=202=20=E2=80=94=20Redis-PII)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- docs/decisions/2026-04-17-redis-pii.md | 32 ++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 docs/decisions/2026-04-17-redis-pii.md diff --git a/docs/decisions/2026-04-17-redis-pii.md b/docs/decisions/2026-04-17-redis-pii.md new file mode 100644 index 0000000..da1f256 --- /dev/null +++ b/docs/decisions/2026-04-17-redis-pii.md @@ -0,0 +1,32 @@ +# ADR: recipientEmail in BullMQ-Jobs + +**Datum:** 2026-04-17 +**Status:** Akzeptiert + +## Kontext + +BullMQ-Jobs im `email-send`-Queue enthalten `recipientEmail` im Klartext. SMTP benötigt die Klartext-E-Mail-Adresse als Empfängeradresse — ohne sie kann keine E-Mail zugestellt werden. + +## Entscheidung + +`recipientEmail` verbleibt im Klartext in den Job-Daten. Redis läuft ausschließlich intern (kein öffentlicher Port, Docker-internes Netzwerk, Hetzner DE). + +Risikominimierung durch bestehende Maßnahmen: +- `removeOnComplete: 100` — abgeschlossene Jobs werden nach 100 Einträgen bereinigt +- `removeOnFail: { count: 500 }` — fehlgeschlagene Jobs werden begrenzt +- `recipientHash` (SHA256) wird für alle Analytics-Events genutzt — kein Klartext in ClickHouse + +## Abgelehnete Alternativen + +**E-Mail-Adresse zur Laufzeit aus DB laden:** Worker enthält nur `subscriberId`, lädt E-Mail aus PostgreSQL. Nachteil: zusätzliche DB-Abfrage pro Job, komplexerer Fehlerfall bei DB-Ausfall während des Versands. + +**Redis Encryption-at-rest:** Technisch möglich (Redis 7 + verschlüsselte RDB-Snapshots). Infra-Aufgabe, nicht im Anwendungscode lösbar. + +## Akzeptiertes Risiko + +Bei einem Redis-Dump-Leak wären E-Mail-Adressen sichtbar. Wahrscheinlichkeit gering (internes Netz, kein öffentlicher Zugriff). + +## Offene Maßnahmen + +- Infra-Ticket erstellen: Redis-Encryption-at-rest auf Hetzner konfigurieren +- Redis-Port darf nie in `docker-compose.yml` nach außen exponiert werden