Commit Graph
99 Commits
Author SHA1 Message Date
sysopsandClaude Sonnet 4.6 58bcfb1586 feat: Dashboard-Metriken nach Mailpiler-Vorbild (Uptime, Aktivität, Prognose)
- storage_stats.go (neu): MailActivityStats (60min/24h/7d/30d), StorageEstimateStats
- dashboard_handlers.go: Uptime (/proc/uptime), activity + estimate in System-Stats-Response
- DashboardTab: Uptime in API-Kachel, neue Kacheln "Mail-Eingang" + "Speicherprognose"
- Warnung (Badge "Knapp!") wenn Partition in <90 Tagen voll

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 10:44:02 +02:00
sysopsandClaude Sonnet 4.6 5bbf6d0ff3 feat(PROJ-34): Retention-Tab + pro-Mandant Aufbewahrungsfristen
- tenantstore: retention_days Spalte, GetRetentionDays/SetRetentionDays
- storage.Save(): per-tenant retention überschreibt globale config
- API: GET /api/admin/retention, PUT /api/admin/tenant/{id}/retention
- Frontend: RetentionTab mit globaler Policy-Anzeige, Mandanten-Tabelle,
  Bearbeiten-Dialog und Purge-Button (superadmin only)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 10:37:15 +02:00
sysopsandClaude Sonnet 4.6 5f0c7a7e6d feat(PROJ-27): Docker-Support + install.sh v2.0 (native + Docker-Modus)
Adds multi-stage Dockerfiles (Go+Xapian CGO, Next.js standalone),
docker-compose.yml, webhook-basierter Deploy-Flow und erweitertes
install.sh mit interaktiver Modus-Auswahl.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 10:18:11 +02:00
sysopsandClaude Sonnet 4.6 842640c3aa fix: Superadmin wird direkt zu /admin weitergeleitet
- Login: superadmin → /admin, alle anderen → /search
- Cached-Session: superadmin → /admin
- Search-Seite: superadmin wird sofort zu /admin umgeleitet

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 10:05:08 +02:00
sysopsandClaude Sonnet 4.6 27040ffcb1 feat(PROJ-28): FQDN + smtp_out Konfiguration
- config: server.fqdn, SMTPOutConfig, smtp_out Abschnitt
- config: IMAPServerConfig.FQDN (runtime-gesetzt)
- main: FQDN-Fallback für SMTP EHLO, FQDN an IMAP-Server
- imapserver: Greeting nutzt server.fqdn (RFC 3501)
- smtpd/imapserver Modulversion 1.3

fix: Superadmin sieht keine Suche/IMAP/POP3 Nav-Links

- Navbar: Suche, IMAP Import, POP3 Import nur für non-superadmin
- Superadmin landet direkt auf Admin-Dashboard

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 09:51:41 +02:00
sysopsandClaude Sonnet 4.6 8d0f685fc9 feat(PROJ-33): IMAP UID-Stabilität + Shared/Personal-Modus
Backend:
- storage: uid BIGSERIAL Migration, MailWithUID, GetMailsWithUID, GetMailsByRecipient
- tenantstore: imap_mode Spalte, GetIMAPMode, SetIMAPMode
- imapserver: stable UIDs aus DB, personal/shared Modus, userEmail in session
- api: GET/PUT /api/admin/settings/imap-mode (domain_admin only, double opt-in)

Frontend:
- IMAPSettingsTab: Modus-Anzeige + Toggle mit Double-Opt-In Dialog
- Admin-Panel: IMAP-Tab für domain_admin

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 09:46:52 +02:00
sysopsandClaude Sonnet 4.6 b6856af2eb feat(PROJ-32): Message-ID-basierte Duplikatserkennung
- message_id Spalte + UNIQUE-Index in emails-Tabelle
- Save() prüft Message-ID vor SHA-256-Flow (kein Disk-I/O bei Duplikat)
- lookupByMessageID() als private Hilfsfunktion
- insertMeta() schreibt message_id, gibt error zurück (Race-safe)
- SaveMeta() schreibt message_id idempotent (Backfill)

feat(PROJ-34): Retention-Policy + Löschsperre (GoBD)

- retain_until TIMESTAMPTZ Spalte in emails-Tabelle
- ErrRetentionLock typed error
- Delete() prüft Retention-Frist vor Löschung
- Purge() löscht alle Mails mit abgelaufener Retention
- POST /api/admin/purge Endpunkt (superadmin only)
- config: storage.retention_days

fix: Superadmin-Benutzerübersicht zeigt Mandant-Spalte

- UsersTab: Mandant-Spalte wenn isSuperAdmin
- domain_auditor Rolle im Create-Dialog ergänzt
- storage Modulversion → 1.6

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 01:29:25 +02:00
sysopsandClaude Sonnet 4.6 cb31c48ce8 fix: version → AppVersion in cmd_import.go (Build-Fehler nach 0.9.1-Umbenennung)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 01:14:27 +02:00
sysopsandClaude Sonnet 4.6 4f7a7d6946 feat: App-Version 0.9.1 + Modulversionsnummern
- version.go: AppVersion + Modules-Map (pro Modul interne Versionsnummer)
- GET /api/version: liefert App- und Modulversionen (ohne Auth)
- archivmail version: zeigt App- und Modulversionen in CLI
- version-Konstante aus cmd_import.go entfernt (war falsche Stelle)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 01:12:51 +02:00
sysopsandClaude Sonnet 4.6 64433aa847 fix(SEC-29): Rollen-Trennung Admins/Auditoren, domain_auditor Rolle
- superadmin + domain_admin haben keinen Mail-Zugriff mehr (requireMailAccess)
- Neue Rolle domain_auditor: alle Tenant-Mails, kein Admin-Zugriff
- auditor + user: nur eigene Mails
- ZIP-Export: kein separates Attachment-Entpacken mehr, nur EML
- roleLevel() um domain_auditor (Level 3) erweitert

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 01:09:19 +02:00
sysopsandClaude Sonnet 4.6 e0f6a818eb feat: LDAP-Test zeigt klickbare Filter-Vorschläge (UCS/AD-Erkennung)
Nach erfolgreichem Verbindungstest werden passende Filter-Vorschläge
angezeigt. Erkennt automatisch Univention UCS (posixAccount) vs.
Active Directory (sAMAccountName). Klick übernimmt den Filter direkt
ins Formular. Vorschläge berücksichtigen mailPrimaryAddress (UCS).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 14:50:20 +01:00
sysopsandClaude Sonnet 4.6 2fa7104605 fix: User-Struct JSON-Tags ergänzen (active/source/id etc. waren Großbuchstaben)
Frontend erhielt 'Active'/'Source' statt 'active'/'source' →
Inaktiv-Badge und local-Badge zeigten falsche Werte.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 13:46:47 +01:00
sysopsandClaude Sonnet 4.6 0b435d8d1a fix: LDAP FetchUsers Filter ohne Klammern erzeugt Compile Error
UserFilter wie 'uid=%s' wurde zu 'uid=*' — kein gültiger LDAP-Filter.
Fix: Klammern ergänzen wenn der Filter nicht mit '(' beginnt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 13:38:19 +01:00
sysopsandClaude Sonnet 4.6 a6a66beaa8 chore: weitere Code-Aufteilung (api.ts, hooks, ldap_sync)
- src/lib/api.ts (1085 Zeilen) → 5 thematische Module unter src/lib/api/
  (core, users, ldap, tenants, mail, system) + index.ts Re-Export
