Commit Graph
261 Commits
Author SHA1 Message Date
sysops a7390151a1 docs: GoBD-Checklist auf aktuellen Stand bringen (PROJ-52, PROJ-56c)
Punkt 1 (Vollständigkeit) war noch als "Teilweise" markiert, obwohl PROJ-52
(Reconciliation-Report) das inzwischen abdeckt. Punkt 7 (Löschsperre)
beschrieb noch den alten Purge() ohne Markierungspflicht; ergänzt um
PROJ-56c Cron-Purge, der nur retain_until < NOW() UND marked_for_deletion
löscht.
2026-07-04 12:07:21 +02:00
sysopsandClaude Sonnet 5 30b7586d94 docs(PROJ-43,PROJ-52): Status auf Deployed setzen nach Produktiv-Deploy
Beide Features wurden auf 192.168.1.131 deployt (Commit 4c92587), inkl. der
zugehörigen QA-Bugfixes (Dry-Run-Adressmatching PROJ-43, days-Clamp PROJ-52).
Deployment-Abschnitte in den Feature-Specs und INDEX.md aktualisiert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 12:00:07 +02:00
sysopsandClaude Sonnet 5 4c92587b60 fix(PROJ-43): Dry-Run für from_addr/to_addr matcht bare Adressen statt <addr>-Form
dryRunCondition() erwartete faelschlich die Winkelklammer-Form "Name <addr>",
waehrend mail_from/mail_to die Adresse bare speichern - Dry-Run zeigte dadurch
immer 0 Treffer fuer Adress-Regeln, obwohl der Live-Matcher (routeBareAddr)
korrekt matcht. QA-Ergebnisse (Bug-1) in die Feature-Spec uebernommen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 11:57:21 +02:00
sysopsandClaude Sonnet 5 04e5b0f74a fix(security-audit): HTTPS/Port-Checks erkennen nftables Set-Syntax nicht
strings.Contains(nftStr, "dport 443") fand den Substring nicht, wenn
nftables mehrere Ports als Set ausgibt ("tcp dport { 80, 443 } accept" statt
"tcp dport 443 accept") — das ist bei archivmail-Installationen der
Normalfall (80+443 stehen zusammen in einer Regel). Dashboard zeigte
dadurch fälschlich "Kein HTTPS — Verbindungen unverschlüsselt", obwohl
Port 443 korrekt offen war (bestätigt auf 131 und 132).

Neue Helper-Funktion nftHasPort() per Regex erkennt beide Formen
(Einzelport und Set). Betrifft die Checks für HTTPS/443, Port 3000 und
Port 8080.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 00:02:20 +02:00
sysopsandClaude Sonnet 5 c274df5023 fix(deploy): update.sh synchronisiert systemd-Units bei jedem Deploy
Bisher schrieb nur install.sh die Unit-Dateien (einmalig beim Erst-Setup).
Server, die vor einer Unit-Änderung installiert wurden, blieben dauerhaft
auf altem Stand — konkret fehlte auf 192.168.1.132 CAP_NET_ADMIN (wurde in
install.sh ergänzt, aber nie auf bereits laufende Installationen
nachgezogen), wodurch die Security-Tab-Aktion "Firewall aktivieren"
(nft -f /etc/nftables.conf) mit "Operation not permitted" fehlschlug.

update.sh schreibt jetzt bei jedem Deploy beide Unit-Dateien neu (identisch
zum install.sh-Template) und lädt sie per daemon-reload nach, bevor die
Dienste gestartet werden.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 23:55:47 +02:00
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
sysopsandClaude Sonnet 5 767373b206 feat(PROJ-46): E-Mail als primärer Login-Identifier für Tenant-User
Tenant-User (tenant_id IS NOT NULL) melden sich künftig per E-Mail an statt
per Username — behebt Verwechslungen wie im Support-Fall vom 2026-06-13
(Login schlug trotz Passwort-Reset fehl, weil E-Mail statt Username
verwendet wurde). Nicht-Tenant-User (Superadmin/System) können weiterhin
Username ODER E-Mail nutzen.

Neue Store.VerifyLogin() prüft erst per E-Mail (alle User), fällt dann auf
Username zurück (nur tenant_id IS NULL). VerifyPassword() bleibt für den
IMAP-Server-Login-Pfad (PROJ-26) unverändert. Bewusster Breaking Change für
Tenant-User, Datenqualität vorab geprüft (0 Kollisionen).

