341 Commits
Author SHA1 Message Date
patrickandClaude Sonnet 5.5 4eb300c252 feat(PROJ-94): Postfach-Zuordnung pro IMAP-Konto, imap-link
Tabelle imap_account_mails, Importer schreibt die Zuordnung auch bei Duplikaten,
Zugriffsregel und Index-Tokens nutzen sie, archivmail imap-link befüllt den
Bestand (Trockenlauf Standard, --apply schreibt nur die Zuordnung).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-29 14:38:27 +01:00
patrickandClaude Sonnet 5.5 2fcf85ed1e docs(PROJ-87,PROJ-90,PROJ-91,PROJ-92,PROJ-93): Status In Review
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-29 14:24:33 +01:00
patrickandClaude Sonnet 5.5 0501118bcd feat(PROJ-92,PROJ-93): Weiterleitung in Liste/Detail anzeigen, imap-verify Vollständigkeitsprüfung
PROJ-92: forwarded_via in Suchtreffern, Detail und Threads; Badge im Portal.
PROJ-93: archivmail imap-verify gleicht Message-IDs im IMAP-Postfach mit dem
Archiv ab (strikt lesend, nur Zahlen und Ordner:UID).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-29 14:20:34 +01:00
patrickandClaude Sonnet 5.5 b15bab355b feat(PROJ-91): Envelope-Absender (Return-Path) durchsuchbar machen
Parser liest oberstes Return-Path, Index-Spalte env_from, Absender-Filter
matcht from_addr oder env_from. Keine Zugriffswirkung. Reindex für Bestand nötig.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-29 13:48:36 +01:00
patrickandClaude Sonnet 5.5 5248a177ce feat(PROJ-87,PROJ-90): Zusatzadressen pro User und Sichtbarkeit aller Mails eigener IMAP-Konten
Rolle user sieht zusätzlich Mails mit Zusatzadressen (PROJ-87) und alle Mails
von IMAP-Konten, deren owner dem User im selben Tenant entspricht (PROJ-90).
Liste, Nachprüfung und Detailzugriff nutzen dieselbe Regel (mailAccess).
Index: Token imapacct<id> in rcpt_addr, Reindex für Bestandsmails nötig.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-29 12:10:57 +01:00
patrickandClaude Sonnet 5.5 f19608dac9 docs(PROJ-89): Status In Review, Deployment-Notizen
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 00:56:11 +02:00
patrickandClaude Sonnet 5.5 94f14896e8 docs(PROJ-87): Add technical design for Zusatzadressen pro User
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 00:46:21 +02:00
patrickandClaude Sonnet 5.5 833ff55e1d feat(PROJ-89): BCC auslesen, indexieren, in Sichtbarkeitsprüfung und Portal anzeigen
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 00:46:21 +02:00
patrickandClaude Sonnet 5.5 1d8c063a4f fix(PROJ-88): IMAP-Cursor nicht über ungespeicherte Mails, Reindex und Zugriff über email_refs-Tenants
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 12:48:52 +02:00
patrickandClaude Sonnet 5.5 e39c1f3b60 fix(PROJ-88): Mail-Sichtbarkeit für Rolle user bei Zustellung über Delivered-To + exakter Adress-Match
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 14:44:18 +02:00
patrickandClaude Sonnet 5.5 ca54b72a96 feat(PROJ-87): Add feature specification for Zusatzadressen pro User
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 14:10:46 +02:00
sysopsandClaude Sonnet 5 ffdfa585cc fix(PROJ-86): defensive UID-Filterung gegen kaputten IMAP-Server (Sync-Loop)
q.sysops.de (Konto patrick@sysops.de) beantwortet "UID SEARCH UID N:*" auf
Mailboxen mit weniger Nachrichten als N fehlerhaft und liefert die letzte
existierende UID statt eines leeren Ergebnisses zurück (verifiziert per
Debug-Client: "UID SEARCH UID 22:*" auf 21-Nachrichten-Mailbox -> [21]).
Ohne Filterung wurde dieselbe UID bei jedem 5-Minuten-Sync erneut als
"neu" behandelt und re-indexiert - dabei driftete auch date_ts bei
Mails ohne Date-Header ständig auf "jetzt". Server-Antwort wird jetzt
client-seitig re-gefiltert, nur UIDs >= angefragtem Minimum zählen als neu.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UPFC6Jk2ke1Pq9XcuVGP1R
2026-09-01 15:01:23 +02:00
sysopsandClaude Sonnet 5 160b28099e fix(PROJ-86): Date-Fallback auf Received-Header-Kette wenn Date-Header fehlt
Alte Bulk-importierte Archive (kein Date:-Header, nur Received:-Zeilen)
bekamen bislang das Import-Datum (received_at) als date_ts zugewiesen -
storage.Save() ignoriert den pm.Date-Parameter komplett und setzt
received_at immer auf NOW(). Jetzt wird bei fehlendem/unparsbarem
Date:-Header die Received:-Kette geparst (origin-nächster Hop zuerst,
via net/mail.Header["Received"] rückwärts iteriert) - liefert das
tatsächliche Mail-Datum statt des Import-Zeitpunkts.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UPFC6Jk2ke1Pq9XcuVGP1R
2026-09-01 14:45:51 +02:00
sysopsandClaude Sonnet 5 e1f39ce56f fix(PROJ-86): stale sync_running-Flag beim Scheduler-Start automatisch bereinigen
Ein IMAP-Konto blieb wegen sync_running=true seit 2026-07-05 (Prozess-Crash
vor dem defer in runSyncWithRetry) für den Scheduler auf ewig "beschäftigt" -
checkAccounts überspringt Konten mit SyncRunning=true. Neue Store-Methode
ClearStaleSyncRunning() wird jetzt bei jedem Scheduler.Start() aufgerufen und
setzt verwaiste Flags zurück, bevor der Scheduler-Loop startet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UPFC6Jk2ke1Pq9XcuVGP1R
2026-09-01 13:56:48 +02:00
sysopsandClaude Sonnet 5 25865423f9 docs: Agent-Definitionen bereinigt (192.168.1.131 raus) + Dual-Source-Falle dokumentiert
192.168.1.131 gehört seit 2026-09-01 nicht mehr zum archivmail-Projekt (User-Bestätigung).
Alle Referenzen in CLAUDE.md und Agent-Defs auf den verbleibenden Server 192.168.1.132
korrigiert (Test/Prod-Paar existiert nicht mehr).

