# Codex-Brief — DB-Namen-Altlast beseitigen (stiller Daten-GAU) **Priorität: vor der ersten echten `@dr-gold.de`-Migration.** Das ist kein Kosmetikproblem. ## Der Befund | Stelle | `db_path` | |---|---| | `config.json.example` | `mail-graveyard.db` | | `INSTALL.md` (`cp config.json.example config.json`) | → `mail-graveyard.db` | | Code-Default in `ConnectDB` (02-database.go) | `mail-graveyard.db` | | **LIVE auf GoldPi** | **`/app/data/emailforwarder.db`** ← hier liegen die echten Daten | Im `data/`-Verzeichnis liegen aktuell: ``` emailforwarder.db 380.928 <- die ECHTEN Daten emailforwarder.db-wal 4.124.152 <- ACHTUNG: groesser als die DB selbst! emailforwarder.db-shm 32.768 mail-graveyard.db 0 <- Leiche email-forwarder.db 0 <- Leiche ``` **Der Schaden, wenn der Default je greift** (jemand folgt der eigenen INSTALL.md, oder `db_path` fehlt in einer Config): SQLite legt klaglos eine **frische, leere DB** an. Konten weg, `copied`-Historie weg. Der Watcher sieht eine leere `copied`-Tabelle und **kopiert jede Mail erneut in die Ziel-Postfaecher** → **Dubletten quer ueber alle ~20 echten dr-gold-Postfaecher**, lautlos, ohne einen einzigen Fehler im Log. ## Teil A — Die Daten umziehen (einmalige Ops-Aktion) **Ist-Zustand als Baseline (muss danach identisch sein; Jobs duerfen durch laufende Watch-/Deploy-Laeufe weiterzaehlen):** `accounts=19`, `copied=215`, `app_users=3`, `jobs=294` vor Ops, `jobs=296` nach Deploy-Abnahme. Reihenfolge ist wichtig — **das WAL ist der gefaehrliche Teil**: ```sh APP=/mnt/DATA/Containers/Test-Container/Mail-Graveyard-Pod D=$APP/data # 1. BEIDE Container stoppen -> kein Schreiber mehr auf der DB podman stop mail-graveyard mail-graveyard-watch # 2. Backup, bevor irgendwas angefasst wird (inkl. WAL/SHM!) cp -a $D/emailforwarder.db $D/BACKUP-emailforwarder.db cp -a $D/emailforwarder.db-wal $D/BACKUP-emailforwarder.db-wal # 3. WAL in die Haupt-DB falten. OHNE DAS gehen 4 MB Daten verloren. sqlite3 $D/emailforwarder.db "PRAGMA wal_checkpoint(TRUNCATE);" # 4. Gegenpruefen, dass alles noch da ist sqlite3 $D/emailforwarder.db "SELECT (SELECT COUNT(*) FROM accounts), (SELECT COUNT(*) FROM copied), (SELECT COUNT(*) FROM app_users), (SELECT COUNT(*) FROM jobs);" # -> MUSS accounts=19, copied=215, app_users=3 liefern. Wenn nicht: STOPP, # nichts weiter tun. jobs kann waehrend Watch/Deploy weiterwachsen. # 5. Erst jetzt umbenennen (ueberschreibt die 0-Byte-Leiche) mv -f $D/emailforwarder.db $D/mail-graveyard.db rm -f $D/emailforwarder.db-wal $D/emailforwarder.db-shm $D/email-forwarder.db # 6. Config umstellen # $APP/config.json: "db_path": "/app/data/mail-graveyard.db" ``` ## Teil B — Die Ursache beseitigen (Code + Repo) 1. `deploy/goldpi-test-container/mail-graveyard-pod/config.json` **und** `config.json.example`: `db_path` auf `mail-graveyard.db` — damit Doku, Deploy und Live endlich dasselbe sagen. 2. **Kein stilles Anlegen mehr.** Das ist die eigentliche Wurzel: `ConnectDB` erzeugt heute klaglos eine leere DB, wenn die Datei fehlt. Bau eine Sicherung ein: - Wenn die DB-Datei **nicht existiert**, nur dann anlegen, wenn explizit `--init-db` uebergeben wurde. Sonst: **laut scheitern** mit `DB %q existiert nicht — mit --init-db neu anlegen oder db_path pruefen` und Exit ≠ 0. - Damit wird aus einem stillen Daten-GAU ein sofort sichtbarer Startfehler. Dasselbe Prinzip wie beim Watch-Fail-Fast: **permanenter Konfigfehler muss schreien, nicht schweigen.** ## Abnahme 1. Container wieder hoch, dann in der DB pruefen: `accounts=19`, `copied=215`, `app_users=3`, `jobs=289` — **identisch**. 2. **Der entscheidende Test:** Der erste Watcher-Lauf nach dem Umzug muss `copied=0` melden (`total=215 copied=0 errors=0`). → Meldet er stattdessen `copied=215`, ist die Dedup-Historie verloren gegangen und er schreibt gerade Dubletten ins Ziel. **Sofort stoppen** und das Backup aus Schritt 2 zurueckspielen. 3. Login in der Web-UI funktioniert weiter (die 3 Benutzer sind mitgezogen). 4. `go test ./...` gruen. Ich (Claude) verifiziere danach Punkt 1–3 unabhaengig auf GoldPi.