Files
betreuungs-cockpit/CHANGELOG.md
T
Florian Wilde 9365645f72 fix: Bindeadresse war in der Vorlage stillschweigend vorbelegt
.env.example setzte APP_BIND=127.0.0.1 als fertigen Wert, mitten zwischen
lauter anderen fertigen Werten. Wer die Datei kopiert und seinen Reverse
Proxy auf einem anderen Server betreibt, kommt damit nicht an die
Anwendung heran - und der Fehler sieht aus, als laege es am Proxy.

Der sichere Standard bleibt 127.0.0.1. Er wird nur nicht mehr als
"schon erledigt" praesentiert, sondern als Entscheidung mit drei
benannten Faellen: Proxy daneben, Proxy woanders mit privatem Netz,
Proxy woanders ohne. Beim dritten Fall steht die Firewallregel dabei.

Die Installationsanleitung nennt APP_BIND jetzt schon in Schritt 3, wo
die .env ausgefuellt wird - nicht erst in Schritt 7, wo der Proxy
drankommt. Wer der Anleitung von oben nach unten folgt, stolpert sonst
erst vier Schritte spaeter darueber.

Dazu ein eigener Abschnitt in der Fehlersuche mit den zwei curl-Proben,
die den Unterschied zwischen falscher Bindeadresse und Firewall zeigen -
und dem Hinweis, dass dafuer kein Neubau noetig ist.

Am Programm aendert sich nichts.

Etappe: 8
Phase: Haertung
2026-08-22 14:22:38 +02:00