Security-Nachtrag: bcrypt-Dummy-Compare im "user not found"-Pfad ergänzt,
um Timing-basierte Identifier-Enumeration zu verhindern.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 23:37:20 +02:00
sysopsandClaude Sonnet 5 804cd62201 fix(PROJ-50): DSGVO-Tab lädt nicht — API-Contract-Mismatch Frontend/Backend
Backend liefert bei GET /api/admin/dsgvo ein Objekt {"requests":[...]},
Frontend erwartete rohes Array → .map() auf Nicht-Array warf Exception,
angezeigt als "DSGVO-Anträge konnten nicht geladen werden".

Zusätzlich stimmten DSGVOResultSummary/DSGVOMailResult-Feldnamen nicht mit
dem Go-JSON überein (total vs. total_hits; id/status/received_at existieren
im Backend nicht, stattdessen mail_id/deletable/deleted/date). Status wird
jetzt im Frontend aus deletable/deleted abgeleitet (mailStatus()).

Bug bestand seit Feature-Implementierung (2026-06-13), fiel erst jetzt beim
ersten Live-Test auf.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 23:06:14 +02:00
sysopsandClaude Sonnet 5 e91206c2b5 chore(PROJ-52): Cron-Job für Reconciliation in /etc/cron.d/archivmail ergänzen
Läuft nachts um 04:10 Uhr, nach dem Purge-Job und außerhalb der
OCR-Pause. Ohne diesen Eintrag existierte der neue Subcommand
"archivmail reconcile" nur manuell aufrufbar, ohne produktiven Betrieb.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 22:54:29 +02:00
sysopsandClaude Sonnet 5 99e4c1bbe4 fix(security): Fail-closed Tenant-Filter in v1-Suche + SMTP-Out-Key-Kette gehärtet
Security-Audit-Nachtrag (siehe PROJ-64):

- internal/api/v1_handlers.go: handleV1SearchMails fehlte der fail-closed
  Tenant-Post-Filter-Fallback für den Fall idxMgr==nil (gleiches Muster wie
  bereits in search_handlers.go). Aktuell nicht ausnutzbar, da idxMgr in
  main.go immer gesetzt wird, aber strukturelle Absicherung gegen künftige
  Regressionen (analog PROJ-55 BUG-1).
- internal/smtpoutconfig/store.go: Verschlüsselungsschlüssel wird jetzt aus
  dem HKDF-abgeleiteten aesKey gebildet statt aus dem rohen cfg.API.Secret,
  konsistent mit internal/ldapconfig und internal/imap/store.go (SEC-08).
  Verifiziert: smtp_out_config auf Produktiv (131) war leer, kein
  Breaking Change für bestehend gespeicherte Zugangsdaten.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 22:48:55 +02:00
sysopsandClaude Sonnet 5 be93614c9f 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>
2026-07-03 22:48:42 +02:00
sysopsandClaude Sonnet 5 b286352d07 fix(PROJ-64): Session-Invalidation bei Passwort-Change + Datei-Permissions gehärtet
Security-Audit deckte zwei Medium-Findings auf: JWTs blieben bis zu 8h nach
Passwort-Change/-Reset oder Admin-TOTP-Reset gültig (kein Session-Invalidation),
und archivierte Mails/Anhänge wurden mit 0644/0755 statt 0600/0700 geschrieben.

- users.tokens_valid_after (neue Spalte) wird bei SetPassword() und
  InvalidateTokensBefore() gesetzt; ValidateToken() lehnt JWTs mit iat davor ab.
- Admin-TOTP-Reset revoked jetzt aktive Sessions des Zielnutzers.
- Mail-/Attachment-Dateien und ihre Verzeichnisse nur noch für den
  archivmail-Service-Account lesbar.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 22:23:27 +02:00
