feat(PROJ-52): Vollständigkeits-Reconciliation (Zähl-Report Mailserver vs. Archiv)

Täglicher Cron-Job (archivmail reconcile) berechnet pro Tenant/Quelle
(SMTP-Journal, IMAP-Konto, POP3-Konto, Datei-Import) archivierte Mail-Zahlen,
für IMAP zusätzlich einen Soll/Ist-Vergleich via UID-Tracking. Abweichungen
über Schwellenwert erzeugen Audit-Log-Warnung. Neue Admin-Dashboard-Kachel
"Vollständigkeits-Check" (letzte 7 Tage, Warn-Badge, CSV-Export).

Schließt die "teilweise erfüllt"-Lücke bei Vollständigkeit im
GoBD/DSGVO-Compliance-Check (VOI-Grundsatz 2).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
sysops
2026-07-03 22:48:42 +02:00
co-authored by Claude Sonnet 5
parent b286352d07
commit be93614c9f
24 changed files with 1577 additions and 10 deletions
+7
View File
@@ -91,5 +91,12 @@ audit:
log_path: /var/archivmail/audit.log
retention_days: 365
# PROJ-52: Vollständigkeits-Reconciliation (Zähl-Report Mailserver vs. Archiv).
# Täglich per Cron ausführen: `archivmail reconcile` (rechnet den Vortag ab).
# alert_threshold_pct = relativer Rückgang (%) unter den 7-Tage-Durchschnitt,
# ab dem ein reconciliation_anomaly Audit-Eintrag entsteht (Default 50).
# reconciliation:
# alert_threshold_pct: 50
logging:
level: info
+33
View File
@@ -42,6 +42,39 @@ type Config struct {
// PROJ-56: load-spreading for background jobs.
OCR OCRConfig `yaml:"ocr"`
IMAPScheduler IMAPSchedulerConfig `yaml:"imap_scheduler"`
// PROJ-52: Vollständigkeits-Reconciliation (Zähl-Report Mailserver vs. Archiv).
Reconciliation ReconciliationConfig `yaml:"reconciliation"`
}
// ReconciliationConfig holds settings for the daily completeness reconciliation
// job (PROJ-52). The job counts newly archived mails per source and per day and
// flags significant drops against the trailing 7-day average.
type ReconciliationConfig struct {
// AlertThresholdPct is the relative drop (in percent, below the trailing
// 7-day average) that triggers a `reconciliation_anomaly` audit entry.
// A pointer so an explicit 0 (alert on any drop) is distinguishable from an
// unset value (use the default).
// nil -> DefaultReconciliationThresholdPct (50%)
// 0 -> alert whenever today's count is below the average
// 1..100 -> alert when today's count is more than this % below the average
AlertThresholdPct *int `yaml:"alert_threshold_pct,omitempty"`
}
// DefaultReconciliationThresholdPct is the default drop threshold (50% below the
// trailing 7-day average) applied when reconciliation.alert_threshold_pct is
// omitted from the config.
const DefaultReconciliationThresholdPct = 50
// ResolvedThresholdPct returns the effective alert threshold in percent.
// A nil or out-of-range value falls back to the default.
func (c ReconciliationConfig) ResolvedThresholdPct() int {
if c.AlertThresholdPct == nil {
return DefaultReconciliationThresholdPct
}
if *c.AlertThresholdPct < 0 || *c.AlertThresholdPct > 100 {
return DefaultReconciliationThresholdPct
}
return *c.AlertThresholdPct
}
// OCRConfig holds settings for the background OCR worker (PROJ-56).