Files
archivmail/docs/GOBD_DSGVO_CHECKLIST.md
T
sysopsandClaude Sonnet 5 af16138687 docs: README aktualisieren, Dev-Log/Dateiindex/GoBD-Checklist/Screenshots ins Repo
README: Feature-Tabelle und Inhaltsverzeichnis auf aktuellen Stand gebracht
(POP3, OCR, eDiscovery, DSGVO, Retention, LDAP, TOTP, IMAP-Server,
Prometheus, Tenant-Export etc. ergänzt).

Zusätzlich aufgenommen: CODEBASE.md (Dateiindex, Stand 2026-03-31 — vor
PROJ-44 eingefroren, sollte bei Gelegenheit aktualisiert werden), DEVLOG.md
(Session-Log), docs/GOBD_DSGVO_CHECKLIST.md (Compliance-Checkliste),
resume (Session-Notiz), screenshots/.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 23:45:59 +02:00

65 lines
9.2 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-06-13, basierend auf Code-Review (nicht nur Spec-Review).
## Zusammenfassung
**Gut abgedeckt:** Verschlüsselung at-rest (AES-256-GCM), Volltextsuche (Manticore), Audit-Log
in PostgreSQL mit Filterung/Export, Retention/Löschsperre (PROJ-34), 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).
**Top-Lücken (priorisiert):**
1. **Audit-Log ist NICHT unveränderbar** kein DB-Trigger/Constraint gegen UPDATE/DELETE auf
`audit_log`, und die in PROJ-11 spezifizierte append-only Flat-File (`/var/log/archivmail/audit.log`,
JSON Lines) existiert im Code nicht. Das ist ein Kernpunkt von VOI-Grundsatz 8 (Protokollierung)
und wird bei einer Prüfung als erstes angeschaut.
2. **Verschlüsselung ist optional/deaktivierbar** `Keyfile` kann leer bleiben → kein "at rest"-Schutz
garantiert, kein erzwungenes Minimum.
3. **Keine Kennzeichnung/Klassifikation personenbezogener Daten** kein `contains_personal_data`
o.ä. Flag im Mail-Datenmodell; DSGVO-Löschkonflikt (Art. 17 vs. GoBD-Aufbewahrung) ist nirgends
im Code dokumentiert oder technisch abgebildet.
4. **Mindestaufbewahrung nicht erzwungen** `retention_days` ist frei konfigurierbar inkl. `0`
(kein Lock); es gibt keine Differenzierung nach Dokumentenart (6 vs. 10 Jahre vs. dauerhaft) und
kein erzwungenes Minimum von 10 Jahren für Buchungsbelege.
5. **Zeitstempel/Signaturerhalt (BSI TR 03125)** nicht implementiert (Nice-to-have, niedrige Priorität).
---
## Checkliste
| # | Anforderung | Status | Begründung / Codeverweis | Empfehlung |
|---|---|---|---|---|
| 1 | **Vollständigkeit** 100% Ein-/Ausgang archiviert | ⚠️ Teilweise | 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. Kein zentraler "Vollständigkeits-Reconciliation"-Mechanismus zwischen Mailserver-Log und Archiv. | Prüfung/Abgleich-Report (z.B. erwartete vs. archivierte Anzahl pro Tag) als neues Feature vorschlagen. |
| 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)** | ⚠️ Teilweise | `RetentionDays` global (`config/config.go:74`) und pro Tenant (`config/config.go:122`, Spalte `tenants.retention_days`) konfigurierbar — aber als EINZELNER Wert für alle Mails, keine Differenzierung nach Dokumentenart (Geschäftsbrief 6J / Rechnung 10J / Vertrag dauerhaft). `0` = kein Lock ist als Default zulässig (kein erzwungenes Minimum). | Spec-Erweiterung: Mindestwert (z.B. Warnung/Block unter 2190 Tagen) und/oder Kategorisierung nach Mail-Typ (PROJ-43 Archivierungsregeln könnte hierfür genutzt werden). |
| 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, `Purge()` löscht nur abgelaufene Mails (`storage.go:710-718`). | |
| 8 | **Protokollierung/Audit-Log unveränderlich** | ❌ Fehlt | `internal/audit/audit.go:64-75` erstellt `audit_log`-Tabelle OHNE Trigger/Rule gegen `UPDATE`/`DELETE` (PROJ-11 AC: "kein UPDATE/DELETE durch Admin oder Anwendung möglich" — NICHT umgesetzt). Die geforderte append-only JSON-Lines-Datei (`/var/log/archivmail/audit.log`) existiert nicht im Code — nur `New(dsn, logDir, logger)` mit Kommentar "logDir is reserved for future". Audit-Events (Login, Suche, Export, Import) werden korrekt geschrieben, aber Unveränderbarkeit ist nicht garantiert. | PROJ-11 nachbessern: (a) PostgreSQL-Trigger/REVOKE UPDATE/DELETE auf `audit_log`, (b) append-only Flat-File-Logger implementieren. Hohe Priorität für GoBD-Prüfungen. |
| 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** | ⚠️ Teilweise | 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`). Kein dokumentierter "Compliance-Erhalt-Check" nach Migration (z.B. automatischer Verify-Lauf nach Schema-Änderung). | Migrations-Runbook + Post-Migration-Integritätscheck (kann PROJ-18-Job nach Migration triggern) dokumentieren. |
| 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** | ❌ Fehlt | Kein Feld wie `contains_personal_data` o.ä. im Mail-Datenmodell (`internal/storage/storage.go` Tabelle `emails`); PROJ-20 (Nutzer-Löschung) behandelt nur Anonymisierung von Nutzerkonten/Audit-Einträgen, nicht von Mail-Inhalten. Konflikt GoBD-Aufbewahrung vs. DSGVO-Löschanspruch ist nirgends dokumentiert oder im Code abgebildet (z.B. `Purge()` prüft nur `retain_until`, keine "Lösch-trotz-Anfrage-abgelehnt"-Logik mit Begründung). | Neue Feature-Spec: DSGVO-Auskunfts-/Löschersuchen-Workflow, der bei aktivem `retain_until` automatisch auf "Aufbewahrungspflicht hat Vorrang" verweist und dies dokumentiert/protokolliert. |
| 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** | ⚠️ Teilweise | AES-256-GCM implementiert (`internal/storage/storage.go:154-...`, `encrypt()`), inkl. gzip vor Verschlüsselung (PROJ-36). ABER: `Keyfile` ist optional — `loadKey()` gibt bei leerem Pfad `nil` zurück → "no encryption configured" (`storage.go:126`). Es gibt keine Pflicht/Warnung im Setup, dass ein Keyfile gesetzt sein MUSS. | Setup-/Healthcheck-Warnung (evtl. in `archivmail status`, siehe letzter Commit) ergänzen, falls `Keyfile` leer ist — und/oder Pflichtfeld in Produktions-Config-Validierung. |
---
## Nächste Schritte (Vorschlag, Priorität absteigend)
1. **PROJ-11 nachbessern** (Audit-Log-Unveränderbarkeit): DB-Trigger gegen UPDATE/DELETE +
append-only JSON-Lines-Datei wie ursprünglich spezifiziert.
2. **Encryption-Pflicht**: Healthcheck/Setup-Validierung, dass `storage.keyfile` konfiguriert ist.
3. **Neue Spec**: DSGVO-Löschersuchen-Workflow mit GoBD-Vorrang-Dokumentation (Punkt 14).
4. **PROJ-34 erweitern**: Mindestaufbewahrung (kein `retention_days=0` als stiller Default in
produktiven Setups) + Differenzierung nach Dokumentenart (ggf. via PROJ-43 Regeln).
5. **Vollständigkeits-Reconciliation** (Punkt 1) als neues Feature evaluieren.
6. Nice-to-have: BSI TR 03125 Zeitstempel/Signaturerhalt (Punkt 12), nur bei konkretem Bedarf.
PROJ-47 (Tenant-Voll-Export, Status "In Review") sollte für Punkt 9 final abgeschlossen werden.