Dokumente werden von keiner Sicherung erfasst #41

Closed
opened 2026-09-01 13:41:56 +00:00 by florian.wilde · 2 comments
Owner

Was fehlt

Der Sicherungsdienst führt täglich um 3:15 Uhr ausschließlich ein pg_dump aus (scripts/sicherung.sh). Die Dokumente liegen im Docker-Volume minio-daten bzw. beim Dateitreiber unter DATEI_SPEICHER_PFAD und werden nicht mitgenommen.

Warum das schwer wiegt

Nach einem Plattenschaden ließe sich die Datenbank vollständig wiederherstellen — mit allen Akteneinträgen, Verweisen und Prüfsummen. Dahinter läge keine einzige Datei. Die Prüfsumme in der Akte belegt dann ein Dokument, das es nicht mehr gibt. Gegenüber dem Betreuungsgericht ist das der schlechteste denkbare Zustand: Die Akte behauptet einen Nachweis, den niemand vorlegen kann.

Bis 31.08.2026 war das folgenlos, weil der Objektspeicher leer war (siehe #41). Seit dem ersten abgelegten Schreiben ist es das nicht mehr.

Umsetzung

Die Dokumente in denselben Lauf aufnehmen wie die Datenbank — gleiche Verschlüsselung, gleiche Prüfsumme, gleiche Aufbewahrungsfrist.

Zwei Punkte, die dabei bedacht werden müssen:

  1. Nicht das rohe Volume einpacken. MinIO schreibt währenddessen weiter; ein tar über das Volumenverzeichnis kann einen halbfertigen Stand erwischen. Sauberer ist mc mirror in ein Zwischenverzeichnis und erst davon die Sicherung.
  2. Beide Treiber abdecken. Der Lauf muss auch mit SPEICHER_TREIBER=datei funktionieren, sonst hängt die Sicherung an der Speicherwahl.

Akzeptanzkriterien

  • Ein Sicherungslauf enthält Datenbank und Dokumente, beides verschlüsselt und mit Prüfsumme.
  • scripts/wiederherstellung.sh stellt beides wieder her; danach ist ein zuvor abgelegtes Dokument über die Oberfläche abrufbar.
  • Der Ablauf ist einmal vollständig durchgespielt und in INSTALLATION.md beschrieben, Wiederherstellung eingeschlossen.
  • SICHERUNG_AUFBEWAHRUNG_TAGE gilt für beides.
  • Schlägt der Dokumententeil fehl, bricht der Lauf sichtbar ab und hinterlässt keine Sicherung, die vollständig aussieht, aber halb ist.
  • Der Selbsttest am Ende prüft beide Teile, nicht nur den Datenbankstand.
## Was fehlt Der Sicherungsdienst führt täglich um 3:15 Uhr ausschließlich ein `pg_dump` aus (`scripts/sicherung.sh`). Die Dokumente liegen im Docker-Volume `minio-daten` bzw. beim Dateitreiber unter `DATEI_SPEICHER_PFAD` und werden **nicht** mitgenommen. ## Warum das schwer wiegt Nach einem Plattenschaden ließe sich die Datenbank vollständig wiederherstellen — mit allen Akteneinträgen, Verweisen und Prüfsummen. Dahinter läge keine einzige Datei. Die Prüfsumme in der Akte belegt dann ein Dokument, das es nicht mehr gibt. Gegenüber dem Betreuungsgericht ist das der schlechteste denkbare Zustand: Die Akte behauptet einen Nachweis, den niemand vorlegen kann. Bis 31.08.2026 war das folgenlos, weil der Objektspeicher leer war (siehe #41). Seit dem ersten abgelegten Schreiben ist es das nicht mehr. ## Umsetzung Die Dokumente in denselben Lauf aufnehmen wie die Datenbank — gleiche Verschlüsselung, gleiche Prüfsumme, gleiche Aufbewahrungsfrist. Zwei Punkte, die dabei bedacht werden müssen: 1. **Nicht das rohe Volume einpacken.** MinIO schreibt währenddessen weiter; ein `tar` über das Volumenverzeichnis kann einen halbfertigen Stand erwischen. Sauberer ist `mc mirror` in ein Zwischenverzeichnis und erst davon die Sicherung. 2. **Beide Treiber abdecken.** Der Lauf muss auch mit `SPEICHER_TREIBER=datei` funktionieren, sonst hängt die Sicherung an der Speicherwahl. ## Akzeptanzkriterien - Ein Sicherungslauf enthält Datenbank **und** Dokumente, beides verschlüsselt und mit Prüfsumme. - `scripts/wiederherstellung.sh` stellt beides wieder her; danach ist ein zuvor abgelegtes Dokument über die Oberfläche abrufbar. - Der Ablauf ist einmal vollständig durchgespielt und in `INSTALLATION.md` beschrieben, Wiederherstellung eingeschlossen. - `SICHERUNG_AUFBEWAHRUNG_TAGE` gilt für beides. - Schlägt der Dokumententeil fehl, bricht der Lauf sichtbar ab und hinterlässt **keine** Sicherung, die vollständig aussieht, aber halb ist. - Der Selbsttest am Ende prüft beide Teile, nicht nur den Datenbankstand.
Author
Owner

Korrektur zum Text oben: Der Verweis muss #42 lauten (leerer Objektspeicher wegen fehlgeschlagener Ablage), nicht #41 — das ist dieses Issue selbst. Beim Anlegen war die Nummer noch nicht vergeben.

Korrektur zum Text oben: Der Verweis muss **#42** lauten (leerer Objektspeicher wegen fehlgeschlagener Ablage), nicht #41 — das ist dieses Issue selbst. Beim Anlegen war die Nummer noch nicht vergeben.
florian.wilde added the in-arbeit label 2026-09-01 13:55:27 +00:00
florian.wilde started working 2026-09-01 13:55:38 +00:00
florian.wilde worked for 8 minutes 2026-09-01 14:03:39 +00:00
Author
Owner

🚀 Umgesetzt und nach main übernommen.

Vorgehen

  1. Beide Skripte gelesen und den Aufbau übernommen: Der Dokumententeil arbeitet genau wie der Datenbankteil — dieselbe Verschlüsselung, dieselbe Prüfsumme, dieselbe Aufbewahrung, derselbe Monatsstand.
  2. Abbruchpfad zuerst: Fehlt das Ablageverzeichnis, bricht der Lauf ab und räumt den angefangenen Datenbankstand weg.
  3. Selbstprüfung erweitert — das Dokumentenarchiv wird entschlüsselt und einmal durchgelesen (tar -tzf), nicht nur angetippt.
  4. Wiederherstellung: leitet die Dokumentendatei aus dem Zeitstempel ab, prüft ihre Prüfsumme, packt aus, und sagt deutlich, wenn zu einer alten Sicherung keine dabei ist.
  5. Elf Prüfungen in tests/skripte.test.ts, gegen vier Mutationen abgesichert.

Zwei Abweichungen von der Aufgabenstellung, beide begründet

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 das Letzte, was man dort will. Das rohe Verzeichnis ist vertretbar, weil MinIO Objekte erst vollständig unter .minio.sys/tmp schreibt und dann umbenennt — ein laufender Upload liegt nie halbfertig im Archiv, er fehlt höchstens.

Nur Lesezugriff, und kein automatisches Zurückschreiben. Der Dienst läuft unbeaufsichtigt per cron. Ein Dienst, der die Daten zerstören kann, die er sichern soll, ist ein Risiko ohne Gegenwert — genau der Fall, gegen den eine Sicherung da ist. Deshalb :ro, und deshalb packt die Wiederherstellung nach ./backups aus und gibt den letzten Handgriff als Einzeiler aus.

Geprüft

Die Kernlogik einmal vollständig von Hand durchgespielt, nicht nur statisch geprüft:

  • packen → verschlüsseln → Selbstprüfung → zurückholen: Inhalt kam bitgleich zurück
  • Klartext im verschlüsselten Archiv nicht auffindbar
  • Selbstprüfung schlägt an bei beschädigtem Archiv und bei falschem Passwort

725 Unit-Tests · tsc sauber · Lint sauber

Beim Ausrollen

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

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

Erwartet: Datenbank gesichert, Dokumente gesichert, Selbstpruefung bestanden - Datenbank und Dokumente.

Der Notnagel von gestern (docker run … tar czf … dokumente-<datum>.tar.gz) kann danach weg — er ist unverschlüsselt und ohne Rotation.

Pull Request: #48 (gemergt)

🚀 **Umgesetzt und nach `main` übernommen.** <!-- claude-status pr: 48 --> **Vorgehen** 1. Beide Skripte gelesen und den Aufbau übernommen: Der Dokumententeil arbeitet genau wie der Datenbankteil — dieselbe Verschlüsselung, dieselbe Prüfsumme, dieselbe Aufbewahrung, derselbe Monatsstand. 2. Abbruchpfad zuerst: Fehlt das Ablageverzeichnis, bricht der Lauf ab **und räumt den angefangenen Datenbankstand weg**. 3. Selbstprüfung erweitert — das Dokumentenarchiv wird entschlüsselt und einmal durchgelesen (`tar -tzf`), nicht nur angetippt. 4. Wiederherstellung: leitet die Dokumentendatei aus dem Zeitstempel ab, prüft ihre Prüfsumme, packt aus, und sagt deutlich, wenn zu einer alten Sicherung keine dabei ist. 5. Elf Prüfungen in `tests/skripte.test.ts`, gegen vier Mutationen abgesichert. **Zwei Abweichungen von der Aufgabenstellung, beide begründet** *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 das Letzte, was man dort will. Das rohe Verzeichnis ist vertretbar, weil MinIO Objekte erst vollständig unter `.minio.sys/tmp` schreibt und dann umbenennt — ein laufender Upload liegt nie halbfertig im Archiv, er fehlt höchstens. *Nur Lesezugriff, und kein automatisches Zurückschreiben.* Der Dienst läuft unbeaufsichtigt per cron. Ein Dienst, der die Daten zerstören kann, die er sichern soll, ist ein Risiko ohne Gegenwert — genau der Fall, gegen den eine Sicherung da ist. Deshalb `:ro`, und deshalb packt die Wiederherstellung nach `./backups` aus und gibt den letzten Handgriff als Einzeiler aus. **Geprüft** Die Kernlogik einmal vollständig von Hand durchgespielt, nicht nur statisch geprüft: - packen → verschlüsseln → Selbstprüfung → zurückholen: Inhalt kam **bitgleich** zurück - Klartext im verschlüsselten Archiv nicht auffindbar - Selbstprüfung schlägt an bei beschädigtem Archiv **und** bei falschem Passwort 725 Unit-Tests · `tsc` sauber · Lint sauber **Beim Ausrollen** `docker compose up -d` erstellt den Sicherungsdienst neu — er braucht die neue Einhängung. Danach einmal von Hand: ```bash docker compose exec sicherung /bin/sh /sicherung.sh ``` Erwartet: `Datenbank gesichert`, `Dokumente gesichert`, `Selbstpruefung bestanden - Datenbank und Dokumente.` **Der Notnagel von gestern** (`docker run … tar czf … dokumente-<datum>.tar.gz`) kann danach weg — er ist unverschlüsselt und ohne Rotation. **Pull Request:** #48 (gemergt)
florian.wilde removed the in-arbeit label 2026-09-01 14:04:31 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Total Time Spent: 8 minutes
florian.wilde
8 minutes
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: florian.wilde/betreuungs-cockpit#41