sysopsandClaude Sonnet 4.6 0ccbd5bafb fix(mailparser): kaputte/truncated Multipart-Mails partiell indexieren statt scheitern
Bei NextPart()-Fehler (EOF, malformed header) wird der bereits geparste Inhalt
zurückgegeben statt der gesamte Parse abgebrochen. parseMultipart() gibt keinen
Fehler mehr zurück — partieller Text/HTML ist besser als gar kein Index-Eintrag.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 20:17:33 +02:00
sysops 5e7ae6e056 fix: Manticore-Architektur in install.sh dynamisch (arm64-Unterstützung) 2026-06-30 20:02:35 +02:00
sysopsandClaude Sonnet 4.6 909a3b0782 chore: update.sh OS-versions-agnostisch machen (Debian 14+ safe)
Go: Versionsprüfung + Auto-Install von upstream falls < 1.24 oder fehlt —
unabhängig von apt und Debian-Version, überlebt OS-Upgrades auf Debian 14+.
Manticore: bookworm-Paket hartcodiert, arm64 in update.sh ergänzt.
Fehlermeldung "apt-get install golang-go" entfernt (falsch nach Umstellung).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 19:59:25 +02:00
sysopsandClaude Sonnet 4.6 681d81c469 chore: Installer auf Debian 13 (trixie) als Mindestanforderung festlegen
- OS-Check: bricht ab wenn nicht Debian 13 erkannt
- Go: apt-golang-go entfernt, Go 1.24.4 von dl.google.com (arm64/amd64)
- Manticore: bookworm-Paket hardcodiert (kein natives trixie-Paket), in
  install.sh und update.sh konsistent
- Native config: batch_mode: true für index + ocr (wie PROJ-58 vorgesehen)
- systemd: NEXT_PUBLIC_API_URL entfernt (Next.js baked bei Build, nicht Runtime)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 19:57:04 +02:00
sysopsandClaude Sonnet 4.6 261a95437c feat(PROJ-50): Admin-Tab "DSGVO-Anfragen" implementiert
Neuer Tab im Admin-Bereich: Antrags-Liste, Formular (Adresse + Zeitraum),
Detail-Dialog mit Mail-Tabelle, PDF-Export und Löschen mit Bestätigung.
Rollen-Gating: admin/auditor sehen den Tab, nur admin kann anlegen/löschen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 19:34:25 +02:00
sysopsandClaude Sonnet 4.6 0552ce49e2 fix(PROJ-50): Cross-Tenant-Lücke + Fehlerbehandlung in DSGVO-Handlern behoben
Bug-1: GetDSGVOMailMeta mit tenant_id-Filter (Defense-in-Depth an DB-Schicht).
Bug-2: Verwaiste open-Einträge bei Auswertungsfehler werden auf failed markiert.
Bug-3: Fehlgeschlagene Suchen werden im Audit-Log protokolliert.
Bug-6: Ungültige date_from/date_to-Eingaben liefern HTTP 400.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 18:17:25 +02:00
sysopsandClaude Sonnet 4.6 dcb88317ac fix(PROJ-63): Defense-in-Depth Tenant-Scope-Härtung der Admin-Endpunkte
tenantAccessAllowed()-Check in allen {id}-Handlern von tenant_handlers.go,
tenant_domain_handlers.go und tenant_logo_handlers.go ergänzt — No-op für
globale Admins, zweite Verteidigungslinie für hypothetische tenant-gebundene
Admin-Sessions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 14:37:39 +02:00
sysopsandClaude Sonnet 4.6 c1338f6721 chore(PROJ-60): Xapian-Reste aus Dockerfile, Makefile und Doku entfernen
Dockerfile und Makefile bauten noch mit CGO_ENABLED=1 -tags xapian und
installierten libxapian-dev/libxapian30, obwohl der Xapian-Code bereits
entfernt wurde. PRD.md und api-v1.md erwähnten Xapian noch im Tech-Stack
bzw. als Such-Syntax-Referenz.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 09:48:52 +02:00
sysopsandClaude Sonnet 4.6 7c028601cf fix(PROJ-62): Cross-Tenant IDOR bei POP3-Konto-Löschung/-Import behoben (Sicherheitsbug)
handleDeletePop3 und handleStartPop3Import prüften nur Owner/Rollen-Level,
nicht den Tenant-Scope (anders als das korrekte IMAP-Pendant). Ein
domain_admin konnte dadurch POP3-Konten eines fremden Tenants löschen
oder deren Import anstoßen. Fix: tenantAccessAllowed(sess, acc.TenantID)
ergänzt, analog zum IMAP-Handler. Gefunden bei gezielter Nachsuche nach
Geschwister-Bugs zu PROJ-61.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 01:52:01 +02:00
sysopsandClaude Sonnet 4.6 363874767b fix(PROJ-61): Cross-Tenant Stored XSS via Mandanten-Logo behoben (Sicherheitsbug)
GET /api/tenants/{id}/logo prüfte nur die Authentifizierung, aber keinen
Tenant-Scope — jeder eingeloggte Nutzer konnte das Logo jedes beliebigen
Tenants lesen. Kombiniert mit dem bisher erlaubten SVG-Upload (kann
eingebettetes JavaScript enthalten) ergab das einen Cross-Tenant Stored-XSS:
ein domain_admin konnte ein bösartiges SVG als eigenes Logo hochladen und
Opfer aus beliebigen anderen Tenants per direktem Link darauf locken.