Zusätzlich Erkenntnisse aus PROJ-86-Audit (Subagenten db-migrator + mailarchiv-architect)
in die Agent-Defs eingearbeitet: emails.tenant_id vs. email_refs Dual-Source-Falle,
MailDocument-Fan-out-Drift-Muster, emails_global-Mirror-Pflicht, --tenant-Reindex-Lücke.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UPFC6Jk2ke1Pq9XcuVGP1R
2026-09-01 13:56:41 +02:00
sysopsandClaude Sonnet 5 c2b92a9a30 chore: npm audit fix — nanoid High-Vuln (infinite loop bei size=0)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UPFC6Jk2ke1Pq9XcuVGP1R
2026-09-01 12:27:40 +02:00
sysopsandClaude Sonnet 5 26c0e04c75 fix(PROJ-86): Manticore-Index-Drift (emails_global) + Datumssortierung bei fehlendem Date-Header
emails_global bekam nie Tenant-Mails gespiegelt, Superadmin-Suche sah nur
~30% aller Mails. Zusätzlich sanken Mails ohne gültigen Date-Header
(date_ts=0) beim datumssortierten Listing ans Ende aller Ergebnisse und
waren dadurch praktisch unauffindbar ("GUI zeigt neue Mails nicht") -
Import/Indexierung liefen technisch korrekt, nur Sortierung/Spiegelung
waren kaputt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UPFC6Jk2ke1Pq9XcuVGP1R
2026-09-01 12:17:09 +02:00
sysopsandClaude Sonnet 5 7727ad5cdf docs(PROJ-84,PROJ-85): Status auf Deployed - Backfill/Reindex auf 131+132 verifiziert
PROJ-84: 131 hatte 0 Kandidaten, 132 541/541 korrigiert (bereits
vorher bestätigt). PROJ-85: --apply + reindex auf 132 (54/54) und
131 (Produktiv) ohne Fehler durchgelaufen, User-Gegenprobe bestätigt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WapWkrQusDuBMhaN8WyuXB
2026-08-06 22:38:44 +02:00
sysopsandClaude Sonnet 5 8f46d688a8 feat(PROJ-85): Fix undeklarierte 8-Bit-Zeichen in Header/Body ohne Encoded-Word
Getrennt von PROJ-84: Header (v.a. Subject) mit rohen 8-Bit-Bytes ohne
RFC-2047-Encoded-Word-Syntax wurden nicht auf tatsächliches Charset
geprüft, landeten als ungültiges UTF-8 in emails.subject und Manticore.
Gleiche Lücke bei decodeCharset() für den Body ohne verwertbaren
Content-Type.