304 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Änderungen
Alle nennenswerten Änderungen an dieser Anwendung, in umgekehrter
Reihenfolge. Aufbau nach [Keep a Changelog](https://keepachangelog.com/de/1.1.0/),
Versionsnummern nach [Semantic Versioning](https://semver.org/lang/de/).
**Was hier steht:** was sich für dich beim Arbeiten ändert — nicht, welche
Datei angefasst wurde. Wer den technischen Verlauf braucht, findet ihn im
Git-Log; jeder Commit trägt seine Etappe.
**Was die Zahlen bedeuten:**
| Stelle | Wann sie steigt | Was du tun musst |
|---|---|---|
| **Major** (1.x.x → 2.0.0) | Etwas verhält sich anders als vorher, oder eine Migration lässt sich nicht zurücknehmen | Changelog lesen, **vorher sichern**, Zeit einplanen |
| **Minor** (1.0.x → 1.1.0) | Neue Funktionen, alles Bisherige bleibt wie es war | Changelog überfliegen, normal aktualisieren |
| **Patch** (1.0.0 → 1.0.1) | Fehler behoben, sonst nichts | Einfach aktualisieren |
Eine Datenbank-Migration lässt sich **nicht** zurückrollen. Vor jedem
Update ein Backup anstoßen — siehe README, Abschnitt *Sicherung und
Wiederherstellung*.
---
## [Unveröffentlicht]
_Noch nichts._
## [1.0.3] – 2026-08-22
Keine Änderung am Programm — nur an der Konfigurationsvorlage und der
Anleitung. Ein Neubau des Abbilds ist nicht nötig.
### Behoben
- **`.env.example` band die Anwendung stillschweigend an `127.0.0.1`.**
Der Wert stand dort als fertig ausgefüllte Zeile zwischen lauter anderen
fertigen Zeilen. Wer die Datei kopiert hat und seinen Reverse Proxy auf
einem **anderen** Server betreibt, kam nicht an die Anwendung heran —
und der Fehler sah aus, als läge es am Proxy.
Jetzt steht dort eine Entscheidung mit drei benannten Fällen statt eines
Vorgabewerts. Der sichere Standard bleibt `127.0.0.1`; er wird nur nicht
mehr als „schon erledigt" präsentiert.
Für bestehende Installationen genügt eine Zeile in der `.env`:
```bash
APP_BIND=10.0.0.5 # Adresse, über die der Proxy diesen Server erreicht
docker compose up -d
```
### Geändert
- **`docs/INSTALLATION.md`** nennt `APP_BIND` jetzt schon in Schritt 3, wo
die `.env` ausgefüllt wird — nicht erst in Schritt 7, wo der Proxy
drankommt. Dazu ein eigener Abschnitt in der Fehlersuche: „Der Proxy
erreicht die Anwendung nicht", mit den zwei `curl`-Proben, die den
Unterschied zwischen falscher Bindeadresse und Firewall zeigen.
## [1.0.2] – 2026-08-22
### Behoben
- **Die Einrichtung des zweiten Faktors brach mit einem Serverfehler ab**
(„Application error: a server-side exception has occurred"). Im
Serverlog stand `Umgebungsvariable ENC_KEY_V2 fehlt` — obwohl niemand
einen zweiten Schlüssel wollte.
Ursache: `docker-compose.yml` reicht `ENC_KEY_V2` immer an den Behälter
durch, mit **leerem Wert**, wenn in der `.env` keiner steht. Die
Anwendung erkannte Schlüssel aber am Variablennamen statt am Inhalt,
fand also ein leeres `ENC_KEY_V2` und brach ab. Leere
Schlüsselvariablen werden jetzt übersprungen.
Betroffen war jede Stelle, die verschlüsselte Felder schreibt oder
liest — also praktisch alles außer der reinen Anmeldung. Die Anmeldung
ging durch, weil sie ohne Verschlüsselung auskommt; der Fehler trat
deshalb erst auf der nächsten Seite auf.
- **Die Meldung beim Schlüsselwechsel** nennt jetzt, welche Versionen
tatsächlich vorhanden sind, und die richtige Reihenfolge: erst den
neuen Schlüssel eintragen, dann `ENC_KEY_AKTIV` umstellen.
### Hinzugefügt
- **`scripts/anmeldung-pruefen.mjs`** — beantwortet die Frage, warum eine
Anmeldung nicht klappt. Das Formular sagt bewusst nicht, woran es lag,
sonst ließe sich daran ablesen, welche Adressen es gibt. Auf dem Server
darf man es wissen: Jeder Versuch wird mit Grund protokolliert, und das
Skript liest ihn vor — dazu den Zustand des Zugangs, den Stand der
Login-Sperre und die eingestellte `AUTH_URL`.
```bash
docker compose exec app node scripts/anmeldung-pruefen.mjs deine@adresse.de
```
Es ändert nichts, es liest nur.
### Geprüft
- Sieben neue Tests (`tests/umgebung.test.ts`) decken die
Schlüsselauswertung ab, darunter genau die Konstellation aus dem
Fehlerbericht: gesetztes `ENC_KEY_V1`, leeres `ENC_KEY_V2`.
## [1.0.1] – 2026-08-22
### Behoben
- **Betriebsskripte fehlten im Docker-Abbild.** Das Verzeichnis `scripts/`
wurde beim Bauen nie in die Laufzeitstufe übernommen. `docker compose
exec app node scripts/totp-geheimnis.mjs …` endete deshalb mit
`Cannot find module`. Betroffen waren alle Skripte, die im laufenden
Behälter gedacht sind — auch `wartungsschluessel.mjs` und
`schluessel-erzeugen.mjs`.
Nach dem Update funktioniert der Befehl wie dokumentiert. Wer nicht
gleich aktualisieren will, kommt einmalig auch so an das Skript:
```bash
docker compose cp scripts/totp-geheimnis.mjs app:/app/totp-geheimnis.mjs
docker compose exec app node totp-geheimnis.mjs deine@adresse.de
```
### Hinzugefügt
- **`scripts/totp-geheimnis.mjs`** — liest das TOTP-Geheimnis eines Zugangs
aus, um denselben Zugang auf einem zweiten Gerät einzurichten (Handy und
Tablet, oder ein Ersatzgerät). Die Anwendung zeigt das Geheimnis sonst
nur einmal an, beim Einrichten; bisher blieb nur, den zweiten Faktor
zurückzusetzen und alle Wiederherstellungscodes neu zu erzeugen.
Das Skript läuft nur auf dem Server und nur mit Zugriff auf die Datenbank
**und** auf `ENC_KEY_V1`. Wer beides hat, kann ohnehin alles lesen — es
ist also keine Hintertür, sondern erspart eine unnötige Neueinrichtung.
## [1.0.0] – 2026-08-22
Erste vollständige Fassung. Alle acht Etappen umgesetzt, alle
Abnahmekriterien als Test hinterlegt.
### Hinzugefügt
**Der Alltag**
- **Dashboard „Heute"** — beantwortet morgens, was ansteht: Fristen-Ampel
(überfällig / diese Woche / diesen Monat), wer gerade am Zug ist,
offene Nachforderungen des Bezirks, ungeprüfter Posteingang,
unverbuchte Belege, Kennzahlen zu Vermögen und Heimkosten.
- **Fristen** — die gesetzlichen Pflichtfristen entstehen von selbst aus
dem Bestellungsdatum: Vermögensverzeichnis und Anfangsbericht nach drei
Monaten, Jahresbericht und Vermögensübersicht zum Ende jedes
Betreuungsjahres, Aufwandspauschale, Landespflegegeld,
Zuzahlungsbefreiung, Rückkaufswerte. Liste, Monatskalender und ein
ICS-Feed zum Abonnieren im eigenen Kalender.
- **Vorgänge** als Fallakte mit Zeitstrahl über Dokumente, Protokolle,
Fristen und Buchungen. Neun Vorlagen mit vorbefüllter Aufgabenliste,
darunter Heimeinzug, Antrag Hilfe zur Pflege, Wohnungsauflösung,
Hausverkauf, Darlehen nach § 91 SGB XII und Widerspruch gegen einen
Bescheid.
- **Kontakte und Kontaktprotokoll** — Verzeichnis aller Stellen mit
Aktenzeichen, dazu eine Schnellerfassung, die am Handy in unter zwanzig
Sekunden zu bedienen ist.
**Papier**
- **Dokumentenablage** mit Drag & Drop, Sammel-Upload und Handy-Foto.
Texterkennung auf Deutsch, Volltextsuche über alle Schreiben,
Posteingangsbuch mit den Stufen neu → gesichtet → zugeordnet →
beantwortet, Feld für den Ablageort des Papieroriginals.
- Beim Import werden **Absender, Datum, Aktenzeichen, Dokumentart und
eine im Text genannte Frist vorgeschlagen** — mit der Textstelle
daneben, damit man prüfen kann. Übernommen wird nur auf Klick.
- **Belegmappe**: alle Dokumente eines Vorgangs oder Zeitraums als eine
chronologisch sortierte, paginierte PDF mit Deckblatt und
Inhaltsverzeichnis.
**Geld**
- **Kassenbuch** mit Belegzwang, Kategorien, CSV- und CAMT.053-Import.
Harte Trennung zwischen dem Vermögen der betreuten Person und eigenen
Auslagen, mit Warnung bei Buchungen auf ein als privat markiertes Konto.
- **Konten** mit verschlüsselter IBAN und Saldoständen je Stichtag,
**Vermögensposten** mit vollständiger Wert-Historie und Pflichtangabe
zur Wertquelle. Werte werden nie überschrieben.
- **Vermögensverzeichnis (§ 1835 BGB)** und **Vermögensübersicht bzw.
Rechnungslegung (§§ 1859, 1865 BGB)** als druckfertige PDF, in zwei
Ausgabevarianten für befreite und nicht befreite Betreuer.
**Behörde**
- **Sozialhilfe-Modul** für das Verfahren beim Bezirk: Antragsakte,
Nachforderungs-Tracker mit Fortschrittsbalken, vorbefüllte Checkliste
der Standardunterlagen mit Begründung, warum der Träger sie will.
- **Bescheid-Prüfung** mit Berechnung der Rechtsbehelfsfrist ab dem
Zugangsdatum, einschließlich Wochenende, bayerischer Feiertage und dem
Sonderfall fehlender Rechtsbehelfsbelehrung. Der Rechenweg wird
ausgegeben.
- **Heimkosten-Gegenüberstellung** Monat für Monat: Kosten gegen
Pflegekasse, Leistungszuschlag nach § 43c SGB XI, Rente und
Sozialhilfeanteil — die Deckungslücke wird sichtbar.
- **Schonvermögens-Bewertung** je Posten (verwertbar / geschützt /
strittig) mit Begründungsfeld und Textbausteinen zu § 90 SGB XII.
- **Katalog weiterer Leistungen**: Landespflegegeld, Zuzahlungsbefreiung,
Rundfunkbeitragsbefreiung, Schwerbehindertenausweis, Grundsicherung.
**Substanz**
- **Immobilie** mit Grundbuchdaten, Belastungen nach Abteilung II und
III, Wert-Historie, Status im Sozialhilfeverfahren und einer
Pflichten-Checkliste bei Leerstand — zehn Punkte, jeder mit Begründung.
- **Versicherungen und Verträge** mit Kündigungsfristen-Rechner, der den
spätesten Absendetag nennt, Anschreiben zur Rückkaufswert-Anfrage mit
automatischer Wiedervorlage und einem Kündigungs-Assistenten.
- **Heim und Pflege** mit Heimvertrag, Leistungszuschlag-Staffel,
Pflegegrad-Historie, Abwesenheitstagen und einem Gesundheitsverlauf mit
COPD-Bezug: Exazerbationen, Sauerstoff, Stürze, Krankenhaus,
Hilfsmittel, Impfungen nach STIKO-Plan.
**Ausgabe**
- **Jahresbericht (§ 1863 BGB)** als Entwurf zum Überarbeiten, gespeist
aus Kontaktprotokollen, Gesundheitsereignissen und Vorgangsstatus.
Ausgabe als PDF und als DOCX.
- **Unterlagenpaket für den Bezirk**: die im Tracker markierten
Dokumente als eine PDF mit Anschreiben und Inhaltsverzeichnis.
- **Vollexport** als ZIP mit allen Originaldateien, allen Daten als
entschlüsseltes JSON, den erzeugten Berichten, einer LIESMICH und
SHA-256-Prüfsummen.
- **Wissensbasis** mit 37 Hinweiskarten, pflegbar als JSON-Datei ohne
Neustart. Jede mit Rechtsgrundlage, Link und dem stehenden Vermerk,
dass sie keine Rechtsberatung ersetzt.
**Verwaltung**
- **Mitleser-Rolle** mit modulweiser Freigabe und ausdrücklicher Warnung
bei Gesundheit, Finanzen und Sozialhilfe.
- **Papierkorb** mit 30 Tagen Aufbewahrung.
- **Wartungslauf** über `/api/wartung`: Fristerinnerungen per E-Mail,
Papierkorb leeren, alte Anmeldeversuche entfernen.
### Sicherheit
- **Pflicht-Zweitfaktor** (TOTP nach RFC 6238). Lässt sich nicht
abschalten. Acht Wiederherstellungscodes, einzeln Argon2id-gehasht.
- **Anwendungsseitige Feldverschlüsselung** mit AES-256-GCM für
Diagnosen, den ermittelten Willen, IBANs, Versicherungs-, Renten- und
Steuernummern sowie alle Freitext-Notizen. Der Feldname wird
mitauthentifiziert — ein Geheimtext lässt sich nicht von einem Feld in
ein anderes umhängen. Schlüsselrotation ohne Datenverlust vorgesehen.
- **Argon2id** nach OWASP-Empfehlung, mit automatischem Nachziehen bei
späterer Parametererhöhung.
- **Rate-Limiting** am Login nach E-Mail und Anschluss. Die Sperre wird
geprüft, bevor überhaupt gerechnet wird, und die Antwortzeit ist
gestreckt — sie verrät nicht, welche Adressen existieren.
- **Unveränderliches Audit-Log**: ein Datenbank-Trigger weist UPDATE und
DELETE ab, auch bei direktem Zugriff mit `psql`.
- **Strenge Content-Security-Policy** mit Nonce pro Anfrage. Keine
externen Schriften, kein CDN, keine Tracker — nachgewiesen durch einen
Test, der jede Anfrage an einen fremden Host als Fehler wertet.
- **Uploads** werden an den Magic Bytes geprüft, nicht an Endung oder
gemeldetem MIME-Typ. Ausgeliefert wird nur über kurzlebige signierte
URLs, immer als Anhang mit `nosniff`.
- **Erneute Anmeldung** vor Export, endgültigem Löschen und
Rollenänderungen. Ein Passwortwechsel beendet alle offenen Sitzungen.
### Betrieb
- Docker Compose mit Anwendung, PostgreSQL, MinIO und Sicherungsdienst.
**Ohne Reverse Proxy** — der ist auf dem Zielserver vorhanden. Die
Datenbank hat keine Portfreigabe.
- **Tägliche verschlüsselte Sicherung** um 03:15 Uhr mit Selbstprüfung:
lässt sich die Datei nicht wieder entschlüsseln, endet der Lauf mit
Fehler statt mit einem stillen Scheinerfolg.
- Verarbeitungsverzeichnis und Datenschutzhinweise als ausfüllbare
Textbausteine.
- Bauprotokoll aus den Commit-Trailern.
### Bekannte Einschränkungen
- Die Texterkennung ist gegen ein echtes Tesseract **nicht** end-to-end
geprüft. Der Weg „nicht verfügbar, Upload funktioniert trotzdem" ist
getestet.
- Der CAMT.053-Import ist nur gegen selbst gebaute Beispiele geprüft, nicht
gegen einen echten Bankauszug.
- Das Kostenkonto der Immobilie wertet über Buchungskategorien aus und
wäre bei einem **zweiten** Grundstück falsch. Die Oberfläche sagt das
an der Auswertung dazu.
- Eine Aufgabe aus einer Vorgangs-Vorlage lässt sich nicht entfernen —
passt sie im Einzelfall nicht, bleibt sie offen stehen.
- `@react-pdf/renderer` braucht in diesem Abhängigkeitsbaum eine Krücke
(`src/lib/pdf/standardschrift.ts`), weil seine Unterabhängigkeiten für
Standardschriften kein Schriftobjekt mehr liefern.
Was davon wann angegangen wird, steht in [`docs/ROADMAP.md`](docs/ROADMAP.md).
---
[Unveröffentlicht]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.0.3...HEAD
[1.0.3]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.0.2...v1.0.3
[1.0.2]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.0.1...v1.0.2
[1.0.1]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.0.0...v1.0.1
[1.0.0]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/releases/tag/v1.0.0