Fix: tenantAccessAllowed()-Scope-Check beim Logo-Lesepfad (analog PROJ-55),
SVG aus erlaubten Upload-Typen entfernt, X-Content-Type-Options: nosniff
als Defense-in-Depth ergänzt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 00:31:41 +02:00
sysopsandClaude Sonnet 4.6 5f63bfe8d4 chore(PROJ-60): Xapian-Legacy-Backend vollständig aus dem Code entfernt
Xapian war seit der Manticore-Migration (PROJ-30) nur noch ein
build-tag-gatetes, in Produktion nie genutztes Legacy-Backend.
internal/index/xapian.go, xapian_stub.go, xapian_wrapper.cpp/.h entfernt;
index.New() unterstützt jetzt nur noch "manticore". Default-Fallbacks in
Nebenwerkzeugen (archivmail-import/-export, cmd_export/cmd_reindex/...)
von "xapian" auf "manticore" korrigiert, Xapian-spezifische Tests entfernt,
Kommentare bereinigt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 00:12:06 +02:00
sysopsandClaude Sonnet 4.6 043520ecc3 chore(PROJ-59): tote Xapian-Reste aus config.docker.yml.example entfernen
xapian_path/backend: xapian waren toter Datenmüll (StorageConfig hat kein
xapian_path-Feld, wird beim YAML-Unmarshal stillschweigend ignoriert).
Auf den tatsächlich genutzten Manticore-Default umgestellt
(backend: manticore, manticore_dsn). Behebt das in PROJ-56 QA als
INFO 3 dokumentierte, außerhalb des Scopes liegende Finding.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 00:03:49 +02:00
sysopsandClaude Sonnet 4.6 46502abe75 fix(PROJ-58): Lockfile gegen überlappende Cron-Batch-Läufe + update.sh synct Cron-Dateien
Root Cause für ausbleibende Lastsenkung: update.sh hat /etc/cron.d/archivmail
nie auf den Server kopiert, daher fehlten die PROJ-58-Cronzeilen trotz
aktivem batch_mode komplett. Jetzt kopiert update.sh die Cron-Datei und alle
Wrapper-Skripte bei jedem Deploy automatisch ein.

Zusätzlich: Wrapper-Skripte (analog mailpiler indexer.delta.sh) verhindern
per Lockfile, dass sich Cron-Läufe bei großem Backlog überlappen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 23:54:37 +02:00
sysopsandClaude Sonnet 4.6 c91eeac0a0 docs(PROJ-58): batch_mode für Neuinstallationen standardmäßig aktivieren
config.docker.yml.example setzt index.batch_mode/ocr.batch_mode jetzt
auf true statt es nur kommentiert zu zeigen, damit neue Installationen
direkt mit Cron-Batch-Verarbeitung statt Dauerbetrieb starten. Bestehende
Installationen (131/132) sind unberührt, da ihre config.yml unabhängig
vom Repo-Beispiel ist.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 23:16:34 +02:00
sysopsandClaude Sonnet 4.6 fae274f930 feat(PROJ-58): Indexierung + OCR optional als Cron-Batch statt Dauerbetrieb
Neues config.yml-Feld batch_mode (index/ocr, Default false = unverändertes
Verhalten). Bei batch_mode:true verarbeiten neue Cron-Jobs (index-pending,
ocr-reprocess) die Backlogs in größeren Abständen statt sofort bei jedem
Mail-Import, um Schreiblast auf der Festplatte zu glätten. Zeiten in
/etc/cron.d/archivmail frei anpassbar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 23:07:17 +02:00
sysopsandClaude Sonnet 4.6 76655f78a2 fix(PROJ-57): UTF-8-Encoding für Mails mit Nicht-UTF-8-Charset korrigieren
Der Mail-Parser ignorierte das charset-Parameter aus Content-Type und
interpretierte Bytes immer als UTF-8, wodurch iso-8859-1/windows-1252
kodierte Mails (z.B. mit Umlauten) als Mojibake gespeichert wurden.
Zusätzlich fehlte das Charset für die Manticore-MySQL-Verbindung und
der charset-Parameter im JSON-Response-Header.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 22:47:00 +02:00
sysopsandClaude Sonnet 4.6 69c120a268 feat(PROJ-56d): archivmail import um --tenant Flag erweitert
archivmail import --dir/--file ordnete importierte Mails bisher immer
ohne Mandant zu (Save(..., nil) fest verdrahtet). Neuer --tenant <id> Flag
übergibt die Tenant-ID an Store.Save() und an idxMgr.ForTenant(), sodass
Mail sowohl in der DB als auch im richtigen Tenant-Suchindex landet —
und automatisch die Retention-Regeln des Tenants greifen (applyRetention
nutzt bereits die übergebene tenantID). Relevant für den geplanten
Watch-Folder-Import pro Mandant.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 17:03:15 +02:00
sysopsandClaude Sonnet 4.6 b3ff8e6cf9 feat(PROJ-56c): Purge-Cron löscht nur explizit markierte Mails
Der automatische Purge-Cron darf nicht allein anhand des abgelaufenen
retain_until löschen — eine Mail muss zusätzlich von einem Admin im UI
zur Löschung markiert worden sein. Dafür: neue Spalten
marked_for_deletion(_by/_at) auf emails, Store.ListExpiredMarkedMailIDs()
(retain_until abgelaufen UND markiert) für den Cron-Pfad, und
Store.SetMarkedForDeletion() zum Setzen/Löschen der Markierung.

