Phase 11: Freigabereife (#16)
Pruefung / pruefung (push) Canceled after 0s
Pruefung / oberflaeche (push) Canceled after 0s

This commit was merged in pull request #16.
This commit is contained in:
2026-09-06 20:05:49 +00:00
parent 91742a0dd7
commit 14cc4de9b8
21 changed files with 2495 additions and 8 deletions
+119 -2
View File
@@ -1,6 +1,6 @@
# Anleitung
Bedienung von FLORIAN, Stand Phase 10 (Version 0.11.0). Die Bilder zeigen die
Bedienung von FLORIAN, Stand Phase 11 (Version 0.12.0). Die Bilder zeigen die
Beispielwehr aus dem Seed und werden mit `npm run screenshots` neu erzeugt.
---
@@ -2253,7 +2253,124 @@ jeweiligen Detailseite sichtbar.
---
## 61. Wenn etwas nicht geht
## 61. Wenn jemand Auskunft über seine Daten verlangt
Jede Person darf verlangen zu erfahren, welche Daten über sie verarbeitet
werden — Art. 15 DSGVO. Die Anfrage muss **innerhalb eines Monats** beantwortet
werden, und sie ist kostenlos.
### So geht es
1. **Mitglieder** öffnen, die Person anklicken.
2. Rechts oben auf **Datenauskunft**.
3. **Auskunft erstellen**.
Danach stehen drei Dinge bereit:
| | Wofür |
|---|---|
| **Die Anzeige** | Was ausgehändigt wird — vor dem Aushändigen |
| **PDF** | Das Schreiben an die Person. Ausdrucken oder als Datei geben |
| **JSON** | Nur, wenn die Person die Daten maschinenlesbar verlangt (Art. 20) |
Das Recht dazu heißt `person.export` und liegt bei Kommandant und
Administrator.
### Was drinsteht
Dreizehn Abschnitte: Stammdaten, Zugang, Rollen, Qualifikationen,
arbeitsmedizinische Vorsorge, Belastungsübungen, Einsatz- und
Übungsbeteiligung, Anwesenheiten, Fahrten, Beiträge, Benachrichtigungswege,
Ausweise.
Über jedem steht, **wozu** diese Daten vorliegen. Das ist kein Beiwerk: Art. 15
verlangt neben den Daten auch die Zwecke und den Hinweis auf die weiteren
Rechte. Eine bloße Liste erfüllt die Auskunftspflicht nicht.
**Auch das Unangenehme steht drin** — ein gemahnter Beitrag, eine nicht
bestandene G26. Eine Auskunft, die auswählt, was gut aussieht, ist keine.
**Leere Abschnitte bleiben stehen.** „Dazu liegen keine Daten vor" ist eine
Auskunft.
**Gesundheitsdaten sind gekennzeichnet.** G26 und Belastungsübungen sind eine
besondere Kategorie nach Art. 9 — das steht im Bericht ausdrücklich dabei.
### Was nicht drinsteht
Was die Person **getan** hat, erscheint nur als Zahl: „12 durchgeführte
Prüfungen", „3 gemeldete Mängel".
Das ist Absicht. Die Prüfprotokolle selbst gehören zum Nachweisbestand der
Feuerwehr und nicht zu den personenbezogenen Daten eines Mitglieds. Würden sie
mitgeliefert, käme jeder über eine Selbstauskunft an die kompletten
Geräteakten — die Auskunftspflicht wäre eine Hintertür.
### Der Vorgang wird protokolliert
Dass eine Auskunft erteilt wurde, steht danach unter **Protokoll**. Das ist
richtig so: die Auskunft legt alles offen, was über einen Menschen gespeichert
ist, einschließlich seiner Gesundheitsdaten. Wer sie erstellt hat und wann,
gehört festgehalten.
### Wenn die Person in zwei Wehren geführt wird
Dann gibt es **zwei** Auskünfte, eine je Wehr. Das ist kein Versehen: jede Wehr
ist eine eigene Verantwortliche im Sinne der Verordnung und kann nur über die
Daten Auskunft geben, die sie selbst führt.
---
## 62. Sicherung und Wiederherstellung
> **Der wichtigste Satz dieses Kapitels:** Eine Sicherung, die nie
> zurückgespielt wurde, ist eine Vermutung.
### Sichern
```bash
npm run sicherung
npm run sicherung -- --ziel D:\backups
```
Gesichert wird die Datenbank **und** der Dateispeicher — Prüfprotokolle,
Einsatzberichte, Fotos, Rechnungen. Beides aus demselben Moment: eine
Datenbank von heute mit Dateien von gestern ergibt Einträge, die auf nichts
zeigen.
Das Ergebnis ist ein Verzeichnis mit Zeitstempel. Es gehört auf ein anderes
Gerät — eine Sicherung auf derselben Festplatte hilft gegen einen
Festplattenfehler nicht.
### Zurückspielen
```bash
npm run wiederherstellen -- --quelle sicherungen/2026-09-05T14-16-48
```
So passiert **nichts**. Es wird nur angezeigt, aus welchem Moment die
Sicherung stammt und wie groß sie ist. Erst mit `--wirklich` am Ende wird
zurückgespielt — und dabei **der gesamte vorhandene Bestand überschrieben**.
### Einmal im Jahr proben
Nicht im Notfall zum ersten Mal. Der Ordner kann leer sein, der Auszug
abgeschnitten, das Passwort falsch — man erfährt es sonst an dem Tag, an dem
man es nicht erfahren will.
Nach dem Zurückspielen prüft das Skript selbst nach, ob die Schutzsperren der
Datenbank wieder stehen. Drei Handgriffe bleiben trotzdem:
1. **Anmelden** — kommt jemand hinein?
2. **Ein Prüfprotokoll öffnen** — ist das PDF da?
3. **Die Mitgliederzahl** mit der Erwartung vergleichen.
Erst danach gilt die Sicherung als geprüft. Das Datum der letzten geglückten
Probe gehört ins Sicherungskonzept.
---
## 63. Wenn etwas nicht geht
| Beobachtung | Wahrscheinliche Ursache | Was hilft |
|---|---|---|
+2 -1
View File
@@ -41,7 +41,8 @@ Faktoren, die in die Schätzung eingehen:
| 8 | Lokale KI | 9–12 PT | 2,5–3 h | **3:40 h** |
| 9 | Kassenverwaltung | 8–11 PT | 2–3 h | **4:10 h** |
| 10 | Mandantenfähigkeit | 4–6 PT | 1–1,5 h | **4:20 h** |
| | **Summe** | **127–170 PT** | **29–38,5 h** | **32:50 h** |
| 11 | Freigabereife | 5–7 PT | 1,5–2 h | **2:40 h** |
| | **Summe** | **132–177 PT** | **30,5–40,5 h** | **35:30 h** |
123–164 Personentage entsprechen etwa **6 bis 8 Monaten Vollzeitarbeit** einer
einzelnen Person. Zum Vergleich: eine kommerzielle Feuerwehrverwaltung kostet
+81 -1
View File
@@ -23,7 +23,87 @@ Die aufgewendete Zeit wandert nach jedem Abschnitt in die Spalte
| Aufräumarbeiten (Issues #10–#12) | 1:20 h | 1 | 04.09.2026 |
| Phase 9 — Kassenverwaltung | 4:10 h | 1 | 04.09.2026 |
| Phase 10 — Mandantenfähigkeit | 4:20 h | 1 | 05.09.2026 |
| **Summe** | **32:50 h** | **13** | |
| Phase 11 — Freigabereife | 2:40 h | 1 | 05.09.2026 |
| **Summe** | **35:30 h** | **14** | |
---
## 2026-09-05 · Phase 11 — Freigabereife
**14:30 – 17:10 · 2:40 h · Version 0.12.0**
### Was entstanden ist
Kein Modul, sondern die drei Software-Voraussetzungen für 1.0.0.
| Bereich | Umfang |
|---|---|
| Auskunft | `lib/dsgvo/auskunft.ts` und `bericht.ts`, `person.auskunft`, Dialog auf der Mitgliederseite |
| Sicherung | `scripts/sicherung.ts`, `wiederherstellen.ts`, `sicherung-zugang.ts`, `sicherung-sperren.ts` |
| Pipeline | `.gitea/workflows/pruefung.yml` mit zwei Aufträgen |
| Tests | 18 neue: 9 gegen die Auskunft, 11 gegen die Sicherung |
### Entscheidungen
**Die Auskunft trennt „über mich" von „von mir".** Was über die Person
gespeichert ist, steht vollständig drin — auch der gemahnte Beitrag und die
nicht bestandene G26. Was die Person *getan* hat, steht als Zahl drin. Die
zwölf Prüfprotokolle, die sie unterschrieben hat, gehören zum Nachweisbestand
der Wehr; vollständig ausgeliefert käme jeder über eine Selbstauskunft an die
Geräteakten, und die Auskunftspflicht wäre eine Hintertür.
**Über jedem Abschnitt steht der Zweck.** Art. 15 Abs. 1 verlangt nicht nur
die Daten, sondern auch Zwecke, Empfänger und den Hinweis auf die weiteren
Rechte. Eine Liste ohne das sieht aus wie eine Auskunft und ist keine — das ist
der Unterschied zwischen einem Datenbankexport und einem Schreiben an einen
Menschen.
**Eine Mutation, keine Abfrage.** Das Erstellen der Auskunft *ist* die
Offenlegung, und die gehört ins Protokoll. Als Abfrage würde sie
zwischengespeichert und mehrfach ausgeführt — sie wäre entweder nicht oder
zwanzigmal vermerkt.
**Sicherung und Wiederherstellung gehören zusammen.** Deshalb sind es zwei
Skripte in einem Zug und nicht eines. Der Probelauf ist die Vorgabe; ohne
`--wirklich` geschieht nichts.
**Eine Liste, zwei Verwendungen.** `sicherung-sperren.ts` treibt sowohl das
Wiederherstellen der Sperren als auch deren Prüfung. Zwei Listen wären zwei
Wahrheiten, und die falsche fiele erst im Notfall auf.
**Die Pipeline baut das eigene Postgres-Image.** Ein Dienst-Container mit
`postgres:17` ließe die Migrationen durchlaufen und scheiterte erst bei der
ersten Umkreissuche — die Pipeline prüfte dann etwas anderes als den Betrieb.
### Wo es gehakt hat
| Problem | Ursache | Lösung |
|---|---|---|
| **Eine Wiederherstellung entfernte alle Unveränderlichkeitsgarantien** | Zuerst `--no-acl` im Dump. Und selbst ohne das Flag greift beim Zurückspielen die Vorgabeprivilegierung aus dem Init-Skript: jede von `pg_restore` neu angelegte Tabelle bekommt alle Rechte, und `GRANT` kann nur hinzufügen | Das Skript setzt die Sperren nach dem Zurückspielen neu und prüft danach nach. Gefunden haben es vier Datenbanktests direkt nach der ersten Rückspielprobe |
| `pg_dump` lehnte die Verbindungszeichenkette ab | Prisma hängt `?schema=public` an — „invalid URI query parameter" | Die URL wird zerlegt, Benutzer und Datenbank gehen als Flags, das Passwort über `PGPASSWORD` |
| Feldnamen im Auskunftssammler stimmten reihenweise nicht | Aus dem Gedächtnis geschrieben statt aus dem Schema gelesen: `alarmierung` statt `alarmiertUm`, `beginn` statt `beginnUm`, `gemeldetVonId` statt `melderId` | Der Typechecker hat sie alle einzeln benannt — zehn Durchgänge, jeder eine Zeile |
| Ein eigener Test war falsch, nicht der Code | `new URL("localhost:5432")` gelingt in Node: „localhost:" gilt als Protokoll | Die Zusicherung prüft jetzt, was wirklich greift — die Protokollprüfung eine Zeile später |
| Ein Vorlagentest fiel im vollen Lauf aus | Er klickte auf „Speichern“, bevor React lief — dann verschickt das Formular sich selbst, und die Fehlerfläche entsteht nie. Unter Last dauert das Hydrieren länger. Dasselbe Muster wie beim Anmeldeskript in Phase 8 | Er wartet jetzt auf einen client-seitig erzeugten Knopf, bevor er klickt |
### Abweichung von der Vorgabe
**Die Pipeline ist nicht erprobt.** Sie ist geschrieben und syntaktisch
geprüft, aber in Gitea war zum Zeitpunkt dieser Phase kein `act_runner`
registriert. Ohne Runner erscheinen die Läufe als „wartend" und laufen nie.
Ob der Ablauf durchläuft, zeigt sich erst, wenn einer eingerichtet ist — das
steht so auch im README, damit niemand sich auf eine Prüfung verlässt, die
nicht stattfindet.
### Nachweise
- `npm run typecheck` — ohne Ausgabe
- `npm run lint` — ohne Befund
- `npm run test` — 599 Tests grün, davon 18 neu
- Auskunft von Hand erzeugt: 13 Abschnitte, 28 Angaben, 58 kB PDF
- **Sicherung und Wiederherstellung vollständig durchgeführt**: ein nach der
Sicherung angelegter Datensatz war danach weg, alle Zahlen stimmten wieder,
und die 599 Tests liefen nach dem Zurückspielen grün — einschließlich derer,
die die Sperren prüfen
---
+22 -2
View File
@@ -20,6 +20,7 @@ Phase 7 ████████████████████ fertig
Phase 8 ████████████████████ fertig 0.9.0
Phase 9 ████████████████████ fertig 0.10.0
Phase 10 ████████████████████ fertig 0.11.0
Phase 11 ████████████████████ fertig 0.12.0
Freigabe ░░░░░░░░░░░░░░░░░░░░ offen 1.0.0
```
@@ -290,15 +291,34 @@ sie schlimmer als keine. Die Aufsicht sieht jede Wehr einzeln.
jemand über die Grenze sieht — und die Kreisebene kann hineinschauen, ohne
etwas anfassen zu können.
## Phase 11 — Freigabereife · fertig
Am 05.09.2026 umgesetzt. Kein Modul, sondern die drei Software-Voraussetzungen
für die Freigabe.
- **Auskunft nach Art. 15 DSGVO.** Das Recht `person.export` stand seit Phase 0
im Katalog und war zugewiesen — umgesetzt war nichts. Ohne Auskunftsseite ist
ein Löschkonzept nicht abnehmbar.
- **Sicherung und Wiederherstellung** mit einer durchgeführten Rückspielprobe.
- **Pipeline** in Gitea Actions: typecheck, lint, Migrationen, Seed und Tests.
Die Rückspielprobe hat sich sofort bezahlt gemacht: der erste Versuch lief
sauber durch und hatte dabei sämtliche Unveränderlichkeitsgarantien der
Datenbank entfernt. Gefunden haben es die Datenbanktests unmittelbar danach —
also genau die Probe, wegen der 1.0.0 sie verlangt.
**Die Wehr kann jetzt:** eine Selbstauskunft erteilen, ihren Bestand sichern
und ihn nachweislich zurückholen.
## 1.0.0 — Freigabe
Kein neues Modul, sondern eine Entscheidung: die Wehr setzt FLORIAN im
Echtbetrieb ein. Voraussetzungen:
- Datenübernahme aus der bisherigen Verwaltung abgeschlossen und abgeglichen
- Sicherungskonzept steht und ist einmal wiederhergestellt worden
- ~~Sicherungskonzept steht und ist einmal wiederhergestellt worden~~ — mit Phase 11 erledigt
- Schulung von Kommandant, Gerätewart und Atemschutzgerätewart erfolgt
- Löschkonzept nach DSGVO abgenommen
- Löschkonzept nach DSGVO abgenommen (die Auskunftsseite dazu gibt es seit Phase 11)
- Der Hinweis zur analogen Atemschutzüberwachung wird bewusst und
dokumentiert abgeschaltet — oder bewusst stehen gelassen