Commit Graph
284 Commits
Author SHA1 Message Date
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
sysopsandClaude Sonnet 4.6 1c52181e75 docs(PROJ-50): Tech Design für DSGVO-Löschersuchen für Mail-Inhalte
Architektur-Entwurf: neue dsgvo_requests-Tabelle, Admin-Workflow "DSGVO-Anfragen"
(Antrag -> Suche -> retain_until-Prüfung -> Ablehnung/Löschbar -> Export/Löschung),
Erweiterung des Manticore-Index um cc_addr/bcc_addr (inkl. Reindex-Hinweis). Status
auf In Progress gesetzt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 21:41:29 +02:00
sysopsandClaude Sonnet 4.6 a87d2c80fa docs(PROJ-51): Status auf Deployed setzen
PROJ-51 (Aufbewahrungsfristen nach Dokumentenart, inkl. minimaler PROJ-43-Basis)
ist auf Test (132) und Produktion (131) deployed und verifiziert.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 21:12:28 +02:00
sysopsandClaude Sonnet 4.6 7ac0391205 fix(PROJ-51): retain_until_source nicht für Endbenutzer, WARN-Status in CLI
- search_handlers.go: retain_until_source wird nur noch an Rollen != user
  ausgegeben, um interne Archivierungsregel-IDs nicht an normale
  Endbenutzer zu exponieren
- cmd_status.go: archivmail status zeigt [WARN] statt [OK] wenn Detail
  mit "WARNUNG" beginnt (z.B. PROJ-51 Retention-Check); Exit-Code/r.OK
  bleibt unverändert

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 21:05:07 +02:00
sysops 507dee6431 feat(PROJ-51): Aufbewahrungsfristen nach Dokumentenart (Retention-Kategorien)
Fuehrt archiving_rules ein (PROJ-43-Basis: Tabelle + CRUD-API + Admin-UI) und
erweitert die Retention-Logik (PROJ-34) um Regel-basierte Fristen, eine
globale Mindestfrist (min_retention_days) sowie Nachvollziehbarkeit der
Frist-Quelle (retain_until_source) in API und Mail-Detailansicht.
2026-06-13 20:48:16 +02:00
sysopsandClaude Sonnet 4.6 7c08ebe1b7 docs(PROJ-51): Tech Design für Retention-Kategorien (inkl. minimaler PROJ-43-Basis)
Architektur-Entwurf: archiving_rules-Tabelle (minimale PROJ-43-Basis) + CRUD-API +
Regel-Verwaltung im Admin-Bereich, erweitert um retention_days pro Regel und globale
Mindest-Aufbewahrungsfrist (min_retention_days). Status auf In Progress gesetzt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 20:19:15 +02:00
sysopsandClaude Sonnet 4.6 e1ed4e521e chore(PROJ-49): Status auf Deployed setzen
Erfolgreich auf Test (192.168.1.132) und Produktion (192.168.1.131)
ausgerollt und verifiziert.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 20:11:40 +02:00
sysopsandClaude Sonnet 4.6 46096db802 feat(PROJ-49): Verschlüsselungspflicht at-rest sichtbar machen (Healthcheck & Warnung)
storage.loadKey() startet bei fehlendem/unlesbarem/ungültigem Keyfile
weiterhin unverschlüsselt (kein Hard-Fail), aber:
- einmalige WARN-Logzeile beim Start mit konkretem Grund
- neuer Healthcheck-Prüfpunkt "Encryption" in archivmail status
- Dashboard-API liefert encryption.enabled
- README: GoBD-Hinweis zu storage.keyfile

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 20:01:38 +02:00
sysopsandClaude Sonnet 4.6 dc9e11fc9f chore(PROJ-48): Status auf Deployed setzen
Erfolgreich auf Test (192.168.1.132) und Produktion (192.168.1.131)
ausgerollt und verifiziert.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 19:55:00 +02:00
sysopsandClaude Sonnet 4.6 7e4175923f feat(PROJ-48): Audit-Log Unveränderbarkeit (Trigger, append-only Logfile, Healthcheck)
DB-Trigger audit_log_immutable verhindert UPDATE/DELETE auf audit_log,
zusätzliches append-only JSON-Lines-Logfile (audit.log_path) als
tamper-evident Backup, neuer Healthcheck-Prüfpunkt in archivmail status.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 19:44:07 +02:00
sysopsandClaude Sonnet 4.6 cca27c663a feat: mobile Responsiveness für Suche und Mail-Detailansicht
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 13:18:19 +02:00
sysops bc82854165 feat: archivmail status CLI mit Healthcheck für PostgreSQL, Manticore und Storage
Prüft DB-Erreichbarkeit + Mail-Statistiken, Manticore-Verbindung/Version
und Storage (Keyfile, Pfad, freier Speicherplatz). --json für maschinenlesbare Ausgabe.
2026-06-13 00:01:40 +02:00
sysops 0ecde0c1ef feat(cli): archivmail update — Wrapper für update.sh
Statt update.sh manuell zu suchen/laden kann jetzt
`archivmail update` (als root) ausgeführt werden. Nutzt
/opt/archivmail/update.sh falls vorhanden, sonst Download von Gitea.
2026-06-12 23:45:15 +02:00
sysops 501ee8f7ea fix(sec): Cross-Tenant-IDOR bei POP3-Konten schließen
Gleiches Muster wie bei IMAP (730099d): domain_admin konnte POP3-Konten
fremder Tenants auflisten, löschen und Importe/Progress fremder Tenants
ansehen, da pop3_accounts keine tenant_id hatte und Store.List() für
Admins ungefiltert alle Konten lieferte.

