Briefe: UID ist Cursor (keine Identitaet), Backup-Weg ohne Stillstand

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>
This commit is contained in:
DonVoo 2026-07-16 21:44:20 +02:00
parent 645ce25848
commit e5aacf9b3f
2 changed files with 172 additions and 11 deletions

View file

@ -30,15 +30,31 @@ Doku sauber halten — wir haben sie selbst kurz verwechselt.
## Die Idee
**Die UID ist die einzige Kennung, die ohne Body zu haben ist.** Sie bricht die
Ringabhaengigkeit. `UID FETCH <cursor+1>:* (UID)` kostet einen Roundtrip statt
20 GB.
`UID FETCH <cursor+1>:* (UID)` kostet einen Roundtrip statt 20 GB.
Der Preis: UIDs sind Server-Zusagen, keine Wahrheiten. Sie gelten nur, solange
`UIDVALIDITY` konstant bleibt. **Deshalb ist die UIDVALIDITY-Pruefung kein
Beiwerk, sondern das, was die Abkuerzung ueberhaupt erst zulaessig macht.**
Ohne sie tauschen wir einen teuren Beweis gegen eine billige Annahme — bei
diesem Anbieter die schlechteste aller Ideen.
### Die UID ist ein CURSOR, keine Mail-Identitaet
Das ist die wichtigste Abgrenzung des ganzen Briefes, bitte nicht verwaschen:
- **`UIDVALIDITY + UID` entscheidet nur, WELCHE Mail neu untersucht werden
muss.** Das ist eine billige Vorauswahl von Kandidaten.
- **Erst fuer diese neuen UIDs wird der Body geladen, und daraus weiterhin die
kanonische Identitaet `(normalisierte Message-ID, body_sha256 ueber
canonicalMessageBytes)` berechnet.**
- **`body_sha256` bleibt die Wahrheit.** Die UID ersetzt sie an keiner Stelle.
Sie vermeidet ausschliesslich den erneuten Download alter Kandidaten.
Der Watcher schwaecht die Identitaetsgarantie also **nicht** ab — er spart nur
den Weg zu Kandidaten, die wir ohnehin verwerfen wuerden. Wer die UID zur
Identitaet befoerdert, hat den Brief falsch gelesen: UIDs sind
Server-Zusagen, keine Wahrheiten.
### Warum die UIDVALIDITY-Pruefung nicht optional ist
Die Zusage gilt nur, solange `UIDVALIDITY` konstant bleibt. **Deshalb ist die
UIDVALIDITY-Pruefung kein Beiwerk, sondern das, was die Abkuerzung ueberhaupt
erst zulaessig macht.** Faellt sie weg, tauschen wir einen teuren Beweis gegen
eine billige Annahme — bei diesem Anbieter die schlechteste aller Ideen.
## Was zu bauen ist
@ -63,9 +79,11 @@ Ablauf je Ordner:
Loggen, melden, komplett neu einlesen. Der Fall ist selten und teuer —
genau darum darf er nicht leise passieren.
3. Kein Eintrag vorhanden → Volllauf, danach Cursor setzen.
4. Sonst: `UID FETCH (last_uid+1):* (UID)` → nur diese UIDs mit Body holen und
durch die **unveraenderte** Pipeline schicken:
`AlreadyCopied -> mbox.Append -> dst.Append -> MarkCopied`.
4. Sonst: `UID FETCH (last_uid+1):* (UID)`**nur UIDs, kein Body.** Fuer genau
diese UIDs dann den Body holen und durch die **unveraenderte** Pipeline
schicken: `AlreadyCopied -> mbox.Append -> dst.Append -> MarkCopied`.
Die Identitaet wird dort wie bisher aus dem Body berechnet — der Watcher
liefert Kandidaten, keine Identitaeten.
5. Cursor **erst nach erfolgreichem Durchlauf** aller neuen Mails setzen.
Bricht etwas ab, bleibt der alte Stand stehen. Lieber zweimal lesen als
einmal ueberspringen.