Fix #41: Dokumente mitsichern #48

Merged
florian.wilde merged 1 commits from fix/41-dokumente-sichern into main 2026-09-01 14:04:04 +00:00
Owner

Closes #41

Was jetzt passiert

Je Sicherungslauf entstehen zwei verschlüsselte Dateien mit demselben Zeitstempel:

cockpit_2026-09-01_0315.dump.enc        <- Akte, Fristen, Buchungen
dokumente_2026-09-01_0315.tar.gz.enc    <- Bescheide, Schreiben, Belege

Beide mit Prüfsumme, beide in der Aufbewahrung, beide im Monatsstand, beide in der Selbstprüfung. Schlägt der Dokumententeil fehl, bricht der Lauf ab und räumt den angefangenen Datenbankstand weg.

Zwei Entscheidungen, die vom Issue abweichen

Kein mc mirror. Der MinIO-Client fehlt im Sicherungsbehälter und müsste bei jedem Lauf aus dem Netz geholt werden — eine Internetabhängigkeit im Sicherungspfad ist genau das, was man dort nicht will. Stattdessen wird das Verzeichnis direkt eingepackt. Das ist vertretbar, weil MinIO ein Objekt erst vollständig unter .minio.sys/tmp schreibt und dann umbenennt: Ein laufender Upload liegt nie halbfertig im Archiv, er fehlt höchstens. Derselbe Weg deckt den Dateitreiber mit ab.

Nur Lesezugriff. Der Dienst bekommt das Ablageverzeichnis mit :ro. Er läuft unbeaufsichtigt per cron; ein Fehler im Skript oder ein kompromittierter Behälter würde sonst Sicherung und Bestand auf einmal treffen. Deshalb schreibt die Wiederherstellung die Dateien auch nicht selbst an ihren Platz, sondern packt sie nach ./backups aus und gibt den letzten Handgriff als Einzeiler aus.

Geprüft

Die Kernlogik von Hand durchgespielt — packen, verschlüsseln, Selbstprüfung, zurückholen:

  • Inhalt kam bitgleich zurück (diff -r)
  • Klartext im Archiv nicht auffindbar
  • Selbstprüfung schlägt an bei beschädigtem Archiv und bei falschem Passwort

Dazu elf Prüfungen in tests/skripte.test.ts, gegen vier Mutationen getestet: Dokumententeil entfernt · Abbruch entfernt · Aufräumen halbiert · Schreibrecht erteilt — jede wird rot.

725 Unit-Tests, tsc und Lint sauber.

Nach dem Ausrollen

docker compose up -d erstellt den Sicherungsdienst neu — er braucht die neue Einhängung. Danach einmal von Hand prüfen:

docker compose exec sicherung /bin/sh /sicherung.sh

Erwartet werden die Zeilen Datenbank gesichert, Dokumente gesichert und Selbstpruefung bestanden - Datenbank und Dokumente.

Closes #41 ## Was jetzt passiert Je Sicherungslauf entstehen zwei verschlüsselte Dateien mit demselben Zeitstempel: ``` cockpit_2026-09-01_0315.dump.enc <- Akte, Fristen, Buchungen dokumente_2026-09-01_0315.tar.gz.enc <- Bescheide, Schreiben, Belege ``` Beide mit Prüfsumme, beide in der Aufbewahrung, beide im Monatsstand, beide in der Selbstprüfung. Schlägt der Dokumententeil fehl, bricht der Lauf ab und räumt den angefangenen Datenbankstand weg. ## Zwei Entscheidungen, die vom Issue abweichen **Kein `mc mirror`.** Der MinIO-Client fehlt im Sicherungsbehälter und müsste bei jedem Lauf aus dem Netz geholt werden — eine Internetabhängigkeit im Sicherungspfad ist genau das, was man dort nicht will. Stattdessen wird das Verzeichnis direkt eingepackt. Das ist vertretbar, weil MinIO ein Objekt erst vollständig unter `.minio.sys/tmp` schreibt und dann umbenennt: Ein laufender Upload liegt nie halbfertig im Archiv, er fehlt höchstens. Derselbe Weg deckt den Dateitreiber mit ab. **Nur Lesezugriff.** Der Dienst bekommt das Ablageverzeichnis mit `:ro`. Er läuft unbeaufsichtigt per cron; ein Fehler im Skript oder ein kompromittierter Behälter würde sonst Sicherung und Bestand auf einmal treffen. Deshalb schreibt die Wiederherstellung die Dateien auch nicht selbst an ihren Platz, sondern packt sie nach `./backups` aus und gibt den letzten Handgriff als Einzeiler aus. ## Geprüft Die Kernlogik von Hand durchgespielt — packen, verschlüsseln, Selbstprüfung, zurückholen: - Inhalt kam **bitgleich** zurück (`diff -r`) - Klartext im Archiv nicht auffindbar - Selbstprüfung schlägt an bei beschädigtem Archiv **und** bei falschem Passwort Dazu elf Prüfungen in `tests/skripte.test.ts`, gegen vier Mutationen getestet: Dokumententeil entfernt · Abbruch entfernt · Aufräumen halbiert · Schreibrecht erteilt — jede wird rot. **725 Unit-Tests**, `tsc` und Lint sauber. ## Nach dem Ausrollen `docker compose up -d` erstellt den Sicherungsdienst neu — er braucht die neue Einhängung. Danach einmal von Hand prüfen: ```bash docker compose exec sicherung /bin/sh /sicherung.sh ``` Erwartet werden die Zeilen `Datenbank gesichert`, `Dokumente gesichert` und `Selbstpruefung bestanden - Datenbank und Dokumente.`
florian.wilde added 1 commit 2026-09-01 14:03:56 +00:00
Der Sicherungsdienst machte taeglich ein pg_dump und sonst nichts. Nach
einem Plattenschaden waere die Akte vollstaendig wiederhergestellt worden
- mit allen Eintraegen, Verweisen und Pruefsummen, aber ohne eine einzige
Datei dahinter. Die Pruefsumme in der Akte haette dann ein Dokument
belegt, das es nicht mehr gibt. Gegenueber dem Betreuungsgericht ist das
der schlechteste denkbare Zustand.

