Snapshot (14-snapshot.go) korrekt: VACUUM INTO vor der Wasserlinie, N aus dem
Schnappschuss, MAX(file_offset+frame_len), kein indexed_bytes, stat nur als
Notbremse. Datensatz-Kreuzpruefung (Zeile 145) war nicht verlangt und ist gut.
Reindex-Erhaltung sauber: Position ist Schluessel, Body-Hash ist Bedingung.
Real geprueft: 228 Dateien, mbox_index 121.861 = Produktion, integrity ok.
BEFUND 1 (Blocker): normalizeMessageID aendert die Identitaet fuer Werte mit
verirrtem '>'. Gemessen: 3 Zeilen copied, 2 mbox_index. Die Reindex-Erhaltung
schuetzt den Index, nicht den Live-Pfad - LegacyMessageID ist ebenfalls
neu-normalisiert. Erster Nachtlauf nach Rollout erzeugt 3 lautlose Dubletten.
BEFUND 2: Snapshot-DB ist 0644 und enthaelt 46 Klartext-Passwoerter; die
mbox-Dateien daneben sind 0600.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
uid-delta-brief.md:
UIDVALIDITY+UID waehlt nur KANDIDATEN aus. Body wird weiterhin geladen,
Identitaet weiterhin aus canonicalMessageBytes berechnet. body_sha256
bleibt die Wahrheit; die UID spart nur den Download alter Kandidaten.
backup-brief.md (Pos-81):
DB und mbox sind NICHT symmetrisch abhaengig - mbox ohne DB ist per
Reindex heilbar, DB ohne mbox ist wertlos. Gefaehrlich ist allein
neuere DB + aeltere mbox. Daraus die Reihenfolge-Regel: DB zuerst.
Gemessen: /mnt/DATA ist ext4 ohne LVM -> atomarer Snapshot unmoeglich.
Aber mbox ist strikt append-only (06-mbox.go:61, kein O_TRUNC/Truncate/
Rename), und MAX(file_offset+frame_len) aus mbox_index ist die exakte
Schreib-Wasserlinie - ueber alle 228 mbox-Dateien 0 Abweichungen.
Daraus: VACUUM INTO + Praefix-Kopie = konsistenter Stand OHNE Stillstand.
Falle notiert: mbox_index_state.indexed_bytes ist NICHT die Wasserlinie.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der Volllauf laedt strukturell jede Quellmail, bevor er weiss, ob er sie hat -
die Identitaet ist der Body-Hash. Belegt am Lauf e.klarner: 46.415 gelesen,
10.023 geschrieben. Der Nachtlauf zieht so ~42 GB/Nacht.
Die UID ist die einzige Kennung ohne Body und bricht die Ringabhaengigkeit.
UIDVALIDITY-Pruefung ist dabei nicht Beiwerk, sondern Voraussetzung.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der in rettungslauf-fixes.md beschriebene Befund "~109 byte-verschiedene
Mails mit gleicher Message-ID" war eine HYPOTHESE, die faelschlich als
Befund formuliert wurde.
Messung nach Einbau von body_sha256 (petarus/INBOX.Sent): 518 Quell-Mails,
davon nur 463 eindeutige Identitaeten - exakt der Archivbestand. Die 55
"fehlenden" sind bitgenaue Duplikate an der Quelle (eine Identitaet 10x,
zwei je 6x, fuenf je 4x - Re-Import-Signatur). Es fehlte nie etwas.
Der body_sha256-Schluessel war dennoch richtig: er ist der Beweis der
Bitgleichheit. Waeren die Mails verschieden gewesen, waeren sie beim
kontrollierten Nachlauf archiviert worden.
Lehre im Brief ergaenzt: Eine Zaehlung taeuscht in beide Richtungen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Behebt drei Fehler derselben Klasse: an jeder Stelle wurde derselbe Wert
zweimal berechnet, statt einmal berechnet und weitergereicht - und die
beiden Berechnungen liefen auseinander.
1. Instabiler Ersatzschluessel (bug-hashkey-instabil.md)
Mails ohne Message-ID bekamen sha256 ueber die IMAP-Rohbytes, der
Reindex hashte dieselbe Mail ueber die mbox-gespeicherten Bytes
(>From-Quoting, andere Zeilenenden) -> zwei Schluessel, 4.024
Doppel-Eintraege in copied.
Fix: canonicalMessageBytes() bringt beide Seiten auf eine Form
(>From zurueckdrehen, CRLF->LF, Trailing-Newlines weg). Alle Pfade
(Index, Migration, Viewer, Dedup) nutzen dieselbe Funktion.
body_sha256 in copied + mbox_index, UNIQUE erweitert.
2. Index-Drift (bug-index-drift.md)
Der plain-mbox-Reader las nach Datei-Position statt nach dem
gespeicherten file_offset. Weil SQLITE_BUSY (busy_timeout=0) je
Ordner einen Index-Eintrag verschluckt hatte, war ab dieser Luecke
alles um 1 verschoben: Klick auf Mail X zeigte Mail X+1.
Betroffen genau die 6 Ordner mit Busy-Fehler beim Rettungslauf.
Fix: busy_timeout=10000, Lesen ueber file_offset, --reindex --rebuild.
3. HTML-Vorschau-Panic (bug-htmltotext-panic.md)
replaceCaseInsensitive/stripHTMLBlock indizierten mit Offsets aus
strings.ToLower(s) in s - ToLower ist nicht byte-laengen-erhaltend
(z.B. U+0130). ~0,1% der Mails brachten die Vorschau zum Absturz.
Fix: asciiFoldIndex() sucht direkt auf den Original-Bytes; zusaetzlich
Rohtext-Fallback, damit keine archivierte Mail unsichtbar wird.
Weiter: Archiv-zuerst-Reihenfolge (mbox_done/target_done) - ein
sterbendes Ziel kostet keine Archiv-Kopie mehr; Dedup vergleicht
zusaetzlich den Inhalt und schuetzt byte-verschiedene Varianten.
WICHTIG: Die 62.073 alten Alias-Zeilen in copied bleiben bewusst
erhalten. Sie sehen wie Muell aus, sind aber die Zeilen, auf die der
alte Schluessel matcht - ein Loeschen wuerde Mails erneut in fremde
Postfaecher kopieren.
Verifiziert: go test ./... gruen; 58.051 Archivmails, 0 ohne
copied-Zeile; Drift 0 ueber alle 69 Ordner; 2.000 HTTP-Stichproben
ueber 8 Ordner: 0 falsche Zuordnung, 0 Panics; Watcher 220 + 60 Mails
archived=0 target=0 errors=0. Live als Image fix-identity2-20260716.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>