- pop3_accounts: neue Spalte tenant_id (ALTER TABLE ADD COLUMN IF NOT EXISTS)
- Store.List() filtert nach tenant_id, außer für superadmin
- Store.Create() setzt tenant_id beim Anlegen
- delete/start-import/progress prüfen zusätzlich tenantAccessAllowed()
2026-06-12 23:31:56 +02:00
sysops 730099d2aa fix(sec): Cross-Tenant-IDOR bei IMAP-Konten schließen
domain_admin sah und konnte IMAP-Konten (inkl. Credentials) fremder
Tenants auflisten, löschen, synchronisieren und umkonfigurieren, da
Store.List() für Admins ungefiltert alle Konten lieferte und die
Einzelhandler nur den Owner, nicht den Tenant prüften.

- Store.List() filtert jetzt nach tenant_id, außer für superadmin
- Store.Create() setzt tenant_id beim Anlegen
- Alle Einzelhandler (delete/start-import/progress/sync/update)
  prüfen zusätzlich tenantAccessAllowed()
2026-06-12 23:26:31 +02:00
sysopsandClaude Sonnet 4.6 d07e65021f fix(tenants): NULL-Scan-Fehler in tenantstore.List() beheben
ldap_url kommt via LEFT JOIN tenant_ldap und ist NULL für Mandanten
ohne LDAP-Konfiguration. Scan in *string schlug fehl ("cannot scan
NULL into *string") und ließ GET /api/admin/quotas mit 500 fehlschlagen
("Quota-Daten konnten nicht geladen werden").

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 22:38:28 +02:00
sysopsandClaude Sonnet 4.6 f82e3eb907 feat: Admin-/Auditor-Login-Link auf Startseite
Permanenter Link zur Admin-Login-Seite unterhalb der bestehenden
Links (Passwort vergessen / Registrieren), statt nur als Hinweis
nach einem fehlgeschlagenen Admin-Login-Versuch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 22:08:21 +02:00
sysopsandClaude Sonnet 4.6 a3bab16f07 fix(imap): IMAP/POP3-Import in korrekten Tenant-Index schreiben
IMAP- und POP3-Importer haben Mails immer nur in emails_global
indexiert (TenantID nie gesetzt, idxMgr.Global() statt
ForTenant(tenantID)). Dadurch fehlten neue Mails ab dem letzten
Server-Neustart im Tenant-Index (Suche zeigte veraltete Ergebnisse).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 21:15:10 +02:00
sysopsandClaude Sonnet 4.6 f32f83ff8e fix(PROJ-28): Invite-Token Pflicht bei Signup — TOCTOU + Enumeration-Leak schließen
- Signup ohne Invite-Token gibt 400 zurück (war: optional)
- Use() statt Peek() vor User-Erstellung: verhindert TOCTOU bei parallelen
  Requests mit demselben Token und Enumeration via "Token noch gültig?"
- invite_used Audit-Eintrag ergänzt
- Doppeltes IsConfigured()-Check entfernt
- Frontend: ohne ?invite= im URL wird Formular nicht gerendert

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 18:20:07 +02:00
sysopsandClaude Sonnet 4.6 15a5da33fd feat(PROJ-13): OpenAPI 3.0 Spec + GET /api/v1/docs Endpoint
Serves the static OpenAPI YAML via go:embed. Completes the last
open acceptance criterion for PROJ-13. PROJ-44 marked Deployed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 18:03:58 +02:00
sysopsandClaude Sonnet 4.6 fa9f77782c fix(sec): Authorization-Bypässe und Path-Traversal schließen, Xapian-Doku bereinigen
- SEC: requireMailAccess auf GET /api/threads/{threadID} — superadmin/domain_admin konnten Mail-Metadaten lesen
- SEC: requireMailAccess auf POST /api/export/ediscovery — superadmin/domain_admin konnten bis zu 10k EML exportieren
- SEC: V1-API user-role Keys müssen 'contact=' angeben — verhindert vollständige Tenant-Enumeration
- SEC: Domain-Regex-Validierung in handleCertACME vor filepath.Join und certbot-Aufruf
- docs: README und config.test.yml auf Manticore Search aktualisiert (kein Xapian mehr)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 23:55:31 +02:00
sysopsandClaude Sonnet 4.6 8d950b48f7 fix(mailparser): Deutsche Wochentagsabkürzungen im Date-Header parsen
PMG mit German-Locale erzeugt "So, 24 Aug 2025 00:05:17 +0200" statt
"Sun, ..." — Go's net/mail und alle bisherigen Fallbacks scheitern daran.
Fix: Wochentag-Präfix (≤3 Zeichen vor dem ersten Komma) abschneiden
und erneut mit den numerischen Offset-Formaten parsen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 23:46:13 +02:00
sysopsandClaude Sonnet 4.6 a1c4e59fff fix: Date-Parsing-Fallback für nicht-standard MTA-Datumsformate
mailparser: weitere Layouts (Timezone +02:00 mit Doppelpunkt, ohne Sekunden)
storage: GetReceivedAts() für Batch-Lookup von received_at
search_handlers: received_at als Fallback wenn pm.Date.IsZero()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 23:36:18 +02:00
sysopsandClaude Sonnet 4.6 1f7e02dc53 fix(build): turbopack.root explizit setzen, verhindert Warning bei multiplen lockfiles
Next.js/Turbopack kann sich den Workspace-Root falsch ableiten wenn
im Parent-Verzeichnis des Build-Dirs eine package-lock.json liegt
(z.B. durch alten Deploy-Stand). __dirname als expliziter Root behebt
die Warnung dauerhaft.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 20:46:46 +02:00
sysopsandClaude Sonnet 4.6 33539d281a fix(ui): Uhrzeit in Datumsspalte der Suchergebnisse anzeigen
toLocaleDateString → toLocaleString mit dateStyle+timeStyle, zeigt
jetzt z.B. "11.05.2026, 00:05" statt nur "11.05.2026".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 20:38:54 +02:00
sysopsandClaude Sonnet 4.6 726dd78f3a fix(PROJ-4): SMTP tenant routing: header fallback for BCC journaling
resolveTenant() now tries RCPT TO first, then falls back to parsing
To/Cc/From headers. Needed because BCC-journaled mails arrive with
RCPT TO = the archive's own BCC address, not the real recipient's domain.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 14:56:32 +02:00
sysopsandClaude Sonnet 4.6 799c828548 feat(PROJ-45): IMAP per-folder UID-tracking, UIDVALIDITY-check + reindex OCR protection
- scheduler.go: BUG-1 fix — preserve stored uid_validity when server returns 0
- scheduler.go: BUG-2 fix — replace inline switch with DecideResync() call
- scheduler.go: SetAuditLogger wired; imap_uidvalidity_reset audit event
- cmd_reindex.go: read existing attachment_text before IndexSync to prevent
  Manticore REPLACE INTO from wiping OCR text written by the OCR worker

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 14:56:28 +02:00
sysopsandClaude Sonnet 4.6 4151b6f8c5 feat(PROJ-45): IMAP Per-Folder UID-Tracking + UIDVALIDITY-Check
- FolderState: GetFolderState, UpsertFolderState, ListFolderStates, DecideResync
- syncFolder nutzt per-folder UID-Tracking statt globalem highest_uid
- UIDVALIDITY-Check loest automatisch Full-Resync aus
- imap_folder_state Tabelle in initSchema (CREATE TABLE IF NOT EXISTS)
- SetAuditLogger in main.go verdrahtet

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 10:49:14 +02:00