Je Lauf entstehen jetzt zwei verschluesselte Dateien mit demselben
Zeitstempel: der Datenbankstand und ein Archiv des Ablageverzeichnisses.
Beide mit Pruefsumme, beide in der Aufbewahrung, beide im Monatsstand,
beide in der Selbstpruefung.

Schlaegt der Dokumententeil fehl, bricht der Lauf ab und raeumt den
angefangenen Datenbankstand wieder weg. Eine Sicherung, die nur die halbe
Wahrheit enthaelt, aber vollstaendig aussieht, ist schlimmer als gar
keine: Man verlaesst sich darauf und merkt es erst im Ernstfall.

## Abweichung von der urspruenglichen Idee

Im Issue stand "mc mirror statt rohem Verzeichnis". Beim Umsetzen zeigte
sich, dass der MinIO-Client in diesem Behaelter fehlt und bei jedem Lauf
aus dem Netz geholt werden muesste. Eine Internetabhaengigkeit im
Sicherungspfad ist genau das, was man dort nicht will.

Stattdessen wird das Verzeichnis direkt eingepackt. Das ist vertretbar,
weil MinIO ein Objekt erst vollstaendig unter .minio.sys/tmp schreibt und
dann an seinen Platz umbenennt: Ein laufender Upload liegt nie halbfertig
im Archiv, er fehlt hoechstens. Derselbe Weg deckt den Dateitreiber mit
ab.

## Nur lesend

Der Sicherungsdienst bekommt das Ablageverzeichnis mit ":ro" eingehaengt.
Er laeuft unbeaufsichtigt per cron; ein Fehler im Skript oder ein
kompromittierter Behaelter wuerde sonst Sicherung und Bestand auf einmal
treffen - genau der Fall, gegen den eine Sicherung da ist.

Deshalb schreibt die Wiederherstellung die Dateien auch nicht selbst an
ihren Platz, sondern packt sie nach ./backups aus und gibt den letzten
Handgriff als Einzeiler aus. In ein laufendes MinIO hineinzuschreiben
wuerde dessen Datenbestand ohnehin beschaedigen.

## Geprueft

Die Kernlogik einmal von Hand durchgespielt: packen, verschluesseln,
Selbstpruefung, zurueckholen - der Inhalt kam bitgleich zurueck, der
Klartext war im Archiv nicht auffindbar, und die Selbstpruefung schlug
sowohl bei einem beschaedigten Archiv als auch bei falschem Passwort an.

Dazu elf Pruefungen in tests/skripte.test.ts gegen vier Mutationen:
Dokumententeil entfernt, Abbruch entfernt, Aufraeumen halbiert,
Schreibrecht erteilt - jede wird rot.

Refs #41
florian.wilde merged commit dbc24d965d into main 2026-09-01 14:04:04 +00:00
florian.wilde deleted branch fix/41-dokumente-sichern 2026-09-01 14:04:04 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: florian.wilde/betreuungs-cockpit#48