RepairUTF8/RepairUTF8Bytes (charset_repair.go): bytegenaue Reparatur,
gültiges UTF-8 bleibt Identität, nur ungültige Byte-Sequenzen fallen
auf Windows-1252 zurück. Attachment.Data bewusst ausgenommen (bleibt
byte-exakt für Downloads). fix-subjects-Kommando erkennt jetzt beide
Fälle (HasEncodedWord || NeedsCharsetRepair).

Verifiziert auf 192.168.1.132: 54 zusätzliche Subject-Fälle, 219
Body-Fälle behoben (bodyInvalidUTF8 219 -> 0). --apply noch nicht
ausgeführt, Body-Korrektur braucht zusätzlich reindex.

Die ursprünglich gemeldete Amazon-Mail bleibt bewusst unverändert:
Encoding-Fehler kam bereits so vom Absender (=3F statt =DC im
Original-Encoded-Word), GoBD verbietet nachträgliche Korrektur
archivierter Originalinhalte.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WapWkrQusDuBMhaN8WyuXB
2026-08-06 20:46:58 +02:00
sysopsandClaude Sonnet 5 786d8341f4 chore: Versionierung an Feature-Fortschritt koppeln (1.0.0 -> 1.8.0)
package.json-Version stand seit Projektstart unverändert auf 1.0.0.
Neues Schema in CLAUDE.md dokumentiert: Minor = aktive Features aus
features/INDEX.md / 10, abgerundet. 82 aktive Features -> 1.8.0.
Veralteten "nächste freie PROJ-44"-Hinweis auf dynamischen Verweis
auf INDEX.md korrigiert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WapWkrQusDuBMhaN8WyuXB
2026-08-06 20:08:56 +02:00
sysopsandClaude Sonnet 5 1dfd8c18ac feat(PROJ-84): fix-subjects CLI-Backfill für kaputte MIME-Header-Betreffs
CLI-Subkommando "archivmail fix-subjects" korrigiert Bestandsmails mit
undekodiertem RFC-2047-Encoded-Word im Betreff (Folge des Fixes in
31d7113). Dry-Run per Default, echte Änderung nur mit --apply.

Original-EML im Storage bleibt unangetastet - nur Postgres emails.subject
wird korrigiert, danach Manticore-Reindex inkl. Erhalt von OCR-Text.
Jeder Lauf erzeugt einen Audit-Log-Eintrag (metadata_backfill).

Verifiziert auf 192.168.1.132: 543 Kandidaten, 541 reparierbar, 2 zu
Recht übersprungen (RFC-2047-Verletzung im Original). --apply noch
nicht ausgeführt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WapWkrQusDuBMhaN8WyuXB
2026-08-06 19:58:41 +02:00
sysopsandClaude Sonnet 5 31d71138c9 fix: MIME-Encoded-Word-Betreffs mit Windows-1252 werden nicht dekodiert
decodeMIMEHeader() nutzte mime.WordDecoder ohne CharsetReader. Go kennt
dort nativ nur UTF-8/US-ASCII/ISO-8859-1, alles andere (z.B.
Windows-1252) ließ DecodeHeader() scheitern, Betreff blieb roh
("=?Windows-1252?Q?...?="). CharsetReader ergänzt, nutzt dieselbe
htmlindex-Logik wie decodeCharset() für den Body (vgl. PROJ-57).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WapWkrQusDuBMhaN8WyuXB
2026-08-06 19:22:19 +02:00
sysopsandClaude Sonnet 5 2aad899dfc docs(PROJ-81): Pflegehinweis für pdfjs-dist in Spec ergänzt
Seit dem BUG-81-3-Fix läuft PDF-Parsing über pdfjs-dist im App-Origin
statt in einer Browser-Sandbox. Sicherheitsniveau hängt damit an der
Code-Qualität der Dependency - Update-Pflicht bei Security-Releases
dokumentiert, nicht erst beim nächsten großen Dependency-Sweep.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WapWkrQusDuBMhaN8WyuXB
2026-08-06 19:19:43 +02:00
sysopsandClaude Sonnet 5 1ad1132006 fix(PROJ-81): BUG-81-3 - PDF-Vorschau via pdf.js statt sandboxed iframe
Chromium/Brave zeigte leeren PDF-Bereich (PDFium/MimeHandlerView
verweigert Rendering in sandbox="allow-scripts" ohne allow-same-origin,
Firefox war nicht betroffen). allow-same-origin nachzurüsten kam nicht
infrage: Blob-URLs erben den App-Origin, die Kombination hätte die
Sandbox faktisch aufgehoben (PROJ-61-Kontext).

