Commit Graph
296 Commits
Author SHA1 Message Date
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
sysopsandClaude Sonnet 5 28565f089d docs(PROJ-69,PROJ-70): Deployment-Status auf Deployed setzen
Beide Features auf 132 und 131 deployed (2026-07-07). PROJ-69/PROJ-70
ohne vollständigen Browser-/E2E-Test, nur Smoke-Tests — offene QA-Punkte
in den Spec-Dateien dokumentiert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 01:26:37 +02:00
sysopsandClaude Sonnet 5 ba0c519b00 docs(PROJ-70): Implementation Notes für Frontend ergänzen
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 00:43:53 +02:00
sysopsandClaude Sonnet 5 4b3a4ef996 feat(PROJ-70): Frontend für IMAP-Rückholung (Opt-in + Restore-Button)
- MeResponse um imap_restore_enabled erweitert
- setImapRestore() + restoreMail() API-Funktionen (index.ts re-export)
- useImapRestore-Hook + ImapRestoreSection (Switch + Passwort-Dialog) in Settings
- RestoreMailButton in Mail-Detailansicht (Sichtbarkeit + Konto-Select)
- Spec/INDEX auf In Review

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 00:43:24 +02:00
sysopsandClaude Sonnet 5 c00bf27fea docs(PROJ-70): Feature-Spec-Datei nachtragen (versehentlich nicht committed)
Datei war durch .git/info/exclude (features/) von "git add -u" ausgenommen,
INDEX-Eintrag existierte bereits, die eigentliche Spec-Datei fehlte im
Commit. Enthält jetzt auch die Implementation Notes zum Backend.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 00:37:32 +02:00
sysopsandClaude Sonnet 5 da79a56b3e feat(PROJ-70): Self-Service IMAP-Rückholung (Backend)
Neuer Opt-in-Endpunkt, mit dem User archivierte Mails per IMAP APPEND
zurück in ihr eigenes externes Postfach (INBOX) kopieren können. Das
Archiv selbst bleibt read-only (nur storage.Load(), kein Schreibzugriff
auf internal/imapserver).

- PATCH /api/auth/imap-restore: Opt-in-Flag umschalten, Aktivierung
  erfordert Passwort-Reverifikation.
- POST /api/mails/{id}/restore: lädt Mail lesend, prüft Mail- und
  Account-Ownership in restoreAccessAllowed() (PROJ-61-Muster), APPEND
  via neuer internal/imap/append.go, kein Admin-Override.
- Audit-Log-Eintrag (EventRestore) pro Versuch, erfolgreich und
  fehlgeschlagen.
- imap_restore_enabled-Spalte (default false) via idempotenter
  initSchema-Migration.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 00:36:44 +02:00
sysopsandClaude Sonnet 5 7aa63e30ca docs(PROJ-70): Feature-Spec IMAP-Rückholung anlegen
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 00:36:17 +02:00
sysopsandClaude Sonnet 5 e0b0c6d312 fix: Registrieren-Link auf Startseite entfernen
Selbst-Registrierung ist nicht möglich, /signup nur über gültigen
Einladungslink erreichbar. Route bleibt für Invite-Flow bestehen,
nur der irreführende Link auf der Login-Seite fällt weg.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-06 13:30:47 +02:00
sysopsandClaude Sonnet 5 3b2a8388c1 feat(PROJ-69): Admin-Dashboard Tab-Gruppierung (2-Ebenen-Navigation)
17 flache Tabs unter /admin durch Gruppen-Leiste (Übersicht, Benutzer &
Zugriff, Compliance, Mail-Eingang, System) ersetzt. Rollenbasierte
Sichtbarkeit pro Tab unverändert, nur Navigation strukturiert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-06 12:08:53 +02:00
sysopsandClaude Sonnet 5 8bd02facf5 docs(PROJ-67,PROJ-68): Deployment-Status auf Deployed setzen
Manticore-Upgrade (PROJ-67) und sudo-Provisionierung (PROJ-68) auf 131
und 132 verifiziert abgeschlossen; QA/Deployment-Notizen ergänzt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-06 11:47:33 +02:00
sysops 4eba165250 docs(PROJ-66): Backup & Restore Runbook schreiben
docs/BACKUP_RESTORE_RUNBOOK.md deckt beide Sicherungsebenen ab: App-eigenes
CLI-Backup (archivmail backup/restore, PROJ-66) und Infrastruktur-Ebene
(PBS + Sync auf Zweitserver, pct restore). Enthaelt Bitwarden-Keyfile-
Escrow-Anleitung, Pflicht-Verifikationsschritte (reconcile/reindex/
Stichprobe), Rotation-vs-DSGVO-Hinweis und den offenen Punkt "noch kein
Restore-Test durchgefuehrt" als groesste verbleibende Luecke.