Neue Endpoints (domain_admin+, tenant-scoped):
- GET  /api/admin/retention/expired      Metadaten abgelaufener Mails
                                          (kein Body-Zugriff, SEC-29)
- PUT  /api/admin/mails/{id}/mark-deletion  Markierung setzen/entfernen,
                                          mit Audit-Log-Eintrag

RetentionTab.tsx zeigt abgelaufene Mails mit Checkbox zum Markieren.
Der bestehende manuelle "Jetzt löschen"-Button (/api/admin/purge) bleibt
unverändert und löscht weiterhin alle abgelaufenen Mails auf einen Klick —
nur der unbeaufsichtigte Cron-Job ist jetzt auf markierte Mails beschränkt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 16:40:18 +02:00
sysopsandClaude Sonnet 4.6 586af2478c feat(PROJ-56c): GoBD-Retention-Purge als Cron-Job + Delete()-Konsistenzfix
archivmail purge ist ein neuer CLI-Befehl, der Mails mit abgelaufener
retain_until löscht, aus dem Suchindex entfernt und pro Mail einen
Audit-Eintrag (mail_purged) schreibt — analog zu Pilers purge.sh, nachts
03:40 Uhr über deploy/cron.d/archivmail. Nur Mails mit explizit gesetztem
und abgelaufenem retain_until werden angefasst; ohne retain_until bleibt
alles unberührt, die Löschsperre (PROJ-34) greift weiterhin.