Neu: PdfCanvasPreview.tsx rendert PDF via pdf.js selbst nach <canvas>,
kein iframe/eingebettetes Dokument mehr nötig. Parsing im Worker, kein
PDF-eigenes JavaScript, kein Text-/Annotationslayer im DOM. Seitenlimit
30, eigener Fehlerzweig für passwortgeschützte/beschädigte PDFs.

Neue Dependency pdfjs-dist@6.2.108 - Restrisiko: PDF-Parsing läuft
jetzt im App-Origin statt im Browser-Viewer-Prozess.

Noch nicht im Browser verifiziert, Status bleibt In Review.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WapWkrQusDuBMhaN8WyuXB
2026-08-06 19:14:02 +02:00
sysopsandClaude Sonnet 5 ca693ded1b docs(PROJ-83): Ticket für Audit-Logging bei Anhang-Abrufen angelegt
Nebenfund aus PROJ-81-QA: handleGetAttachment protokolliert Zugriffe
nicht im Audit-Log. Nicht blockierend für PROJ-81-Deploy — Vorschau
ändert das gespeicherte Original nicht, nur die Zugriffs-Nachvollzieh-
barkeit fehlt (GoBD/DSGVO Art. 30).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WapWkrQusDuBMhaN8WyuXB
2026-08-06 18:30:25 +02:00
sysopsandClaude Sonnet 5 bd427a944e fix(PROJ-81): BUG-81-5/-6 - AC1-Wortlaut angeglichen, Content-Type-Fallback für endungslose Anhänge
- AC1-Text auf tatsächlichen Vorschau-Button-Ansatz umformuliert
- resolveMimeType(): Server-content_type nur als Hinweis bei fehlender
  Dateiendung, kann vorhandene Endung nicht überstimmen; Rendering bleibt
  strikt auf clientseitige MIME-Whitelist beschränkt (Security-Modell
  unverändert, kein SVG/HTML)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WapWkrQusDuBMhaN8WyuXB
2026-08-06 18:28:12 +02:00
sysopsandClaude Sonnet 5 0a02bd7112 feat(PROJ-80,PROJ-81): Dark Mode Vervollständigung + Anhang-Online-Vorschau
- PROJ-80: hartkodierte Farben in ModulesTab/TenantsTab/TenantLDAPTab durch
  Theme-Tokens ersetzt, Mail-HTML-Container bewusst hell isoliert, Print
  im Dark Mode auf lesbare (nicht farbidentische) Ausgabe umgestellt
- PROJ-81: neuer AttachmentPreviewDialog für PDF/Bild-Anhänge in /mail/[id],
  MIME-Whitelist ohne SVG, sandboxed iframe ohne allow-same-origin,
  Auto-Retry-Schleife bei Fehlern behoben
