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.
8.8 KiB
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):
- Physische Tenant-Trennung fehlt – Storage ist logisch (DB) getrennt, nicht auf Dateisystem- Ebene (Punkt 15, bekannt seit Tenant-Isolation-Review).
- Zeitstempel/Signaturerhalt (BSI TR 03125) – nicht implementiert (Nice-to-have, niedrige Priorität, nur relevant bei signierten Mails im Kundenkreis).
- 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. 6–10 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)
- Physische Tenant-Trennung (Punkt 15) evaluieren, falls von Kunden gefordert
(siehe Memory
project_tenant_isolation_review.md). - Nice-to-have: BSI TR 03125 Zeitstempel/Signaturerhalt (Punkt 12), nur bei konkretem Bedarf.
- 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).