Files
archivmail/docs/MIGRATION_RUNBOOK.md
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

5.6 KiB
Raw Permalink Blame History

Migrations-Runbook archivmail

Bezug: GoBD/DSGVO-Checkliste (docs/GOBD_DSGVO_CHECKLIST.md), Punkt 10 "Migrationssicherheit". Ziel: nach jeder Schema-, Index- oder Storage-Migration belegen, dass keine Mail verloren ging und die GoBD-Kernanforderungen (Vollständigkeit, Unveränderbarkeit, Auffindbarkeit) weiterhin gelten.

Gilt für: initSchema/ALTER TABLE-Änderungen, Manticore-Reindex nach Schema-Änderung, Storage-Format-Wechsel (z.B. Kompression, Verschlüsselung), Tenant-Migrationen (migrate-tenants), Piler-Import (import-piler).

Grundsatz

Jede Migration ist ein potenzieller Datenverlust-Vektor. Vor/während/nach jeder produktiven Migration gilt: Zählen, Prüfen, Belegen — nicht nur "Migration lief ohne Fehler durch".

Ablauf

1. Vor der Migration (Baseline)

# Mail-Gesamtzahl + Tenant-Verteilung als Referenzwert
psql "$DSN" -c "SELECT tenant_id, COUNT(*) FROM emails GROUP BY tenant_id ORDER BY 1;"

# Aktuellen Reconciliation-Stand sichern (PROJ-52) — zeigt ob VOR der Migration
# bereits Lücken bestanden, damit die nicht fälschlich der Migration angelastet werden
archivmail reconcile --days 7 --dry-run 2>&1 | tee /var/log/archivmail/migration-pre-$(date +%F).log

# Backup, falls nicht ohnehin durch reguläres Backup abgedeckt (siehe devops-deploy)
pg_dump ... # Backup-Kommando gemäß bestehendem Backup-Runbook

Baseline-Zahlen (Gesamtzahl Mails, Zahl pro Tenant, Zeitpunkt) in den Deploy-/Change-Log-Eintrag übernehmen (DEVLOG.md oder Commit-Message).

2. Migration ausführen

Reguläres Vorgehen laut update.sh/install.sh (Schema-Migrationen laufen idempotent beim Start über initSchema, kein manueller Schritt nötig für reine ADD COLUMN IF NOT EXISTS). Bei Index-Migrationen (z.B. neues Manticore- Feld) ggf. archivmail reindex bzw. archivmail reindex-tenant <id> gezielt ausführen.

3. Nach der Migration (Compliance-Erhalt-Check)

# 1. Zählvergleich — Gesamtzahl und Tenant-Verteilung MUSS mit Baseline übereinstimmen
psql "$DSN" -c "SELECT tenant_id, COUNT(*) FROM emails GROUP BY tenant_id ORDER BY 1;"
# Abweichung → STOP, nicht weiter deployen, Ursache klären (siehe "Bei Abweichung" unten)

# 2. Integritätscheck (PROJ-18) — läuft im Daemon ohnehin alle 5 Minuten automatisch
#    (runIntegrityCheck in cmd/archivmail/main.go), nach einer Migration zusätzlich
#    gezielt die Logs der ersten Läufe nach Neustart prüfen:
journalctl -u archivmail --since "-15min" | grep "integrity check"
# Erwartung: "integrity check: complete" mit failed=0

# 3. Manticore-Index-Konsistenz — Trefferzahl im Index sollte plausibel zur
#    Mail-Zahl in Postgres passen (kein 1:1, da Anhänge/OCR-Text mitgezählt werden
#    können, aber grobe Größenordnung muss stimmen)
mysql -h127.0.0.1 -P9306 -e "SELECT COUNT(*) FROM emails_global;"

# 4. Reconciliation-Report (PROJ-52) — Anomalie-Alert darf durch die Migration
#    selbst NICHT ausgelöst werden (kein realer Rückgang, nur andere Quelle/Zeitpunkt)
archivmail reconcile --date $(date +%F) 
# Dashboard/API /api/admin/reconciliation prüfen: kein unerwarteter alert:true

# 5. Stichprobe: eine bekannte Mail vor/nach Migration per ID abrufen und
#    EML-Export vergleichen (Byte-Identität, PROJ-12 Unveränderbarkeit)
archivmail export --id <bekannte-mail-id> --out /tmp/post-migration-check.eml
diff /tmp/pre-migration-check.eml /tmp/post-migration-check.eml

4. Bei Abweichung

  • Zahlendifferenz in Schritt 3.1 → Migration NICHT als abgeschlossen betrachten, keine weiteren Schritte (Cron-Purge, Deploy auf zweiten Server) auslösen.
  • Ursache eingrenzen: welcher Tenant/Zeitraum betroffen? Anhand Audit-Log (event_type IN ('import','mail_purged')) im Migrationszeitraum abgleichen.
  • Rollback nur nach Rücksprache — Datenbank-Restore aus Schritt 1-Backup, nicht einfach erneut migrieren ohne Root-Cause.
  • Vorfall im DEVLOG.md und ggf. als Audit-Log-Eintrag dokumentieren (GoBD-Nachvollziehbarkeit: auch fehlgeschlagene Migrationsversuche gehören ins Protokoll).

Speziell: Tenant-Migration (archivmail migrate-tenants)

Zusätzlich zu obigem Ablauf:

  • Vor der Migration: SELECT COUNT(*) FROM emails WHERE tenant_id IS NULL; (Mails ohne Tenant-Zuordnung) als Baseline — nach der Migration darf diese Zahl nur durch bewusste Zuordnung sinken, nie durch Datenverlust steigen.
  • Tenant-Quotas (PROJ-29) nach Migration neu berechnen lassen, falls Mails zwischen Tenants verschoben wurden.

Speziell: Piler-Import (archivmail import-piler)

  • Piler-seitige Mail-Zahl (aus Piler-Datenbank/Export) als externe Baseline neben der internen archivmail-Zählung führen — reine interne Zählung beweist nicht, dass alles aus Piler übernommen wurde.
  • Reconciliation-Quelle import (PROJ-52) zeigt Tageszahlen des Imports; gegen Piler-Log gegenprüfen.

Speziell: Manticore-Schema-Änderung (z.B. neue Spalte, PROJ-50 cc_addr/bcc_addr)

  • ensureColumn-Migration ist idempotent, aber NICHT rückwirkend befüllend für bereits archivierte Mails (nur neue/reindexierte Dokumente bekommen den Wert). Nach Schema-Änderung: archivmail reindex für Bestandsdaten planen, wenn das neue Feld auch für alte Mails durchsuchbar sein soll — sonst in der jeweiligen Feature-Spec als bekannte Deviation vermerken (siehe PROJ-50, BCC-Deviation).

Verweis

  • PROJ-18 (Integritätsprüfung, SHA-256, alle 5 Minuten automatisch im Daemon)
  • PROJ-52 (Vollständigkeits-Reconciliation, täglicher Report)
  • PROJ-19 (Piler-Import), PROJ-30 (Xapian→Manticore-Migration) — historische Migrationen, an denen dieses Runbook sich orientiert