Beim Testen aufgedeckt: Store.Delete() entfernte die Datei vor dem
DB-Delete und verschluckte den Fehler, wenn email_refs/email_attachments
per Fremdschlüssel die Löschung blockierten — Ergebnis war ein DB-Eintrag
ohne zugehörige Datei. Jetzt läuft die DB-Löschung (inkl. abhängiger
Zeilen) zuerst in einer Transaktion, die Datei wird erst nach
erfolgreichem Commit entfernt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 16:00:41 +02:00
sysopsandClaude Sonnet 4.6 d826fe1da7 chore(PROJ-56): Cron-Dateien nach mailpiler-Vorbild konsolidieren
Statt einer Datei pro Job (wie bisher archivmail-ocr-pause) bündelt
/etc/cron.d/archivmail jetzt alle archivmail-Wartungsjobs in einer Datei,
analog zu /etc/cron.d/piler. Neue Jobs (Purge, nächtlicher Reindex,
Watch-Folder-Import) werden hier künftig als weitere Zeile ergänzt statt
in eigenen Dateien.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 15:41:50 +02:00
sysopsandClaude Sonnet 4.6 dba9939880 feat(PROJ-56): OCR-Pausenfenster per SIGHUP-Reload statt Restart
paused_hours konnte bisher nur über einen vollen Prozess-Restart geändert
werden, was SMTP/IMAP/API unnötig unterbricht. Worker.pausedHours ist jetzt
ein atomic.Pointer mit SetPausedHours(); SIGHUP liest config.yml neu und
aktualisiert nur die OCR-Pausenzeit im laufenden Prozess. Neue
deploy/cron.d/archivmail-ocr-pause(.sh) lässt Admins die Pausenzeiten direkt
in der Cron-Datei pflegen und löst per systemctl reload statt restart aus.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 14:46:13 +02:00
sysops be48a99af9 docs(PROJ-56): Status auf Deployed setzen
Erfolgreich auf 192.168.1.132 (Test) und 192.168.1.131 (Produktion)
deployed, keine Fehler.
2026-06-22 14:35:10 +02:00
sysops 12c4dc7ea7 docs(PROJ-56): Test-Deployment auf 192.168.1.132 dokumentieren 2026-06-22 14:30:33 +02:00
sysops 4dbf27cc1d feat(PROJ-56): Last-Entzerrung für OCR und IMAP-Sync
OCR-Worker pausieren optional in konfigurierbarem Zeitfenster
(paused_hours), Jobs bleiben pending statt verworfen zu werden.
IMAP-Scheduler verteilt Sync-Starts via deterministischem
Pro-Account-Jitter, um Lastspitzen bei vielen Postfächern mit
gleichem Intervall zu vermeiden. Beides per Config opt-out,
Default-Verhalten unverändert. Build + Smoke-Test auf 132 verifiziert.
2026-06-22 14:21:09 +02:00
sysops a55faf74b1 chore: Frontend-Seiten in Komponenten/Hooks aufteilen
admin/page.tsx (1019→446), search/page.tsx (871→304), imap/page.tsx
(738→142), settings/page.tsx (641→56). Reine Umstrukturierung,
keine Verhaltensänderung, Build verifiziert.
2026-06-22 11:29:43 +02:00
sysops ce197a3ab7 docs(PROJ-55): Status auf Deployed setzen
Erfolgreich auf 192.168.1.132 (Test) und 192.168.1.131 (Produktion)
deployed, Live-Verifikation bestanden.
2026-06-22 00:13:23 +02:00
sysops ef83174553 docs(PROJ-55): Live-Verifikation auf 132 dokumentieren
Initial verdächtigter Cross-Tenant-Treffer als beabsichtigtes
email_refs-Dedup-Verhalten verifiziert (kein Leak). PROJ-55 ist
production-ready, Live-Test PASS.
2026-06-22 00:10:51 +02:00
sysops 1d27dc2d8b refactor: große API-Handler-Dateien in fokussierte Module aufteilen
Reine Code-Verschiebung, keine Logikänderung. Betroffen:
- ldap_tenants.go (994 Zeilen) -> ldap_tenants.go (Routing) + ldap_handlers.go
  + tenant_handlers.go + tenant_domain_handlers.go + tenant_logo_handlers.go
  + tenant_helpers.go
- import_handlers.go (621 Zeilen) -> imap_handlers.go + pop3_handlers.go
  + import_helpers.go
- admin_handlers.go (702 Zeilen) -> admin_users_handlers.go +
  admin_status_handlers.go + admin_services_handlers.go +
  admin_security_handlers.go