- useLDAPConfig / useTenantLDAPConfig / useTenantUsers Hooks extrahiert;
  admin/page.tsx nutzt diese statt roher useState-Blöcke
- handleSyncTenantLDAP, handleAdminSyncTenantLDAP, doSyncTenantLDAP,
  buildTenantTestConfig, syncResult aus ldap_tenants.go in ldap_sync.go verschoben

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 13:05:19 +01:00
sysopsandClaude Sonnet 4.6 bc4a98de0d chore: admin/page.tsx in Einzelkomponenten aufteilen (3917 → 1304 Zeilen)
- Tab-Sektionen → src/components/admin/tabs/ (11 Dateien)
- Dialoge → src/components/admin/ (TenantLDAPDialog, UserDialogs)
- Keine Verhaltensänderungen, TypeScript fehlerfrei

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 12:30:16 +01:00
sysopsandClaude Sonnet 4.6 38f8cdddc7 fix: TypeScript-Fehler bei tenantUsersSyncResult errors-Pruefung
Optional chaining auf errors.length fuehrt zu 'possibly undefined'
in strict mode -- explizite null-Guard + nullish coalescing fix.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 11:36:35 +01:00
sysopsandClaude Sonnet 4.6 72b023b598 feat: LDAP-User-Sync in Mandanten-Benutzerliste
Neuer Endpoint POST /api/admin/tenants/{id}/ldap/sync importiert alle
LDAP-User (source=ldap) per UpsertLDAPUser in die Tenant-Benutzerliste.
Im Nutzer-Dialog erscheint ein "LDAP-Benutzer synchronisieren"-Button
wenn LDAP für den Mandanten aktiv ist. Unterstützt Univention UCS
(mailPrimaryAddress, inetOrgPerson). Benutzertabelle zeigt jetzt auch
die Quelle (local/ldap).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 11:35:02 +01:00
sysopsandClaude Sonnet 4.6 2da61689ea feat: LDAP-Test zeigt User-Tabelle mit Univention-UCS-Support
Nach erfolgreichem Verbindungstest werden bis zu 50 Benutzer (UID,
Name, E-Mail) in einer scrollbaren Tabelle angezeigt. Unterstützt
mailPrimaryAddress (Univention UCS) als Fallback für mail sowie
inetOrgPerson objectClass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 11:23:12 +01:00
sysopsandClaude Sonnet 4.6 30c6694dff feat(PROJ-24): Mandanten-Logo Upload
- DB: logo_data (BYTEA) + logo_content_type Spalten in tenants-Tabelle
- Backend: SetLogo/GetLogo/DeleteLogo im tenantstore
- API: Logo-Endpunkte für superadmin (beliebiger Mandant) und
  domain_admin (eigener Mandant), max. 2 MB, PNG/JPEG/GIF/WebP/SVG
- Frontend: Logo-Dialog in Mandantentabelle (superadmin),
  Logo-Upload-Sektion im LDAP-Tab (domain_admin)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 03:15:34 +01:00
sysopsandClaude Sonnet 4.6 cd2781bdff fix: Mandanten-Nutzerdialog Fehlerhandling + LDAP-Hinweis
- Fehlerstate für Nutzer-Dialog: API-Fehler werden jetzt angezeigt statt silent ignoriert
- LDAP-Hinweis: wenn LDAP aktiv aber keine lokalen User da sind, erklärender Text
  "LDAP ist aktiv — Benutzer erscheinen hier nach ihrem ersten Login"
- tenantUsersDialogLdap State: speichert ob Tenant LDAP aktiviert hat

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 02:18:41 +01:00
sysopsandClaude Sonnet 4.6 9db433c4c1 fix: Mandantenverwaltung LDAP-Status und Nutzer-Listing
- tenantstore.List(): LEFT JOIN tenant_ldap hinzugefügt — ldap_enabled + ldap_url
  werden jetzt im GET /api/tenants Response mitgeliefert
- Tenant-Struct: Felder LDAPEnabled *bool + LDAPURL string ergänzt
- Neuer Endpunkt GET /api/tenants/{id}/users → listet Nutzer eines Mandanten
- api.ts: getTenantUsers() Funktion + tenant_id Feld im User Interface
- Admin-Panel: "Nutzer"-Button im Mandanten-Tab öffnet Dialog mit Nutzerliste

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 02:01:12 +01:00
sysopsandClaude Sonnet 4.6 b3074b303e fix: LDAP leere BindPassword schlägt Login fehl + install.sh Passwort-Extraktion
- auth.Manager.Login: LDAP-Fallback überspringen wenn URL oder BindPassword leer
  (verhindert go-ldap ErrorEmptyPassword Code 206 bei fehlerhaftem LDAP-Config-Eintrag)
- install.sh: grep-Muster von variablenbreitem Lookbehind auf \K umgestellt
  (PCRE unterstützt keine variablen Lookbehinds — Passwörter wurden nie korrekt extrahiert)
- install.sh: Wartezeit auf Backend-Start erhöht (bis zu 15s statt 2s)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 01:47:48 +01:00
sysopsandClaude Sonnet 4.6 fd46f0de9a fix: superadmin beim ersten Start anlegen + Installer zeigt echte Passwörter
- seedDefaultUsers: superadmin (Rolle superadmin) zu Default-Usern hinzugefügt
  → wird beim ersten Backend-Start mit Zufallspasswort angelegt