AC 8 aus PROJ-66 damit erfuellt; AC 6 (Restore-Test) und AC 7 (Alerting)
bleiben offen.
2026-07-05 21:11:39 +02:00
sysops e19f2e5b6e chore: AppVersion auf 1.0.0 anheben
0.9.1 stand seit Einführung des Versionsschemas fest, obwohl seitdem
PROJ-19 bis PROJ-68 dazugekommen sind (inkl. Breaking Change PROJ-46).
1.0.0 markiert diesen Stand als erstes stabiles Release nach eigenem
Schema (MAJOR: Breaking Changes / große Architekturänderungen).

Modul-Versionen für die zuletzt geänderten Pakete nachgezogen:
storage 1.9->1.10 (PROJ-65/66), api 1.8->1.9 (PROJ-67/68),
auth 1.3->2.0 (PROJ-46 Breaking Change), userstore 1.3->1.4 (PROJ-46).
2026-07-05 20:18:42 +02:00
sysops af897948be fix(PROJ-68): CapabilityBoundingSet blockiert sudo trotz korrekter sudoers-Regel
QA-Re-Diagnose auf 132 fand einen zweiten, unabhängigen Blocker: die
archivmail.service-Unit setzt CapabilityBoundingSet=CAP_NET_BIND_SERVICE
CAP_NET_ADMIN. Das kappt das Capability-Set des GESAMTEN Prozessbaums
inklusive der von exec.Command("sudo", ...) geforkten Kindprozesse - sudo
braucht aber zusaetzlich CAP_SETUID/CAP_SETGID um auf uid/gid 0 zu
wechseln, sonst bricht es ab ("unable to change to root gid: Operation not
permitted"), selbst wenn sudoers korrekt konfiguriert ist.

Ein erster Verifikationsversuch per `runuser -u archivmail -- sudo ...`
hatte faelschlich Erfolg gemeldet, weil runuser den restriktiven
Bounding-Set der Unit nicht traegt - nur ein Test im echten
systemd-Unit-Kontext (systemd-run oder echter API-Call) ist aussagekraeftig.

Fix: CapabilityBoundingSet in update.sh und install.sh um CAP_SETUID
CAP_SETGID erweitert. AmbientCapabilities bleibt unveraendert (der Go-Daemon
selbst soll diese Rechte nie dauerhaft halten, nur der sudo-Kindprozess
braucht sie im Bounding-Set verfuegbar).
2026-07-05 20:10:30 +02:00
sysops 7300a696ca fix(PROJ-68): sudo-Provisionierung für Admin-Dienststeuerung ergänzen
Root Cause für den HTTP-500-Bug beim Manticore-Neustart über den Dienste-Tab:
sudo war auf 132 gar nicht installiert, admin_services_handlers.go ruft aber
für JEDE Dienst-Aktion sudo systemctl auf. Betraf nicht nur Manticore,
sondern alle Dienste in der Whitelist - PROJ-67 hat es nur erstmals sichtbar
gemacht.

install.sh/update.sh installieren jetzt sudo (falls fehlend) und legen
/etc/sudoers.d/archivmail mit NOPASSWD-Regeln für genau die Service-
Whitelist an (archivmail, archivmail-web, manticore, postgresql@17-main,
postfix, nginx) - validiert per visudo -c vor dem Einspielen, damit ein
Bug im Generator nie eine kaputte sudoers-Datei live schaltet. update.sh
zieht das als Backfill für Bestandsinstallationen nach, analog zum
PROJ-67-Upgrade-Pfad-Muster.

archivmail-nft-Helper (externe Zugriffskontrolle) fehlt auf 132 ebenfalls,
aber bewusst nicht Teil dieses Tickets (vermutlich firewall-security-Skill-
Verantwortung).
2026-07-05 19:49:56 +02:00
sysops 4af0e4a280 fix: Modulübersicht mit features/INDEX.md synchronisieren, Versions-Spalte ergänzen
features.ts hatte nur 18 von 67 PROJ-Einträgen mit größtenteils falschem
Status (z.B. PROJ-1 zeigte "In Review" statt "Deployed", PROJ-9 zeigte
"In Progress" statt "Removed") — komplett losgelöst von features/INDEX.md,
offenbar seit den frühen Tagen des Projekts nie mehr aktualisiert.

Vollständig mit INDEX.md abgeglichen (alle PROJ-1 bis PROJ-67 inkl. PROJ-56c),
FeatureStatus um "Removed" erweitert. Neues Feld "version" (manuell gepflegt
pro PROJ, Baseline 1.0) + Tabellenspalte im Modulübersicht-Tab.
2026-07-05 19:44:11 +02:00
sysops 8564d7c11f feat: Versions-Spalte im Dienste-Tab für Superadmin
Bislang war die einzige Möglichkeit, die laufende Manticore-/PostgreSQL-/
Postfix-/nginx-Version zu sehen, SSH + <binary> --version. serviceVersion()
löst das best-effort pro Dienst auf (archivmail/-web: appVersion-Konstante,
manticore: searchd --version, postgresql: psql --version, postfix: postconf
mail_version, nginx: nginx -v). Fehler werden verschluckt (leerer String),
eine unbekannte Version darf den Dienst-Status nicht auf "Fehler" kippen.

manticore war bisher gar nicht in der Dienste-Whitelist (allowedServices) —
jetzt ergänzt, damit es überhaupt in der Liste auftaucht und
start/stop/restart wie die anderen Dienste möglich ist.
2026-07-05 19:12:38 +02:00
sysops bbefa838c3 feat(PROJ-67): Manticore-Version dynamisch aus Repo-Packages-Datei lesen
Statt Version hart zu pinnen, wird bei jedem install.sh-/update.sh-Lauf die
Packages-Datei von repo.manticoresearch.com abgefragt und der letzte
"Package: manticore"-Block (Version+Filename) daraus extrahiert. Bleibt
dadurch automatisch aktuell, ohne den Code bei jeder neuen Manticore-Version
manuell anfassen zu müssen. _MANTICORE_VERSION_FALLBACK greift nur, wenn die
Packages-Datei nicht erreichbar/parsbar ist (Netzwerkfehler, Repo down).

Parser-Bug beim ersten Entwurf gefunden und gefixt: die awk-Regex
"/(^|\n)Package: manticore$/" matchte nie, weil $ in einem Multi-Zeilen-
Record das Ende des GESAMTEN Records verankert, nicht das einer Zeile.
Gefixt durch Split der ersten Zeile und direkten String-Vergleich. Gegen die
echte Packages-Datei getestet (liefert korrekt Version 27.1.5-...).
2026-07-05 18:16:14 +02:00
sysops 4e085238b6 feat(PROJ-67): Manticore-Upgrade-Pfad für Bestandsinstallationen
install.sh/update.sh übersprangen den Manticore-Block komplett, sobald
irgendeine Version schon lief — der Versions-Pin aus dem letzten Fix wirkte
dadurch nie auf existierende Installationen (nur Neuinstallationen). Jetzt
per dpkg --compare-versions: ist die installierte Version älter als
_MANTICORE_VERSION, wird der Dienst gestoppt, das neue Paket eingespielt und
neu gestartet. Downgrade-Schutz durch "lt"-Vergleich.

Spec PROJ-67 dokumentiert die Recherche zum Versionssprung 25.0.0 -> 27.1.5
(u.a. offene Frage zur neuen v27-Auth-Funktionalität) und den geplanten
Produktiv-Test auf 131.
2026-07-05 18:10:53 +02:00
sysops 3428537cd9 fix(deploy): Manticore-Installer auf aktuelles Paketschema+Version aktualisieren
Manticore hat das Debian-Paketschema geändert: früher mehrere
manticoresearch_*-Pakete unter pool/main/m/manticoresearch/, seit ~v25 ein
einziges "manticore"-Paket unter dists/bookworm/main/binary-ARCH/. Beide
Skripte waren zudem hart auf die veraltete Version 6.3.6 gepinnt (aktuell:
27.1.5). GitHub-Release-Fallback entfernt, da GitHub-Releases inzwischen
keine .deb-Assets mehr anhängen (leeres assets[], per API verifiziert) —
repo.manticoresearch.com ist der einzige funktionierende Weg.

Neue Download-URL + Paket-Metadaten (Name/Version/Architektur) gegen den
echten Server verifiziert, beide Skripte mit bash -n auf Syntaxfehler
geprüft. Betrifft nur Neuinstallationen — bestehende Installationen mit
bereits laufendem Manticore überspringen den Installationsblock unverändert.
2026-07-05 18:00:36 +02:00
sysops 55131de81d fix(PROJ-66): Build-Fehler in printHelp() + -force überschreibt keine Hardlinks
BUG-1 (QA): Backticks in der restore-Hilfezeile schlossen das Raw-String-
Literal von printHelp() vorzeitig, Build brach komplett. Backticks durch
einfache Anführungszeichen ersetzt.

BUG-2 (QA): -force bei restore scheiterte an bereits vorhandenen
Hardlink-Zieldateien (os.Link: file exists) — für den Normalfall (Restore
gegen einen PROJ-65-Tenant-Hardlink-Bestand) war -force damit funktionslos.
copyTreePreservingHardlinks() entfernt jetzt eine vorhandene Zieldatei vor
os.Link.
2026-07-04 15:15:54 +02:00
sysops 2b70895a37 feat(PROJ-66): Keyfile-Escrow-Hinweis bei Installation ausgeben
install.sh gibt das frisch generierte Keyfile nach der Erzeugung einmalig
aus (beide Installationspfade), mit Aufforderung es sofort in einen
Passwort-Safe (Bitwarden) zu verschieben. Backup ist ohne dieses Keyfile
wertlos — der Hinweis darf nicht vom "mach ich später" verschluckt werden,
da der Wert danach nirgends mehr sichtbar abrufbar ist.
2026-07-04 15:13:33 +02:00
sysops f3a7dea3cc feat(PROJ-66): CLI-Kommandos archivmail backup/restore
Sichert Store (Hardlinks erhalten, PROJ-65-tauglich ohne Abhängigkeit von
rsync -H), Keyfile, config.yml und PostgreSQL (pg_dump -Fc) konsistent in
ein Zielverzeichnis. Rotation läuft nur nach erfolgreichem Lauf, ein
fehlgeschlagener Backup rotiert nie ein gutes altes Backup weg.

restore ist bewusst konservativ: bricht bei nicht-leerem Store/Keyfile ohne
-force ab, stoppt/startet den Dienst nicht selbst, gibt am Ende die
Pflicht-Verifikationsschritte (reconcile, reindex, Stichprobe) aus.

Ergänzt die vorhandene PBS+Sync-Infrastruktur um einen App-eigenen,
selektiven Restore-Weg. Kein automatischer Cron-Eintrag aktiv (Zielpfad
noch offen), nur als Vorlage in deploy/cron.d/archivmail auskommentiert.
Kein lokaler go build möglich, QA folgt auf Testserver.
2026-07-04 14:09:37 +02:00
sysops ebab716006 docs(PROJ-66): Backup-Strategie-Spec anlegen; PROJ-65 Deployed-Status nachziehen
PROJ-66 (Planned): kein App- oder Cron-Backup für /var/archivmail/store,
Keyfile, PostgreSQL auf 131 und 132 vorhanden. Nutzer-Rückmeldung ergänzt:
Infra-Ebene sichert bereits per Proxmox Backup Server + Sync auf Zweitserver,
das entschärft den Off-Site-Blocker deutlich - verbleibende Kernlücke ist
ein nie getesteter Restore, nicht das fehlende Backup-Ziel. Bitwarden-
Keyfile-Escrow als zusätzlicher, von PBS unabhängiger Wiederherstellungsweg
ergänzt.

PROJ-65: Deploy-Agent hatte Status/QA-Ergebnisse bereits lokal geschrieben,
aber noch nicht committed.
2026-07-04 13:52:05 +02:00
sysops a15fa37619 feat(PROJ-65): Physische Tenant-Trennung im Storage-Layer (Hardlink-Ordner)
Jeder Tenant bekommt ein eigenes Verzeichnis store/tenant_<id>/, das per
Hardlink auf die kanonische content-adressierte Datei zeigt — das bestehende
Cross-Tenant-Dedup-Modell (email_refs M:N, PROJ-32/37) bleibt dadurch
erhalten, kein Speicherplatz-Mehrverbrauch. Neues CLI-Subcommand
`archivmail migrate-tenant-dirs` zieht Bestandsdaten einmalig nach
(idempotent). Zusätzlich neuer Status-Check checkStoragePermissions
(warnt bei zu offenen store_path-Rechten, analog checkEncryption/PROJ-49).

DB-gestützte Zugriffskontrolle bleibt der maßgebliche Zugriffspfad im Code;
die Tenant-Ordner sind eine zusätzliche Defense-in-Depth-Ebene für manuelle
Dateisystem-Audits. Kein lokaler go build möglich, QA folgt auf Testserver.
2026-07-04 13:03:52 +02:00
sysopsandClaude Sonnet 5 cc30440e99 docs(PROJ-46): Status auf Deployed setzen nach Produktiv-Deploy (2026-07-04)
Backend/Frontend erfolgreich auf 192.168.1.131 deployt (update.sh, code war
bereits committed). Deployment-Abschnitt mit Smoke-Test-Ergebnis ergänzt,
Breaking-Change-Hinweis (Tenant-User Login nur noch per E-Mail) ins DEVLOG.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 12:41:08 +02:00
sysopsandClaude Sonnet 5 08f486a28c docs(PROJ-46): QA-Testergebnisse (9/9 PASS auf 192.168.1.132) dokumentieren
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 12:38:55 +02:00
sysops 81744562c3 docs: README auf aktuellen Stand bringen (PROJ-43/52 Deployed, Config-Referenz vervollständigt)
"In Entwicklung" und Funktionsübersicht listeten PROJ-43/PROJ-52 noch als
Planned, obwohl seit 2026-07-04 deployt. Config-Referenz fehlten mehrere
produktiv genutzte Sektionen (server.fqdn, api.trusted_proxies/secure_cookies,
smtp_out, smtp.tenant_routing, storage.retention_days/min_retention_days/
compress, ocr.paused_hours, imap_scheduler, reconciliation, imap_server,
metrics) — jetzt vollständig dokumentiert.
2026-07-04 12:25:26 +02:00
sysops bd727616b6 chore: Screenshots aus dem Repo entfernen
Screenshots dürfen nicht auf Gitea landen, waren in af16138 versehentlich
mit committet. Aus Tracking entfernt (git rm --cached, Dateien bleiben
lokal erhalten) und in .gitignore aufgenommen.
2026-07-04 12:21:17 +02:00
sysops 45ac68564b docs(PROJ-65): Spec für physische Tenant-Trennung im Storage-Layer
Bewertet drei Optionen (Hardlink-Farm pro Tenant, Metadaten-Trennung
dokumentieren, Dedup nur noch pro Tenant) gegen das bestehende
Cross-Tenant-Dedup-Modell (email_refs M:N). Empfehlung: Option B
zuerst, Option A nur bei konkreter Kundenanforderung.
2026-07-04 12:17:17 +02:00
sysops 17633cb86c docs: Migrations-Runbook für Compliance-Erhalt-Check ergänzen (GoBD Punkt 10)
Baseline/Post-Vergleich, PROJ-18-Integritätscheck, Manticore-Konsistenz,
PROJ-52-Reconciliation und Byte-Vergleich als Ablauf nach jeder Schema-/
Index-/Tenant-Migration. Checklist-Punkt 10 auf Erfüllt gesetzt.
2026-07-04 12:14:30 +02:00
sysops 6d67a6bbe7 docs: GoBD-Checklist auf aktuellen Stand bringen, Spec für PROJ-56c nachtragen
Checklist war seit 2026-06-13 nicht aktualisiert: PROJ-48/49/50/51/52 waren
laengst deployt, standen aber noch als fehlend/teilweise drin. PROJ-56c
(Cron-Purge mit Markierungspflicht) war im Code implementiert, hatte aber
nie eine eigene Feature-Spec — nachtraeglich dokumentiert.
2026-07-04 12:12:08 +02:00
sysops a7390151a1 docs: GoBD-Checklist auf aktuellen Stand bringen (PROJ-52, PROJ-56c)
Punkt 1 (Vollständigkeit) war noch als "Teilweise" markiert, obwohl PROJ-52
(Reconciliation-Report) das inzwischen abdeckt. Punkt 7 (Löschsperre)
beschrieb noch den alten Purge() ohne Markierungspflicht; ergänzt um
PROJ-56c Cron-Purge, der nur retain_until < NOW() UND marked_for_deletion
löscht.
2026-07-04 12:07:21 +02:00
sysopsandClaude Sonnet 5 30b7586d94 docs(PROJ-43,PROJ-52): Status auf Deployed setzen nach Produktiv-Deploy
Beide Features wurden auf 192.168.1.131 deployt (Commit 4c92587), inkl. der
zugehörigen QA-Bugfixes (Dry-Run-Adressmatching PROJ-43, days-Clamp PROJ-52).
Deployment-Abschnitte in den Feature-Specs und INDEX.md aktualisiert.

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

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

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

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

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

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 23:55:47 +02:00
sysopsandClaude Sonnet 5 af16138687 docs: README aktualisieren, Dev-Log/Dateiindex/GoBD-Checklist/Screenshots ins Repo
README: Feature-Tabelle und Inhaltsverzeichnis auf aktuellen Stand gebracht
(POP3, OCR, eDiscovery, DSGVO, Retention, LDAP, TOTP, IMAP-Server,
Prometheus, Tenant-Export etc. ergänzt).

Zusätzlich aufgenommen: CODEBASE.md (Dateiindex, Stand 2026-03-31 — vor
PROJ-44 eingefroren, sollte bei Gelegenheit aktualisiert werden), DEVLOG.md
(Session-Log), docs/GOBD_DSGVO_CHECKLIST.md (Compliance-Checkliste),
resume (Session-Notiz), screenshots/.

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

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

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

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

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

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

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

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

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

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 22:48:55 +02:00
sysopsandClaude Sonnet 5 be93614c9f feat(PROJ-52): Vollständigkeits-Reconciliation (Zähl-Report Mailserver vs. Archiv)
Täglicher Cron-Job (archivmail reconcile) berechnet pro Tenant/Quelle
(SMTP-Journal, IMAP-Konto, POP3-Konto, Datei-Import) archivierte Mail-Zahlen,
für IMAP zusätzlich einen Soll/Ist-Vergleich via UID-Tracking. Abweichungen
über Schwellenwert erzeugen Audit-Log-Warnung. Neue Admin-Dashboard-Kachel
"Vollständigkeits-Check" (letzte 7 Tage, Warn-Badge, CSV-Export).

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

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

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

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

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

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 19:59:25 +02:00