- PROJ-82 angelegt: Print-Farbparität als Folge-Ticket (BUG-80-1-Rest)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WapWkrQusDuBMhaN8WyuXB
2026-08-06 18:00:41 +02:00
sysops a1bf581fdd docs: DEVLOG aktualisieren, doppelte Session-Stubs bereinigt
Duplizierte "Keine Commits"-Eintraege der heutigen Session (Hook lief
mehrfach) durch einen konsolidierten Eintrag mit den echten PROJ-79-
Commits ersetzt.
2026-08-06 14:45:45 +02:00
sysops 4d25b11413 feat(PROJ-79): typescript 5 -> 6.0.3, PROJ-79 abgeschlossen
TS 7.0.2 getestet und verworfen: typescript-eslint@8.66.0 wirft explizit
"does not support TS 7.0" (Peer-Range <6.1.0, siehe typescript-eslint#10940).
tsc/lint/build auf 6.0.3 gruen.

Alle 5 Teilschritte von PROJ-79 bearbeitet - lucide-react, tailwindcss v4
+ tailwind-merge v3 und @types/node abgeschlossen, eslint 10 und
typescript 7 an Oekosystem-Blockern (Plugin-Support fehlt) dokumentiert
zurueckgestellt. Status auf Deployed.
2026-08-06 14:34:53 +02:00
sysops 61c004c2ac docs(PROJ-79): tailwindcss-v4-Deploy auf 132+131 dokumentiert 2026-08-06 14:32:24 +02:00
sysops 824b24f569 feat(PROJ-79): tailwindcss v3 -> v4 + tailwind-merge v3 Upgrade
Offizielles @tailwindcss/upgrade-Tool durchgelaufen: tailwind.config.ts
entfernt, Theme nach globals.css als @theme-Block (CSS-first-Config),
PostCSS auf @tailwindcss/postcss umgestellt. tailwind-merge im selben
Schritt auf v3 (Pflicht-Kopplung an Tailwind v4).

Codemod-Bug korrigiert: variant="outline" (Prop-Wert) wurde faelschlich
als CSS-Klasse zu "outline-solid" umbenannt in 4 Call-Sites - zurueckgesetzt.

Neue Lint-Regel (no-restricted-syntax) gegen *-opacity-* Utilities, die
in v4 nicht mehr existieren und von tailwind-merge v3 lautlos verschluckt
wuerden statt einen Fehler zu werfen.

tsc/lint/build gruen. Visueller Regressionstest offen (kein Browser-Tool
in dieser Session) - folgt auf 132 vor 131-Deploy.
2026-08-06 12:38:51 +02:00
sysops fa8c5dd87a chore(PROJ-79): @types/node Patch-Update auf ^20.19.43
Node auf 131/132 verifiziert (v20.19.2, identisch) - kein Major-Sprung
auf ^26, Typen sollen zur echten Server-Node-Version passen.
2026-08-06 12:23:19 +02:00
sysopsandClaude Sonnet 5 5c3d38ae65 fix(security): Tracking-Pixel-Blocker lässt Backslash-Varianten von https:// durch
EXTERNAL_URL_RE verlangte zwei Forward-Slashes, aber der WHATWG-URL-Parser
akzeptiert für http(s) auch Backslash als Authority-Slash: "https:/\/evil.com"
und "https:\\evil.com" lösen im Browser identisch zu "https://evil.com" auf,
wurden vom PROJ-76-Fix aber nicht erkannt. Ein Tracking-Pixel mit dieser
Schreibweise hätte trotz aktivierter Blockierung geladen und dem Absender
eine Lesebestätigung samt IP verraten.

Gefunden durch Security-Review der heutigen Session-Commits.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019j28kGcaJAhBnrYX34hGdt
2026-08-05 21:45:20 +02:00
sysopsandClaude Sonnet 5 edf6f430df fix: Cert-Renewal-Handler kann /etc/ssl/archivmail nicht beschreiben (systemd-Sandbox)
ProtectSystem=strict + ReadOnlyPaths=.../etc/ssl/archivmail blockierte den
Cert-Handler (internal/api/cert_handlers.go) beim Erstellen/Erneuern von
Zertifikaten mit "read-only file system" — Fehler kam vom systemd-Namespace,
nicht von einem echten ro-Mount oder Owner-Problem. SSL_DIR gehört in
ReadWritePaths statt ReadOnlyPaths, da die Anwendung dort aktiv schreibt.

Fix im Unit-Generator in update.sh, nicht nur manuell am Server, da die
Unit bei jedem Deploy neu geschrieben wird.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019j28kGcaJAhBnrYX34hGdt
2026-08-05 21:31:14 +02:00
sysopsandClaude Sonnet 5 d1b4497893 fix(PROJ-79): next lint kaputt seit Next-16-Upgrade repariert + 30 Findings gefixt
npm run lint rief next lint auf, das es in Next.js 16 nicht mehr gibt —
seit dem Next-16-Upgrade lief effektiv gar kein Lint mehr. Umgestellt auf
eslint . mit Flat-Config (eslint.config.mjs statt .eslintrc.json). Der
dadurch wieder sichtbare Lint-Lauf zeigte 30 Findings (25 Fehler,
5 Warnungen), alle gefixt:

- 19x react-hooks/set-state-in-effect: Loading-States wo möglich als
  echte Ableitung statt eigenem Effect-State (use-mobile.tsx komplett auf
  useSyncExternalStore umgebaut), sonst async-Wrapper mit Cancel-Guard um
  bestehende Loader — Timing/Ladeanzeige unverändert.
- react-hooks/refs (useSearch.ts): Ref-Schreibzugriff aus dem Render in
  einen Effect verschoben.
- 4x no-html-link-for-pages: <a href> durch next/link ersetzt in
  admin/login, forgot-password, signup.
- Rest (exhaustive-deps, no-img-element, unused disable) einzeln gefixt.
- 4 bewusst belassene disable-Kommentare mit Begründung (shadcn/ui-Datei,
  QR-Code-data-URL, Full-Reload nach Auth laut Projektregel).

eslint-Major-Upgrade auf 10 selbst bleibt blockiert: eslint-plugin-react/
jsx-a11y/import unterstützen ESLint 10 in ihrer aktuellen Latest-Version
noch nicht (Crash beim Laden), siehe Feature-Spec PROJ-79.

Verifiziert auf 132 (Build-Sandbox, kein Live-Deploy): npm ci/tsc/lint/
build grün, 8 Kern-Routen per Standalone-Server auf HTTP 200 geprüft.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019j28kGcaJAhBnrYX34hGdt
2026-08-05 21:14:17 +02:00
sysopsandClaude Sonnet 5 a2e45b950b chore(PROJ-79): lucide-react Major-Upgrade + npm audit fix + Deploy-Warn-Gate
lucide-react 0.562.0 auf 1.28.0 (kein Codeumbau nötig, alle genutzten
Icon-Namen kanonisch unverändert). npm audit fix behebt alle 6 gefundenen
Vulnerabilities ohne Breaking Change (next minor 16.2.9->16.3.0 im
bestehenden ^16.1.1-Range). caniuse-lite/Browserslist-DB aktualisiert
(war 8 Monate alt).

update.sh: npm audit --audit-level=high läuft jetzt als nicht-blockierendes
Warn-Gate nach npm ci. Bewusst kein Auto-Fix während des laufenden Deploys
— ein npm audit fix live auf dem Produktivsystem könnte unbemerkt Versionen
ändern, ohne vorherige Verifikation. Bei Fund wird gewarnt und auf lokales
audit fix + Test + Commit verwiesen.

Restliche PROJ-79-Schritte (eslint, @types/node, tailwindcss v4 +
tailwind-merge v3, typescript) bleiben offen, siehe Feature-Spec.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019j28kGcaJAhBnrYX34hGdt
2026-08-05 17:37:40 +02:00
sysopsandClaude Sonnet 5 16bf38876f perf(PROJ-78): Suchfeld-Debounce + stabile Callbacks gegen Re-Render-Spam
Jeder Tastendruck im Suchfeld setzte bisher sofort State in SearchPage,
was über eine instabile doSearch-Referenz einen vollen Re-Render der
Ergebnistabelle auslöste (bei page_size 100: 100 Zeilen inkl.
sanitizeSnippet pro Tastendruck). Suchbegriff liegt jetzt lokal in der
Filterbar und wird debounced (300ms) nach oben propagiert; doSearch liest
Filterwerte aus einem Ref statt sie als Dependencies zu führen und bleibt
dadurch referenzstabil; SearchResultsTable ist jetzt memoisiert.

Enter-Verhalten bleibt sofort (Debounce wird vor dem Submit geflusht),
übrige Filter unverändert direkt-kontrolliert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019j28kGcaJAhBnrYX34hGdt
2026-08-05 15:11:28 +02:00
sysopsandClaude Sonnet 5 e59b11743a perf(PROJ-77): Admin-Tabs per next/dynamic laden statt statisch importieren
18 Admin-Tab-Komponenten wurden bisher alle statisch in src/app/admin/page.tsx
importiert, unabhängig davon welcher Tab tatsächlich geöffnet wird. Umstellung
auf next/dynamic mit gemeinsamem TabSkeleton-Loading-State reduziert das
initiale JS-Bundle der Admin-Route um 204,9 KB (-19,8%). Initial aktiver Tab
bleibt weiterhin serverseitig vorgerendert (ssr: true), kein Skeleton-Flash
beim ersten Laden.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019j28kGcaJAhBnrYX34hGdt
2026-08-05 15:05:24 +02:00
sysopsandClaude Sonnet 5 209fdeb8ad fix(PROJ-76): Mail-HTML-Sanitizing schließt CSS-url()/link/background/srcset ein
blockExternalSrcs() filterte bisher nur src= bei img/video/audio/source und
ließ Tracking-Pixel via <link href>, background=, CSS url() (Style-Block und
inline) sowie srcset durch — DSGVO-relevantes Read-Tracking trotz aktivierter
Blockierung. Zusätzlich deckt die neue Erkennung protokollrelative URLs
(//host/px.gif) ab, die die alte https?:-Prüfung durchließ.

data:/cid:-URIs bleiben unangetastet, <a href> weiterhin klickbar. CSP-Header
als robustere Ergänzung (Blocklist-Regex bleibt grundsätzlich umgehbar) folgt
separat mit dem firewall-security-Skill.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019j28kGcaJAhBnrYX34hGdt
2026-08-05 15:05:16 +02:00
sysopsandClaude Sonnet 5 c75352839c perf(PROJ-75): Partial Index gegen Seq-Scan in GetUnindexedMails
Der index-pending-Cron (PROJ-58) scannte bei jedem Lauf die komplette
emails-Tabelle, weil indexed_at unindiziert war — skaliert linear mit
Archivgröße. Partial Index auf (received_at DESC) WHERE indexed_at IS NULL
verifiziert auf 192.168.1.132: Seq Scan (13.3ms, 52895 Zeilen) → Index Scan
(0.086ms).

Restlicher PROJ-75-Audit (pgxpool-Tuning, reconciliation N+1) bewusst
zurückgestellt, siehe Feature-Spec.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019j28kGcaJAhBnrYX34hGdt
2026-08-05 14:55:13 +02:00
sysopsandClaude Sonnet 5 075afa005a fix(PROJ-74): Test-/Vet-Signatur-Drift beheben, go build/vet/test wieder grün
archivmail-export nutzte noch die alte storage.New(path string)-Signatur
statt storage.Config (fehlender Keyfile/Compress hätte Rohbytes statt
Klartext-EML exportiert). Toten Self-Assignment-Code in storage.go entfernt.
Testdateien (storage, audit, api, userstore, auth) an aktuelle Signaturen
angeglichen; auth-Tests liefen bisher gegen einen SQLite-Pfad statt Postgres-
DSN und wurden auf das TEST_DATABASE_URL-Schema-Isolationsmuster der übrigen
Pakete umgestellt. api_test.go las den Login-Token noch aus dem JSON-Body
statt aus dem httpOnly-Cookie (Auth-Contract-Drift).

TestParseMissingDate an tatsächliches Verhalten angepasst: der Parser lässt
das Datum bewusst als Zero-Value, der time.Now()-Fallback sitzt in der
Storage-Schicht — damit bleibt nachvollziehbar ob ein Datum aus der Mail
stammt oder vom Archiv gesetzt wurde (GoBD).

Verifiziert auf 192.168.1.132: go build/vet/test ./... komplett grün,
kein Skip (Postgres + Manticore erreichbar).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019j28kGcaJAhBnrYX34hGdt
2026-08-05 14:07:46 +02:00
sysopsandClaude Sonnet 5 88cdc3eb3e fix(PROJ-73): Upload-Job-Status bei Panic + nil-Guards nach GetByUsername
Upload-Job bleibt bei einem Panic im Verarbeitungspfad nicht mehr auf
"running" hängen, sondern zeigt "error" mit generischer Meldung (Panic-
Rohwert nur im Server-Log, ErrMsg geht ans Frontend und könnte sonst
Mail-Inhalt-Fragmente transportieren). Zusätzlich fail-closed nil-Guards
an allen 13 GetByUsername-Aufrufstellen in internal/api/, die das
Ergebnis bisher ungeprüft dereferenzierten.

Verifiziert auf 192.168.1.132: Build und go vet fehlerfrei für die
geänderten Dateien.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019j28kGcaJAhBnrYX34hGdt
2026-08-05 13:50:36 +02:00
sysopsandClaude Sonnet 5 798cb2817c fix: Crash-Robustheit + Performance in Backend und Frontend härten
Backend: recover() in allen langlebigen Goroutinen (neues internal/safego-
Paket), MIME-Multipart-Tiefenlimit gegen Stack-Overflow, IMAP-Zeilenlängen-
und FETCH-Result-Limits gegen OOM, MBOX-Buffer-Aliasing-Bug (Datenkorruption
beim Import), ungeprüfte Type Assertions abgesichert, Data Race im
API-Key-Rate-Limiter behoben, SMTP-Session-Panic führt jetzt zu 451-Retry
statt Prozessabsturz. Performance: O(n²)-String-Concat in Mailparser und
IMAP-Parser durch strings.Builder ersetzt.

Frontend: Error Boundaries für Root und Mail-Detailansicht ergänzt (gab es
vorher nicht), zahlreiche Guards gegen nil-Slices aus dem Backend-JSON die
sonst .map()/.length-Crashes/White-Screens auslösten, defekte JSON-Antworten
in api/core.ts abgefangen, zwei React-Key-Bugs bei löschbaren Listen
korrigiert.

Verifiziert auf 192.168.1.132: Build und Tests der geänderten Pakete
fehlerfrei, keine Regressionen gegenüber vorbestehendem Stand.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019j28kGcaJAhBnrYX34hGdt
2026-08-05 13:39:00 +02:00
sysopsandClaude Sonnet 5 0fa4fad49d chore: leere DEVLOG-Sessioneinträge entfernen
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WoaHoJPLcRkzQW4MtvC9EE
2026-07-31 12:36:55 +02:00
sysopsandClaude Sonnet 5 415ac61a9b docs: DEVLOG aktualisieren
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016RmCVQZ9qtzfUtU6a7F4GR
2026-07-30 23:03:36 +02:00
sysopsandClaude Sonnet 5 5416e7d0f8 fix(agents): Deploy-Reihenfolge 132-vor-131 in Subagent-Defs + kaputtes sub-frist Frontmatter
- devops-deploy/mailarchiv-architect/db-migrator sagten teils "direkt auf 131 (Produktiv)"
  deployen/migrieren, widersprüchlich zur Test-first-Konvention (132 zuerst validieren)
- sub-frist.md hatte kaputtes Frontmatter (description = kompletter Prompt-Body dupliziert
  als Einzeiler) statt Kurzbeschreibung + Beispiele wie bei anderen Agenten — dadurch
  vermutlich nicht als regulärer subagent_type registriert
- db-migrator/devops-deploy/sub-frist bisher nie getrackt (.gitignore blockt .claude/),
  jetzt force-added wie mailarchiv-architect/manticore-admin

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016RmCVQZ9qtzfUtU6a7F4GR
2026-07-30 23:02:46 +02:00
sysops 2e952f111d docs(PROJ-72): Feature-Spec nachtragen + Audit-Log-Härtung für abgelehnte Privilege-Checks
Feature-Spec, INDEX.md und features.ts für PROJ-72 (Superadmin-Peer-Patch-Fix)
ergänzt inkl. QA-Ergebnisse. Zusätzlich: abgelehnte Privilege-Escalation-/
Tenant-Isolation-Versuche (403) werden jetzt als Success:false im Audit-Log
protokolliert (vorher nur erfolgreiche Updates) - Härtungspunkt aus QA-Runde.
2026-07-27 00:08:43 +02:00
sysops c580a7c05d fix(PROJ-72): Superadmin kann Passwort/Rolle von Superadmin-Peers nicht ändern
SEC-01 Privilegien-Check (roleLevel(target) >= roleLevel(sess)) blockte
Superadmin (höchstes Level) bei jedem Ziel-User mit gleichem Level -
inklusive anderer Superadmins. Passwort-Reset durch Superadmin schlug
dadurch fehl. Superadmin ist jetzt vom Peer-Level-Check ausgenommen,
da kein höheres Level existiert.
2026-07-26 21:50:19 +02:00
sysopsandClaude Sonnet 5 9db5eaa1e8 feat(PROJ-71): TLS-Pflicht (optional) für eingehenden SMTP-BCC-Kanal
fix: Audit-Log-Detailspalte per Tooltip statt hartem Truncate lesbar machen

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-08 11:43:18 +02:00
sysopsandClaude Sonnet 5 e221fcf63f docs(PROJ-70): Message-ID-Erhalt als Acceptance Criterion festhalten
Wichtig für PROJ-32-Duplikatserkennung. Bereits erfüllt durch 1:1-Weitergabe
der rohen RFC-2822-Bytes an AppendToMailbox() ohne Reparse.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 01:42:02 +02:00