Lokal kein Go-Build möglich — Verifikation manuell per Funktions- und
Import-Abgleich Alt/Neu (alle Symbole exakt einmal vorhanden). Build
muss vor Deploy auf 192.168.1.131/132 bestätigt werden.
2026-06-21 23:38:57 +02:00
sysops 6d3ca7fd50 chore: ungenutzten Frontend-Code entfernen
PageSkeleton, das shadcn Toast-System (toaster/sonner/toast/use-toast)
und das sonner-Paket waren im Code nirgends importiert. Build erfolgreich
verifiziert nach Entfernung.
2026-06-21 23:38:51 +02:00
sysops d80a5d8050 chore: echten HTTP-Health-Check statt nur systemd-Status in update.sh
systemctl is-active zeigt nur, dass der Prozess läuft — nicht, dass er
tatsächlich auf Anfragen antwortet (z.B. bei hängendem DB-Connect).
Beide Dienste werden jetzt per HTTP gegen /api/health (Backend) bzw.
Port 3000 (Frontend) mit Retry (15x1s) geprüft, bevor das Update als
erfolgreich gemeldet wird.
2026-06-21 22:59:31 +02:00
sysops f55a40c77d chore: Manticore-Reindex aus update.sh entfernen
Der automatische Reindex lief bisher bei jedem Deploy mit (volle
Mailmenge), obwohl er nur einmalig für die Xapian→Manticore-Migration
gedacht war. Neue Mails werden ohnehin synchron beim Import indiziert
(IndexSync). Reindex bei Bedarf (z.B. Schema-Änderungen) jetzt manuell.
2026-06-21 22:46:55 +02:00
sysops 92e57431c3 fix(PROJ-55): Tenant-Isolation für Rolle "auditor" + Audit-Log korrigieren
Kritischer Sicherheitsbug: Auditoren mit zugewiesenem Tenant sahen Mails
und Audit-Log-Einträge anderer Tenants (DSGVO-relevant). auditor wird
jetzt analog zu domain_auditor pro Tenant gescoped, sofern tenant_id
gesetzt ist (Abwärtskompatibilität: ohne tenant_id bleibt der bisherige
globale Zugriff erhalten). Betrifft Mail-Suche, Mail-Detailzugriff,
Export, eDiscovery, Threads, OCR sowie das Audit-Log (DB + tamper-evidentes
Flat-File), inkl. Befüllung von tenant_id an allen Audit-Log-Schreibstellen.
2026-06-21 22:26:06 +02:00
sysops 4a8b8964e5 docs(PROJ-53, PROJ-54): Status auf Deployed setzen
Beide Features auf 192.168.1.132 (Test) und 192.168.1.131 (Produktion)
deployed und vom Nutzer bestätigt.
2026-06-14 23:26:57 +02:00
sysops 62693fa36a chore: npm audit fix — Dependency-Updates für picomatch/Next.js-Advisories
Behebt 5 von 7 gemeldeten Schwachstellen (picomatch ReDoS/Method-Injection,
mehrere Next.js-Advisories) via semver-konformer Patch-Updates in
package-lock.json. Verbleibende 2 moderate (postcss <8.5.10) sind in
next@16.2.9 selbst gebündelt, kein stabiler Fix verfügbar (nur 16.3.0
canary/preview) — npm audit fix --force würde next auf 9.3.3 downgraden.
2026-06-14 23:12:35 +02:00
sysops 776dee8a56 fix(PROJ-54): Listenansicht/Pagination für Rolle "user" korrigieren
Filtert die Mails des Nutzers (From/To/Cc/Bcc) jetzt serverseitig via
req.AnyAddress vor LIMIT/OFFSET im Index, statt wie bisher per
Post-Filter nach der Paginierung. total und totalPages stimmen damit
mit den tatsächlich sichtbaren Treffern überein.
2026-06-14 22:58:56 +02:00
sysops 4c20a0025a fix(PROJ-53): TypeScript-Build-Fehler durch fehlendes list_page_size in LoginResponse
setCachedUser() in den Login-Seiten erforderte alle MeResponse-Felder;
list_page_size wird jetzt aus der Login-Response übernommen.
2026-06-14 22:31:59 +02:00
sysops 472ba6a087 feat(PROJ-53): Konfigurierbare Listenanzahl pro Seite
- users.list_page_size (Default 25), PATCH /api/auth/preferences,
  Whitelist 25/50/100/200, Wert in login/me-Response
- Settings-UI mit Select, /search nutzt gespeicherte Seitengröße
- /api/search page_size serverseitig auf max. 500 gecappt

fix(PROJ-46): login_attempts-Migration nutzte s.db statt s.pool
(Backend kompilierte nicht)

feat(PROJ-50): DSGVO-Löschersuchen Backend (dsgvo_requests, Handler,
cc_addr/bcc_addr Indexerweiterung) — noch nicht QA'd/deployed
2026-06-14 22:25:02 +02:00
sysopsandClaude Sonnet 4.6 b73ef55a65 fix: archivmail.service benötigt CAP_NET_ADMIN für Firewall-Aktivierung
Der Admin-Endpoint "Firewall aktivieren" (POST /api/admin/security/fix,
enable_firewall) ruft "nft -f /etc/nftables.conf" auf. flush ruleset
benötigt CAP_NET_ADMIN, das fehlte bisher in der systemd-Unit, wodurch
der Aufruf mit "Operation not permitted" fehlschlug.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 22:01:29 +02:00