- Installer: Passwörter werden nach dem Deployment aus dem Journal gelesen
  (journalctl -u archivmail) statt falschen Platzhalter 'archivmailrockz'

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 01:23:33 +01:00
sysopsandClaude Sonnet 4.6 32032b49d2 fix(installer): echte Web-Passwörter aus Journal lesen statt Platzhalter
Der Backend generiert beim ersten Start zufällige Passwörter und gibt
sie im Journal aus. Der Installer liest sie nun nach dem Deployment
und trägt sie korrekt in install-summary.txt und Terminal-Output ein.
Zuvor wurden fälschlicherweise 'archivmailrockz' als Passwörter angezeigt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 01:22:50 +01:00
sysopsandClaude Sonnet 4.6 33eafc1624 feat(installer): Zusammenfassung aller angelegten User & Passwörter
- Abschlussbericht zeigt alle Credentials in übersichtlicher Tabelle:
  DB-Passwort, API-Secret, Web-Logins (superadmin/admin/auditor)
- Speichert vollständige Zusammenfassung als /etc/archivmail/install-summary.txt
  (chmod 600, nur root lesbar) mit allen Pfaden, Diensten und Hinweisen
- Tabelle im Terminal-Output mit allen wichtigen Zugangsdaten auf einen Blick

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 01:10:19 +01:00
sysopsandClaude Sonnet 4.6 d262253faf fix(installer): DB-Passwort-Mismatch bei Re-Install verhindern
Bei vorhandener config.yml wird das DB-Passwort daraus gelesen und
PostgreSQL entsprechend aktualisiert — verhindert Auth-Fehler beim
zweiten Installer-Durchlauf auf demselben Server.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 01:05:51 +01:00
sysopsandClaude Sonnet 4.6 48e04f36fd fix(installer): Lücken aus Gap-Report geschlossen
- rsync zum apt-Paket-Block hinzugefügt
- DEBIAN_FRONTEND=noninteractive gesetzt (keine debconf-Interaktion)
- go PATH-Fix: Debian-spezifische Pfade in /usr/lib/go-*/bin ergänzen
  (update.sh + install.sh symlink-Fallback)
- TLS-Zertifikat: selbstsigniertes RSA-4096 Cert via hostname -f,
  /etc/ssl/archivmail/ anlegen + Permissions (640, root:archivmail)
- nginx: HTTPS von Anfang an (HTTP→HTTPS Redirect + TLS-Block statt HTTP-only)
- config.yml-Template vollständig:
  - smtp.enabled, smtp.domain (hostname -f), smtp.tls_cert/tls_key
  - imap_server (enabled, bind :993, tls_cert/tls_key)
  - api.trusted_proxies, api.secure_cookies: true
  - Vorhandenes config.yml wird nicht überschrieben
- systemd archivmail.service: AmbientCapabilities=CAP_NET_BIND_SERVICE
  (für privilegierten Port 993 als non-root User)
  NoNewPrivileges=false (erforderlich für AmbientCapabilities)
  ReadOnlyPaths um /etc/ssl/archivmail ergänzt
- systemctl enable am Ende des Installers (ohne --now)
- update.sh nach /opt/archivmail/ kopieren + erstes Deployment direkt anstoßen
- Abschlussbericht: FQDN, HTTPS/IMAP/SMTP URLs, TLS-Hinweis

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 01:03:57 +01:00
sysopsandClaude Sonnet 4.6 c59cad92be fix: IMAP-Konto bearbeiten + Löschen auch bei sync_running
- Store: UpdateCredentials() — Zugangsdaten + Passwort neu verschlüsseln,
  setzt status='idle', error_msg='', sync_running=false zurück
- Handler: PATCH /api/imap/{id} unterstützt nun Credential-Update
  (name/host/username vorhanden = Credential-Update, sonst sync_interval)
- Frontend: "Bearbeiten"-Button öffnet Edit-Dialog mit allen Feldern;
  Passwort-Feld leer = unverändertes Passwort
- Frontend: Löschen-Button nicht mehr durch sync_running blockiert
  (nur noch bei status=running gesperrt)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 00:49:37 +01:00
sysopsandClaude Sonnet 4.6 4a4136e4a6 feat: FQDN-Support, IMAP-TLS und SMTP-TLS via Master-Cert
- config: IMAPServerConfig um TLSCert/TLSKey erweitert
- imapserver: TLS-Support (tls.Listen) mit automatischem Port 993-Default
- Server-Konfiguration: FQDN archivmail.scahome.local
  - nginx server_name auf archivmail.scahome.local gesetzt
  - SMTP domain auf archivmail.scahome.local
  - SMTP TLS aktiviert (/etc/ssl/archivmail/archivmail.crt)
  - IMAP-Server TLS auf Port 993 aktiviert
  - secure_cookies: true (HTTPS)
  - Firewall: Port 993 geöffnet
  - Zertifikat neu ausgestellt (SAN: archivmail.scahome.local + archivmail + 192.168.1.131)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 00:32:25 +01:00
sysopsandClaude Sonnet 4.6 9e71af104f feat: Dark Mode + Zertifikat-Verwaltung im Superadmin
- Dark Mode: ThemeProvider (next-themes), ThemeToggle in Navbar (Hell/Dunkel/System)
- Zertifikat-Tab (superadmin only): aktuelles Zertifikat anzeigen, Upload (cert+key),
  Self-Signed ausstellen, Let's Encrypt/ACME
