Files
archivmail/docs/GOBD_DSGVO_CHECKLIST.md
T
sysops 17633cb86c docs: Migrations-Runbook für Compliance-Erhalt-Check ergänzen (GoBD Punkt 10)
Baseline/Post-Vergleich, PROJ-18-Integritätscheck, Manticore-Konsistenz,
PROJ-52-Reconciliation und Byte-Vergleich als Ablauf nach jeder Schema-/
Index-/Tenant-Migration. Checklist-Punkt 10 auf Erfüllt gesetzt.
2026-07-04 12:14:30 +02:00

57 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# GoBD/DSGVO-Compliance-Checkliste archivmail
Bewertung gegen den "Leitfaden zur E-Mail-Archivierung in Deutschland" (VOI-Grundsätze, GoBD, DSGVO).
Stand: 2026-07-04, basierend auf Code-Review (nicht nur Spec-Review).
## Zusammenfassung
**Gut abgedeckt:** Verschlüsselung at-rest (AES-256-GCM) mit Pflicht-Warnung (PROJ-49), Volltextsuche
(Manticore), unveränderliches Audit-Log per DB-Trigger + append-only JSON-Lines (PROJ-48),
Retention/Löschsperre inkl. Dokumentenart-Kategorien (PROJ-34, PROJ-51), DSGVO-Löschersuchen-Workflow
mit GoBD-Vorrang (PROJ-50), Vollständigkeits-Reconciliation (PROJ-52), Multi-Tenant-Rollenmodell,
Integritätsprüfung per SHA-256 (PROJ-18), Export in EML/MBOX/ZIP/CSV (PROJ-12, PROJ-15, PROJ-39, PROJ-47).
**Verbleibende Lücken (priorisiert):**
1. **Physische Tenant-Trennung fehlt** Storage ist logisch (DB) getrennt, nicht auf Dateisystem-
Ebene (Punkt 15, bekannt seit Tenant-Isolation-Review).
2. **Zeitstempel/Signaturerhalt (BSI TR 03125)** nicht implementiert (Nice-to-have, niedrige
Priorität, nur relevant bei signierten Mails im Kundenkreis).
3. **Informationspflicht der Mitarbeiter** organisatorisch, nicht im Code lösbar (Punkt 13).
---
## Checkliste
| # | Anforderung | Status | Begründung / Codeverweis | Empfehlung |
|---|---|---|---|---|
| 1 | **Vollständigkeit** 100% Ein-/Ausgang archiviert | ✅ Erfüllt | SMTP-BCC-Journal (PROJ-4), IMAP/POP3-Import (PROJ-3/14), EML/MBOX-Import (PROJ-2). SMTP-Daemon (`internal/smtpd/smtpd.go`) gibt bei Storage-Fehler `452` zurück → MTA-Retry, kein Verlust beim Empfang. Vollständigkeits-Reconciliation (PROJ-52, deployt 2026-07-04): täglicher Cron-Report `internal/reconciliation/` zählt archivierte Mails je Quelle, Alert bei >50% Abweichung vom 7-Tage-Schnitt, Audit-Eintrag `reconciliation_anomaly`. | |
| 2 | **Frühzeitigkeit** Archivierung bei Eingang/Ausgang | ✅ Erfüllt | SMTP-BCC-Journaling (PROJ-4) archiviert synchron beim Empfang/Versand; IMAP-Cron-Sync (PROJ-8) ergänzt. `internal/storage/storage.go:343 Save()` läuft direkt im Empfangspfad. | |
| 3 | **Unveränderbarkeit / Formaterhalt** | ✅ Erfüllt | `Save()` speichert Original-RFC2822-Bytes (ggf. gzip-komprimiert, PROJ-36) ohne inhaltliche Konvertierung; `Load()`/`maybeDecompress()` liefert Original zurück. Export liefert EML 1:1 (PROJ-12, `internal/api/export.go`). Kein Schreibzugriff/UPDATE auf gespeicherte Mail-Dateien im Code gefunden. | |
| 4 | **Zugriffsschutz** | ✅ Erfüllt | JWT-Auth (httpOnly Cookie), bcrypt Cost 12 (PROJ-1). Rollenmodell `user`/`auditor`/`admin` strikt getrennt; `admin` hat explizit KEINEN Mail-Zugriff. Tenant-Isolation via `tenantAccessAllowed()` (`internal/api/import_handlers.go:22`). | |
| 5 | **Wiederauffindbarkeit / Volltextsuche** | ✅ Erfüllt | Manticore-RT-Index (PROJ-30), Volltextsuche inkl. Anhänge via OCR (PROJ-35/44), Filter nach Datum/Absender/etc. (PROJ-6). | |
| 6 | **Aufbewahrungsfristen (konfigurierbar je Dokumentenart, i.d.R. 610 Jahre)** | ✅ Erfüllt | PROJ-51 (deployt 2026-06-13): Tabelle `archiving_rules` (`internal/storage/retention_rules.go`) — Muster-Regeln (Absender/Betreff/etc.) mit individueller `retention_days` pro Dokumentenart, Priorität bei mehreren Treffern, `retain_until_source` dokumentiert welche Regel griff. `Store.minRetentionDays`/`SetMinRetentionDays` erzwingt konfigurierbares Minimum. Admin-UI unter `/api/admin/archiving-rules`. | |
| 7 | **Löschsperre** | ✅ Erfüllt | PROJ-34 implementiert: `emails.retain_until`, `ErrRetentionLock` (`internal/storage/storage.go:27,659-667`), `Delete()` verweigert Löschung vor Fristablauf. Zusätzlich Cron-Purge (PROJ-56c, `cmd/archivmail/cmd_purge.go`, nachts 03:40 via `/etc/cron.d/archivmail`): löscht NUR Mails die BEIDE Bedingungen erfüllen — `retain_until < NOW()` UND vom Nutzer explizit `marked_for_deletion=TRUE` gesetzt (`ListExpiredMarkedMailIDs`, `internal/storage/mark_deletion.go:127-148`). Reiner Fristablauf ohne manuelle Markierung löscht nichts automatisch (Vier-Augen-Prinzip: Frist + Mensch). Der manuelle Admin-Button (`Store.Purge()`, `POST /api/admin/purge`) löscht dagegen alles abgelaufene ohne Markierungspflicht — bewusst getrennte, absichtlich unterschiedliche Semantik für Cron vs. manuelle Aktion. | |
| 8 | **Protokollierung/Audit-Log unveränderlich** | ✅ Erfüllt | PROJ-48 (deployt 2026-06-13): `internal/audit/audit.go` installiert Funktion `audit_log_no_mutation()` + Trigger `audit_log_immutable` (blockt UPDATE/DELETE auf DB-Ebene, idempotent via `CREATE OR REPLACE`/`DROP TRIGGER IF EXISTS`). Zusätzlich append-only JSON-Lines-Datei (`ResolvedLogPath()`, Default `/var/log/archivmail/audit.log`), Schreibfehler blockieren den DB-Pfad nicht (best effort, DB bleibt Quelle der Wahrheit). | |
| 9 | **Nachprüfbarkeit durch Dritte / GDPdU-Export** | ✅ Erfüllt | Export-Funktionen: Einzel-EML/PDF, ZIP-Massenexport mit `manifest.csv` (PROJ-12, `internal/api/export.go`), eDiscovery-ZIP mit `metadata.csv` + README (PROJ-39, `internal/api/ediscovery.go`), CLI-Export inkl. Tenant-Voll-Export (PROJ-15, PROJ-47, `cmd/archivmail/cmd_export.go`), Audit-Log-CSV-Export für Auditoren. | Optional: PROJ-47 (In Review) fertigstellen/QA. |
| 10 | **Migrationssicherheit** | ✅ Erfüllt | Migrationstools vorhanden (PROJ-19 Mailpiler-Import, PROJ-30 Xapian→Manticore), `initSchema`/idempotente `ALTER TABLE ... ADD COLUMN IF NOT EXISTS` Pattern durchgängig genutzt (z.B. `storage.go:99-100`). Compliance-Erhalt-Check jetzt dokumentiert: `docs/MIGRATION_RUNBOOK.md` (Zählvergleich Baseline/Post, PROJ-18-Integritätscheck-Log, Manticore-Konsistenz, PROJ-52-Reconciliation, Byte-Vergleich per Export). | |
| 11 | **Maschinelle Auswertbarkeit (Standardformate)** | ✅ Erfüllt | Export als EML (Original-MIME, PROJ-12/15), MBOX (`cmd_export.go`), CSV-Metadaten (PROJ-39). | |
| 12 | **Zeitstempel/Signaturerhalt (BSI TR 03125)** | ❌ Fehlt | Keine S/MIME- oder PGP-Signaturprüfung, kein qualifizierter Zeitstempel-Dienst im Code gefunden. Für die meisten KMU nicht zwingend erforderlich. | Als Backlog-Item vermerken, nur bei Bedarf (signierte Mails im Kundenkreis) als neue Spec aufnehmen. |
| 13 | **Informationspflicht der Mitarbeiter** | ❌ Fehlt (organisatorisch) | Nicht im Code prüfbar/lösbar. | Organisatorische Maßnahme: Betriebsvereinbarung / Datenschutzhinweis außerhalb des Systems. |
| 14 | **Trennung/Kennzeichnung personenbezogener Daten, Löschkonflikt Art. 5/17/32** | ✅ Erfüllt | PROJ-50 (deployt 2026-06-13): `internal/storage/dsgvo_requests.go` — Tabelle `dsgvo_requests`, Workflow sucht betroffene Mails (From/To/CC, Volltext via Manticore `AnyAddress`), löscht NUR Mails ohne aktive Löschsperre (`store.Delete` respektiert `retain_until`), lehnt den Rest mit Begründung "Aufbewahrungspflicht hat Vorrang" ab und protokolliert (`EventDSGVORequest`). Bekannte Deviation: `bcc_addr` ist im Schema vorhanden, aber `mailparser` befüllt BCC nicht (kein BCC-Header in archivierten Mails) — Such-Vollständigkeitszusage entsprechend einschränken. | Deviation (BCC) in Kunden-Doku erwähnen, sonst keine Aktion nötig. |
| 15 | **Mandantentrennung/Zugriffskontrolle nach Rolle (Multi-Tenant)** | ✅ Erfüllt | PROJ-21 Multi-Tenancy, `tenantAccessAllowed()` als Standardmuster (`internal/api/import_handlers.go:22`), Tenant-Quotas (PROJ-29), Pro-Tenant-Retention (`tenants.retention_days`). Laut Memory: keine physische Storage-Trennung pro Tenant (logische Trennung über `email_refs`/DB). | Bekannte Lücke (siehe Memory `project_tenant_isolation_review.md`): physische Storage-Trennung als optionales Härtungsfeature evaluieren, falls von Kunden gefordert. |
| 16 | **Verschlüsselung at-rest** | ✅ Erfüllt | PROJ-49 (deployt 2026-06-13): AES-256-GCM (`internal/storage/storage.go`, `encrypt()`), inkl. gzip vor Verschlüsselung (PROJ-36). `Store.EncryptionEnabled()` + `warnEncryptionStatus()` gibt beim Start eine WARN-Zeile aus wenn Keyfile fehlt/unlesbar/falsche Größe; `archivmail status` prüft `checkEncryption`; Dashboard (`handleSystemStats`) zeigt `encryption.enabled` systemweit. `Keyfile` bleibt technisch optional (Abwärtskompatibilität bestehender Installationen), aber Zustand ist jetzt sichtbar statt stillschweigend. | |
---
## Nächste Schritte (Vorschlag, Priorität absteigend)
1. **Physische Tenant-Trennung** (Punkt 15) evaluieren, falls von Kunden gefordert
(siehe Memory `project_tenant_isolation_review.md`).
2. Nice-to-have: BSI TR 03125 Zeitstempel/Signaturerhalt (Punkt 12), nur bei konkretem Bedarf.
3. Organisatorisch: Mitarbeiter-Informationspflicht (Punkt 13) außerhalb des Codes klären.
**Erledigt seit Stand 2026-06-13:** PROJ-48 (Audit-Log-Unveränderbarkeit), PROJ-49
(Verschlüsselungspflicht/Warnung), PROJ-50 (DSGVO-Löschersuchen), PROJ-51 (Retention-Kategorien),
PROJ-52 (Vollständigkeits-Reconciliation), PROJ-47 (Tenant-Voll-Export, jetzt Deployed).