- Backend: /api/admin/cert/* Endpunkte (info, upload, self-signed, acme), nginx reload
- HTTPS bereits live auf Server (self-signed RSA-4096, Port 443)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 00:14:43 +01:00
sysops 0e62b10bd4 fix(PROJ-26): IMAP-Löschen-Fehler nicht mehr stumm verschlucken — Fehlermeldung anzeigen 2026-03-18 12:16:32 +01:00
sysopsandClaude Sonnet 4.6 d79e334029 refactor: server.go in separate Handler-Dateien aufgeteilt
server.go (2357 -> 391 Zeilen) enthaelt nur noch Server-Struct,
Konstruktor, Router, Middleware und Hilfsfunktionen.

Neue Dateien:
- auth_handlers.go: Login, Logout, Me
- search_handlers.go: Suche, Mail-Anzeige, Anhaenge, Raw-Download
- admin_handlers.go: User-CRUD, SMTP/Storage-Stats, Services, Security
- import_handlers.go: IMAP + POP3 Account-Verwaltung und Import
- dashboard_handlers.go: System-Stats, Audit-Log

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 11:55:21 +01:00
sysops e7146fdbac fix: ungenutzten pgx/v5 Import in labelstore entfernen 2026-03-18 11:47:10 +01:00
sysopsandClaude Sonnet 4.6 19a55a3166 feat(PROJ-26): IMAP-Archive-Server Read-Only Zugriff auf archivierte Mails
- Neues Package internal/imapserver: vollständiger IMAP4rev1-Server (~700 Zeilen)
- Auth via bcrypt (userstore.VerifyPassword), Multi-Tenant-Isolation
- INBOX + INBOX/LabelName Ordnerstruktur
- FETCH mit BODY[], ENVELOPE, RFC822.SIZE, INTERNALDATE, FLAGS, UID
- SEARCH: ALL, FROM, TO, SUBJECT, SINCE, BEFORE + UID FETCH/SEARCH
- Read-Only: STORE, DELETE, COPY, MOVE, APPEND → NO [CANNOT]
- \Seen-Flag nicht persistent (GoBD-konform)
- Max 5 gleichzeitige Verbindungen pro User, 30min Idle-Timeout
- Audit-Log: imap_login / imap_login_failed Events
- Config: imap_server.enabled + imap_server.bind (default: 127.0.0.1:1143)
- Externe Ports: 9993 (primär) und 993 (alternativ) via nginx TLS-Terminierung

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 11:42:35 +01:00
sysopsandClaude Sonnet 4.6 5c25e3a7e7 feat(PROJ-26): IMAP-Verbindungsinfo in User-Settings anzeigen
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 11:36:04 +01:00
sysops dd41e1f00e fix(PROJ-16): LDAP URL-Feld zeigt flexible Port-Hinweise inkl. Univention UCS (7389/7636) 2026-03-18 10:50:34 +01:00
sysops cee75094ad feat(PROJ-9): implement labels frontend - LabelList, LabelPicker, search integration, admin UI 2026-03-18 09:51:10 +01:00
sysops 2e9f1f0471 feat(PROJ-26): Add feature specification for IMAP server interface (read-only archive access) 2026-03-18 09:50:53 +01:00
sysopsandClaude Sonnet 4.6 5a6289c83d feat(PROJ-9): implement labels backend - DB schema, labelstore, API handlers, Xapian integration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 08:32:30 +01:00
sysopsandClaude Sonnet 4.6 bd09992441 feat(PROJ-21): Phase 6+7 abschliessen — Dienste-Tab nur superadmin
Frontend: Dienste-Tab (Systemdienste starten/stoppen) ist jetzt nur
noch für superadmin sichtbar. domain_admin sieht: Dashboard, Benutzer,
Audit-Log, Import, LDAP (eigener Mandant).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 01:18:28 +01:00
sysopsandClaude Sonnet 4.6 372eee7aef fix: api.ts internes request-Typ auch auf qr_code korrigiert
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 01:13:38 +01:00
sysopsandClaude Sonnet 4.6 26ab14b25b fix: restlichen setQrSvg-Aufruf auf setQrCode umbenennen
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 01:12:52 +01:00
sysopsandClaude Sonnet 4.6 dc13edf2f6 fix(PROJ-25): QR-Code als PNG-Base64 anzeigen (statt fehlendem SVG)
Backend gibt qr_code als base64-PNG zurück — Frontend war auf qr_code_svg
ausgerichtet. Fix: getTOTPSetup-Typ angepasst, img-Tag statt dangerouslySetInnerHTML.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 01:12:07 +01:00
sysopsandClaude Sonnet 4.6 0fbb1924bb fix(security): W-02 Secure-Cookie-Flag + W-03 TrustedProxies für X-Forwarded-For
W-02: Cookie Secure-Flag ist nun über config.yml steuerbar.
      api.secure_cookies: true/false — default false (kein Breaking Change).
      Alle 3 SetCookie-Aufrufe (Login, Logout, TOTP) nutzen s.cfg.SecureCookies.

W-03: remoteIP() ist jetzt eine Methode und prüft api.trusted_proxies.
      X-Forwarded-For wird nur ausgewertet wenn der direkte Peer in der
      trusted_proxies-Liste steht (IP oder CIDR). Sonst wird r.RemoteAddr
      verwendet — kein Spoofing mehr möglich.
      Neue Hilfsfunktion: isTrustedProxy(ip, proxies).

config.go: APIConfig um SecureCookies bool + TrustedProxies []string erweitert.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 01:10:24 +01:00
sysopsandClaude Sonnet 4.6 280034679e feat(PROJ-25): User-Profil & Einstellungen — Passwort, E-Mail, 2FA
Backend:
- PATCH /api/auth/password — Passwort ändern (bcrypt, LDAP-Guard, Audit-Log)
- PATCH /api/auth/email — E-Mail ändern (Unique-Check, LDAP-Guard, Audit-Log)
- userstore: UpdatePassword, UpdateEmail, GetPasswordHash

Frontend:
- UserNav.tsx: Dropdown-Menü (Profil & Einstellungen, Abmelden)
- navbar.tsx: UserNav eingebunden
- /settings: Passwort ändern, E-Mail ändern, 2FA verwalten (QR-Code + Deaktivieren)
- api.ts: changePassword, changeEmail, getTOTPSetup, confirmTOTPSetup, disableTOTP

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 01:05:33 +01:00
sysopsandClaude Sonnet 4.6 89a6651b62 chore: go.sum aktualisiert für go-ldap/v3 + Abhängigkeiten
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 00:55:54 +01:00
sysopsandClaude Sonnet 4.6 5fd419617d chore: go.sum aktualisiert für github.com/pquerna/otp v1.4.0 (PROJ-24 TOTP)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 00:55:22 +01:00
sysopsandClaude Sonnet 4.6 2de340573b fix(security): behebe F-01/F-02/W-03/W-04 aus Security-Audit + PROJ-24 TOTP 2FA
F-01: err.Error() wird nicht mehr an HTTP-Clients gesendet.
      Stattdessen generische Fehlermeldungen + Server-Log.
      Betrifft: handleCreateUser, handleUpdateUser, handleDeleteUser,
                handleSyncNow, handleSecurityConfig, handleUpload.

F-02: Login-Audit-Log enthält keinen rohen err.Error() mehr.
      Neue classifyLoginError() Funktion: invalid_password / ldap_error /
      account_disabled / unknown — schützt vor LDAP-Info-Leak via Audit-API.

W-03: remoteIP() trimmt jetzt Leerzeichen aus X-Forwarded-For.
      Vollständige Lösung erfordert Proxy-Konfiguration (W-03 bleibt WARN).

W-04: Attachment-Dateiname wird durch sanitizeFilename() bereinigt.
      Nur [a-zA-Z0-9._- ] erlaubt — verhindert Header-Injection.

PROJ-24: TOTP 2FA vollständig implementiert:
      - internal/auth/totp.go: GenerateSecret, ValidateTOTP, QRCodeSVG
      - internal/api/totp_handlers.go: Setup, Login-Step2, Admin-Reset
      - internal/userstore: SetTOTPSecret, EnableTOTP, DisableTOTP, ResetTOTP
      - Login-Flow: totp_pending JWT → /api/auth/totp → vollwertiger JWT
      - AES-256-GCM verschlüsseltes Secret in users.totp_secret

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 00:54:00 +01:00
sysopsandClaude Sonnet 4.6 787db6638f fix(PROJ-23): Privilege Escalation in Tenant-LDAP + Login-Reihenfolge
- BUG-1 (P0): domain_admin kann keine Rollen > auditor in default_role/
  group_mappings setzen — serverseitige Allowlist-Prüfung in
  handleSaveTenantLDAP (user/auditor) und handleAdminSaveTenantLDAP
  (user/auditor/domain_admin)
- WARN-1: Login-Fallback-Reihenfolge korrigiert — tenant_ldap wird
  jetzt VOR globalem ldap_config geprüft (Spec: tenant > global > local)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 00:32:47 +01:00
sysopsandClaude Sonnet 4.6 9e7add31cd feat(PROJ-23): Pro-Mandant LDAP Frontend
- domain_admin: neuer LDAP-Tab mit Tenant-Konfiguration (eigener Mandant)
  - Gruppen-Mapping auf user/auditor beschränkt (keine Eskalation)
  - Nutzt /api/tenant/ldap Endpunkte
- superadmin: globaler LDAP-Tab umbenannt zu "LDAP (Global)"
- superadmin: Mandantentabelle um LDAP-Statusspalte erweitert
  - Badge: Aktiv / Deaktiviert / ---
  - TenantLDAPDialog pro Mandant (alle Rollen bis domain_admin)
- api.ts: TenantLDAPConfig Interface + 8 neue API-Funktionen
  - getTenantLDAPConfig/save/delete/test (domain_admin)
  - getAdminTenantLDAPConfig/save/delete/test (superadmin)
- Tenant Interface: ldap_enabled + ldap_url Felder ergänzt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 00:27:51 +01:00
sysopsandClaude Sonnet 4.6 e333e34a03 fix: unused time import in tenant_store.go
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 00:19:00 +01:00
sysopsandClaude Sonnet 4.6 78d83d3e98 feat(PROJ-21/23): Pro-Tenant Xapian-Index + Tenant-LDAP Backend
PROJ-21 Phase 4:
- internal/index/tenant_manager.go: TenantIndexManager mit lazy-loading Pool
- internal/index/tenant_worker.go: TenantIndexWorker leitet Submit an richtigen Index
- Jeder Mandant bekommt eigenes Xapian-Verzeichnis (tenant-<id>/)
- handleSearch nutzt direkt Tenant-Index statt nachgelagertem Post-Filter
- runBackfill re-indexiert pro Mandant beim Start

PROJ-23 / PROJ-16 Phase B:
- internal/ldapconfig/tenant_store.go: TenantStore mit AES-256-GCM für tenant_ldap
- internal/api/ldap_tenants.go: 8 neue Handler (GET/PUT/DELETE/test für
  /api/tenant/ldap und /api/admin/tenants/{id}/ldap)
- internal/auth/auth.go: Login-Fallback prüft tenant_ldap nach globalem LDAP
  (Domain-Extraktion → tenant_ldap config → UpsertLDAPUser mit tenant_id)
- internal/api/server.go: SetTenantLDAP(), neue Routen registriert
- internal/tenantstore/store.go: GetByDomain() Interface für auth-Package
- cmd/archivmail/main.go: TenantLDAPStore + TenantIndexManager verdrahtet

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 00:18:35 +01:00
sysopsandClaude Sonnet 4.6 46d7bfe608 fix(security): Kritische Sicherheitslücken beheben (SEC-01/02/03/05/08/17/22/26/28)
- SEC-01: Privilege Escalation verhindert — Rollenhierarchie in Create/Update/DeleteUser
- SEC-02: Tenant-Isolation in Update/DeleteUser — domain_admin nur eigene Nutzer
- SEC-03: IMAP/POP3 Owner-Check via auth.HasRole statt direktem String-Vergleich
- SEC-05: Export PDF/ZIP prüft Tenant-Zugehörigkeit vor Dateiausgabe
- SEC-08: HKDF-SHA256 trennt JWT-Secret von AES-Key (archivmail-jwt-v1 / archivmail-aes-v1)
- SEC-17: handleSecurityFix erfordert requireRole(superadmin)
- SEC-22: Mail-ID Regex [0-9a-f]{64} in allen Handlern (Path-Traversal-Schutz)
- SEC-26: SMTP Fail-Closed — leere AllowedIPs blockiert alles statt zu erlauben
- SEC-28: handleGetRaw — Parse-Fehler bricht ab statt Fallthrough zu Dateizugriff

BREAKING: IMAP/POP3/LDAP-Passwörter müssen nach Deploy einmalig neu eingegeben
werden (neuer AES-Key). JWT-Sessions laufen ab (einmaliges Re-Login nötig).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 00:05:47 +01:00
sysopsandClaude Sonnet 4.6 143db65755 fix: Tenant-Isolation in handleSearch + requireMailAccess
- handleSearch: Ergebnisse nach tenant_id filtern (via email_refs)
- requireMailAccess: domain_admin darf Mails lesen, Tenant-Prüfung
  erfolgt bereits in handleGetMail via GetTenantForMail

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 22:03:22 +01:00
sysops d8a8204e36 fix: allowed_ips non-null assertion 2026-03-17 21:46:25 +01:00
sysops 3e7f365707 fix: allowed_ips optional chain 2026-03-17 21:45:40 +01:00
sysops 24d866d100 fix: smtpStatus.domains optional chain 2026-03-17 21:44:57 +01:00
sysops 13cc114f2f fix: optional SMTPStatus Felder mit ?? absichern 2026-03-17 21:44:14 +01:00
sysops 473715ca20 fix: SMTPStatus Typ um tenant-Felder erweitert 2026-03-17 21:43:19 +01:00
sysops b360e07e2d fix: doppelte sess-Deklaration in handleServiceAction 2026-03-17 21:42:23 +01:00
sysopsandClaude Sonnet 4.6 2dbddff0e2 feat: rollenbasierte SMTP-Statistik + Service-Aktionen
- handleServiceAction: nur superadmin darf Dienste stoppen/starten
- handleSMTPStatus: domain_admin bekommt tenant-gefilterte Stats
  (Domains, Mailanzahl, Speicher) statt globaler Daemon-Info
- Admin-Dashboard: SMTP-Kacheln, Systemauslastung, IP-Allowlist
  nur für superadmin; domain_admin sieht eigene Domain-Statistik
- Dienste-Tab: Aktions-Buttons nur für superadmin sichtbar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 21:41:57 +01:00
sysopsandClaude Sonnet 4.6 db433e5c2e fix: Rollenhierarchie domain_admin/superadmin in Frontend
- useAuth: neue Rollen domain_admin/superadmin + hasRole() helper
- Admin-Page: useAuth(domain_admin), isSuperAdmin-Flag
- Tabs LDAP/Security/Mandanten/Module nur für superadmin
- Navbar: Admin-Link für domain_admin + superadmin sichtbar
- User-Anlage: domain_admin-Rolle wählbar, superadmin nur für superadmin

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 21:23:24 +01:00
sysops 73cb609411 fix: Navbar props in upload page 2026-03-17 21:04:45 +01:00
sysopsandClaude Sonnet 4.6 479c27e5a8 feat(PROJ-21): Phase 2+3+5+8 Multi-Tenancy + PROJ-2 EML/MBOX Upload
Phase 2a: userstore domain_admin/superadmin Rollen, User.TenantID,
          ListByTenant, UpsertLDAPUser mit tenantID
Phase 2b: storage.Save() mit tenantID *int64, email_refs Tabelle,
          GetTenantForMail, GetAllIDsByTenant, StatsByTenant
Phase 2c: JWT-Claims tenant_id/tenant_slug, Session.TenantID,
          Login Domain-Erkennung via E-Mail-Domain
Phase 3:  tenantMiddleware, Handler-Filterung (Users, Mail, Stats)
Phase 5:  SMTP Domain-Routing via DomainToTenantFunc Callback,
          config smtp.tenant_routing + default_tenant_id
Phase 8:  archivmail migrate-tenants Subkommando
PROJ-2:   Upload-Seite /admin/upload mit DropZone + Progress-Polling

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 21:03:40 +01:00
sysopsandClaude Sonnet 4.6 5250ffcd52 fix(deploy): korrigiere update.sh Frontend-Standalone-Deployment
Vorher: rsync --delete führte dazu dass FRONTEND_DIR nach dem Sync
nur den _build/-Unterordner enthielt statt server.js direkt.
Ursache: Next.js standalone spiegelt den absoluten Build-Pfad.

Jetzt: FRONTEND_DIR wird vor dem Sync geleert (rm -rf) um veraltete
Verzeichnisse zu entfernen; rsync ohne --delete kopiert den korrekten
Standalone-Root direkt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 20:32:10 +01:00
sysopsandClaude Sonnet 4.6 3fd7b85080 chore: add go.sum entries for github.com/go-ldap/ldap/v3 v3.4.8
Dependencies resolved via go get on server:
- github.com/go-ldap/ldap/v3 v3.4.8
- github.com/go-asn1-ber/asn1-ber v1.5.5 (indirect)
- github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 (indirect)
- github.com/google/uuid v1.6.0 (indirect)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 20:29:18 +01:00
sysopsandClaude Sonnet 4.6 ac91dceac2 feat(PROJ-22): LDAP Web-GUI + feat(PROJ-21): Multi-Tenancy Phase 1
PROJ-22 – LDAP Web-GUI Konfiguration & Test:
- internal/ldapconfig/store.go: AES-256-GCM Passwortspeicherung, CRUD Upsert (id=1)
- internal/ldapauth/client.go: TestConnection (RootDSE, UserCount) + Authenticate (2-step bind)
- internal/auth/auth.go: LDAP-Fallback in Login(), Gruppen-Rollenzuordnung, issueToken helper
- internal/api/ldap_tenants.go: GET/PUT/DELETE/POST-test /api/admin/ldap mit Audit-Log
- go.mod: github.com/go-ldap/ldap/v3 v3.4.8 hinzugefügt
- Frontend: LDAPConfig/LDAPTestResult Typen, LDAP-Tab mit Gruppen-Mappings + Testergebnis

PROJ-21 Phase 1+6+7 – Multi-Tenancy Grundstruktur:
- internal/tenantstore/store.go: tenants, tenant_domains, tenant_ldap Schema; Migration users/audit_log
- API: 8 Tenant-Routen (CRUD + Domain-Management) via SetTenants()
- cmd/archivmail/main.go: ldapSt + tenantSt initialisiert
- Frontend: Mandanten-Tab mit Tabelle, Domain-Dialog, Deaktivieren/Löschen

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 20:27:56 +01:00
sysops 4f0670d94c fix: update.sh Frontend-Deployment — standalone server.js Pfad korrekt ermitteln 2026-03-17 19:51:21 +01:00
sysops adffff7ee1 feat(PROJ-14): POP3-Import — Client, Store, Importer, API-Routen, Frontend-Seite 2026-03-17 19:48:14 +01:00
sysops 5e69c29f16 feat: Security Audit Auto-Fix Buttons + manuelle Dokumentation (docs/security-audit.md) 2026-03-17 15:23:31 +01:00
sysops 4668150727 feat: Security Audit Tab im Admin-Panel mit nftables/SSH/Fail2ban-Checks 2026-03-17 15:09:01 +01:00
sysopsandClaude Sonnet 4.6 b6fa668002 docs(PROJ-22): Plan LDAP/AD Web-GUI Konfiguration & Test
Vollständiger Plan: ldap_config DB-Tabelle, internal/ldapconfig + ldapauth Pakete, GET/PUT/DELETE/test API-Endpunkte, LDAP-Tab im Admin-UI mit Formular, Testergebnis-Panel, Gruppen-Zuordnungen, Passwort-Masking und Audit-Log.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 14:41:19 +01:00
sysopsandClaude Sonnet 4.6 22dfe1300b docs(PROJ-16/21): LDAP und Multi-Tenancy aufeinander abgestimmt
- PROJ-16: Abhängigkeit zu PROJ-21 dokumentiert, Phase A (config.yml) / Phase B (pro-Mandant DB) getrennt, Rolle "admin" → "domain_admin" in group_mappings, UpsertLDAPUser erhält tenant_id in Phase B, neue /api/tenant/ldap Endpunkte
- PROJ-21: tenant_ldap-Tabelle in Phase 1 ergänzt, Phasen-Abhängigkeit zu PROJ-16 explizit, LDAP in Zugriffsmatrix aufgenommen

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 14:10:48 +01:00
sysopsandClaude Sonnet 4.6 6d088795eb docs(PROJ-21): Architekturplan Multi-Tenancy
Vollständiger Plan für Mandanten-Fähigkeit: Rollenmodell, DB-Schema, API-Änderungen, SMTP-Routing, Frontend, Migrations-Strategie und Umsetzungsphasen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 13:56:18 +01:00
sysopsandClaude Sonnet 4.6 e46b68b63f feat(PROJ-20): GoBD-konforme Nutzer-Löschung mit IMAP-Cleanup und Warn-Dialog
- imap/store.go: DeleteByOwner() – löscht alle IMAP-Konten eines Nutzers
- api/server.go: handleDeleteUser lädt Nutzername vor Löschung, ruft DeleteByOwner, schreibt erweitertes Audit-Log (username, role, IMAP-Count, GoBD-Hinweis)
- admin/page.tsx: confirm() ersetzt durch Dialog mit GoBD-Hinweis, Deaktivieren-Option (empfohlen) und endgültigem Löschen (destruktiv)
- features/PROJ-20-nutzer-loeschung.md: Feature-Spec angelegt
- features/INDEX.md: PROJ-20 eingetragen, Next ID → PROJ-21

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 13:44:32 +01:00
sysopsandClaude Sonnet 4.6 2900e53753 chore: update.sh aktualisiert sich beim Start selbst aus Gitea
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 12:43:15 +01:00
sysopsandClaude Sonnet 4.6 dc71d78d7d chore: migrate-Block aus update.sh entfernt
archivmail kennt keinen migrate-Subcommand – der Block hat immer nur warn ausgegeben und nichts getan.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 12:41:05 +01:00
sysopsandClaude Sonnet 4.6 f00ebbe733 fix: Xapian-Lockfile nach systemctl stop entfernen
Verhindert DatabaseLockError beim Neustart wenn flintlock durch harten Abbruch liegen bleibt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 12:38:42 +01:00
sysopsandClaude Sonnet 4.6 f2dbf18e5a fix: safe.directory für _build vor git fetch setzen
Verhindert "dubious ownership"-Fehler wenn _build unter anderem Nutzer angelegt wurde.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 11:24:59 +01:00
sysopsandClaude Sonnet 4.6 2dbfd3ddf6 chore: allowed_ips Kommentare in config.test.yml ergänzt
Erklärt Zweck, Syntax (IP + CIDR), Leer=allow-all und Neustart-Pflicht.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 11:13:41 +01:00
sysopsandClaude Sonnet 4.6 b95c49daa5 feat(PROJ-2): EML/MBOX-Upload für alle Benutzer zugänglich
- Backend: neue Routen POST /api/upload + GET /api/upload/{jobID}/progress (nur Auth, kein Admin)
- api.ts: uploadMailFilesUser + getUploadProgressUser für /api/upload
- search/page.tsx: Importieren-Button + Upload-Dialog mit Drag-and-Drop, Fortschrittsanzeige und automatischer Suchlisten-Aktualisierung nach Import

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 10:12:09 +01:00
sysopsandClaude Sonnet 4.6 1e677659b9 chore: replace AI Coding Starter Kit references with archivmail project info
- CLAUDE.md: vollständig auf archivmail-Kontext umgeschrieben (Go/Xapian Stack, On-Premise Deploy, keine Supabase/Vercel)
- package.json: name und description auf archivmail aktualisiert

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 09:58:41 +01:00
sysopsandClaude Sonnet 4.6 861df83986 chore: .gitignore und features/ aus Git-Tracking entfernen (nur lokal)
Ignore-Regeln liegen jetzt in .git/info/exclude und werden
nie nach Gitea übertragen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 09:53:47 +01:00
sysopsandClaude Sonnet 4.6 ce10864e62 chore: .claude/ Verzeichnis komplett in .gitignore aufnehmen
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 09:44:05 +01:00
sysopsandClaude Sonnet 4.6 7c29ee88bd docs: vollständige README, PROJ-2 Web-Upload, PROJ-19 Mailpiler-Migration
README.md:
- Vollständige Dokumentation aller implementierten Funktionen
- Konfigurationsreferenz, Installation, Systemd, REST-API-Übersicht
- In-Progress-Features klar gekennzeichnet

PROJ-2 (EML/MBOX Web-Upload):
- POST /api/admin/upload – Multipart-Upload mit Hintergrund-Job
- GET /api/admin/upload/{jobID}/progress – Polling
- Admin-Tab "Import" mit Drag-and-Drop, Fortschrittsbalken, Abschlussbericht

PROJ-19 (Mailpiler Migration):
- archivmail import-piler mit Methoden: pilerexport | direct | auto
- Direct: AES-256-CBC + zlib mit defensiven Fallbacks
- pilerexport: Wrapper um mailpilers Export-Tool

Status-Updates: PROJ-3, PROJ-4, PROJ-6, PROJ-7, PROJ-10, PROJ-11 → Deployed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 09:23:34 +01:00
sysopsandClaude Sonnet 4.6 31de5ec99c fix(deploy): Binary auch nach /opt/archivmail/archivmail kopieren (Service-Pfad)
Der systemd-Service nutzt /opt/archivmail/archivmail direkt.
Das neue Binary wurde nur nach /opt/archivmail/bin/ deployed,
wodurch der Service das alte Binary weiter verwendete.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 02:26:32 +01:00
sysopsandClaude Sonnet 4.6 988c37d85d feat(PROJ-8): Automatischer IMAP-Sync (Cron-Scheduler)
Backend:
- internal/imap/store.go: 7 neue Felder (sync_interval_min, last_sync_at,
  last_sync_count, last_uid, sync_running, sync_status, sync_error_msg)
  DB-Migration via ALTER TABLE ADD COLUMN IF NOT EXISTS
  Neue Methoden: ListAll, UpdateSyncInterval, SetSyncRunning, UpdateSyncResult
- internal/imap/scheduler.go: Scheduler mit time.Ticker (1 min),
  inkrementeller Sync via UID SEARCH UID <lastUID+1>:*,
  exponential backoff (3 Versuche: 1s / 60s / 300s),
  sync_running-Flag verhindert parallele Syncs
- internal/api/server.go: POST /api/imap/{id}/sync (manueller Trigger),
  PATCH /api/imap/{id} (sync_interval_min setzen, 0 oder 5-1440 min)
- cmd/archivmail/main.go: Scheduler gestartet + via SetImap verdrahtet

Frontend:
- src/lib/api.ts: 6 neue ImapAccount-Felder, triggerImapSync, updateImapInterval
- src/app/imap/page.tsx: Intervall-Dropdown, "Sync jetzt"-Button,
  Letzter-Sync-Anzeige mit Status-Badge, Polling auch bei sync_running

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 02:17:44 +01:00
sysopsandClaude Sonnet 4.6 9cc540a880 fix(deploy): update.sh an tatsächliche Server-Struktur anpassen
- FRONTEND_DIR: /opt/archivmail/frontend → /opt/archivmail/web
- Go Build: CGO_ENABLED=1 -tags xapian -buildvcs=false (Xapian-Support)
- Frontend: standalone-Output deployen statt .next/ direkt
- Services: archivmail-frontend → archivmail-web

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 02:01:07 +01:00
sysopsandClaude Sonnet 4.6 bb963a796f security: Zufallspasswörter beim Erststart, kryptographisch sichere JTI-Generierung
- seedDefaultUsers: generiert kryptographisch zufällige Passwörter (crypto/rand)
  statt hartkodiertes "archivmailrockz" — Passwörter werden einmalig im Terminal
  angezeigt und können danach nicht wiederhergestellt werden
- generateJTI: verwendet crypto/rand (16 Byte, hex) statt time.UnixNano XOR deadbeef

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 01:19:24 +01:00
sysopsandClaude Sonnet 4.6 7e165c8eed feat(PROJ-1): httpOnly Cookie, Auditor-Guard, Nutzer-Aktionen (C)
Backend:
- Login setzt httpOnly SameSite=Strict Cookie (archivmail_session)
- Logout löscht Cookie + blacklistet Token
- authMiddleware: Cookie first, Bearer als Fallback (CLI kompatibel)

Frontend:
- api.ts: credentials: include statt localStorage/Bearer Token
- updateUser(), deleteUser() hinzugefügt
- useAuth: kein localStorage mehr, nur /api/auth/me
  requireRole: "admin" | "auditor" | undefined
- Login-Seite: kein localStorage
- Navbar: kein localStorage
- Admin: Nutzer-Aktionen (Sperren/Freischalten, Löschen, Passwort-Reset)
  Löschen verhindert wenn letzter Admin (HTTP 409)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 19:57:13 +01:00
sysopsandClaude Sonnet 4.6 a94b1d3e52 fix(PROJ-1): bcrypt Cost 12, Rate-Limiting, last_login_at, User Update/Delete
- bcrypt cost erhöht von DefaultCost (10) auf 12
- Rate-Limiting: max 5 Fehlversuche in 15 Min → HTTP 429
- last_login_at in DB gespeichert und bei jedem Login aktualisiert
- login_attempts Tabelle für Fehlversuche
- PATCH /api/users/{id}: Passwort-Reset, Rolle, E-Mail, Active
- DELETE /api/users/{id}: Löschen mit Schutz für letzten Admin

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 23:04:45 +01:00
sysopsandClaude Sonnet 4.6 3c722d0987 feat(PROJ-18): E-Mail Integritätsprüfung (SHA-256 Verifikation)
- Storage: VerifyIntegrity, GetAllIDs, GetVerifyStatus + DB-Spalten
- main: Hintergrund-Worker alle 5 Minuten (beim Start sofort: 40/40 OK)
- API: verify_ok + verified_at in GET /api/mails/{id} Antwort
- Frontend: Grüner Haken / graues X / rotes X in Mail-Ansicht

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 21:28:40 +01:00
sysopsandClaude Sonnet 4.6 7e68c7ab02 feat(PROJ-5): AES-256-GCM Verschlüsselung, PostgreSQL Metadaten, Async Index Worker
- Storage: AES-256-GCM Verschlüsselung (keyfile, graceful fallback bei fehlendem Key)
- Storage: PostgreSQL emails-Tabelle mit Auto-Migration
- Storage: Save/Delete/Stats/FirstAndLastMail nutzen DB wenn verfügbar
- Index: Async IndexWorker (Go-Channel, Queue 1000, non-blocking Submit)
- SMTP: IndexCallback für async Indexierung nach Mail-Eingang
- main: Backfill beim Start (40 Mails migriert + indexiert)
- Bestehende Mails werden transparent entschlüsselt (Fallback auf Raw)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 20:26:50 +01:00
sysopsandClaude Sonnet 4.6 850290b5ef feat(PROJ-12): E-Mail Export EML/PDF/ZIP
- GET /api/export/pdf/{id}: PDF-Generierung (stdlib, kein ext. Paket)
- POST /api/export/zip: Streaming-ZIP mit manifest.csv, Anhänge optional
- Max. 500 Mails pro Export, Zugriffscheck per Rolle
- Audit-Log für jeden Export
- Frontend: PDF-Button in Mail-Ansicht
- Frontend: Checkboxen + ZIP-Export-Dialog in Suchergebnissen

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 19:49:00 +01:00
sysopsandClaude Sonnet 4.6 30479cfc60 fix(PROJ-15): archivmail Symlink in /usr/local/bin beim Update setzen
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 19:17:54 +01:00
sysopsandClaude Sonnet 4.6 4f93b9667d feat(PROJ-15): CLI Import & Export als Subcommands
- archivmail import: EML + MBOX, --file/--dir/--recursive/--dry-run/--json
- archivmail export: EML + MBOX, Filter --from/--to/--date-from/--date-to/--query/--force/--json
- archivmail help / version
- MBOX Parser (SplitMbox) in pkg/mailparser/mbox.go
- Subcommand-Router in main.go ohne externe Abhängigkeit

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 18:25:21 +01:00
sysopsandClaude Sonnet 4.6 dbcc980343 chore: Supabase-Paket entfernen (wird nicht verwendet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 18:01:12 +01:00
sysopsandClaude Sonnet 4.6 15fb4e4eaf chore: AI Coding Starter Kit Dateien aus Git entfernen
- .claude/skills/, agents/, rules/ ignoriert (Workflow-Dateien)
- docs/production/ ignoriert (Template-Docs)
- src/lib/supabase.ts ignoriert (nicht verwendet)
- public/ Default-SVGs ignoriert
- .gitignore entsprechend erweitert

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 17:59:54 +01:00
sysopsandClaude Sonnet 4.6 d360c9a5ba feat(PROJ-17): Admin Dashboard Systemauslastung immer anzeigen
- Systemauslastungs-Sektion wird immer gerendert (nicht nur bei Erfolg)
- Fehlermeldung wenn /api/admin/system/stats nicht erreichbar ist
- Feature-Status auf In Review gesetzt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 11:43:19 +01:00