Die Anleitung sagt "./scripts/update.sh" - auf Linux kam dort "Permission denied". Die drei .sh-Dateien lagen mit Modus 644 statt 755 im Index. Ursache ist der Entwicklungsrechner: Unter Windows steht core.filemode=false, git nimmt ein fehlendes Ausfuehrungsrecht dort gar nicht wahr. Gemeldet hat es der Betrieb, nicht der Bau. Wer von 1.1.0 oder aelter kommt, braucht einmalig "bash scripts/update.sh" - das alte Skript ist ja noch das nicht ausfuehrbare. Steht jetzt in README und Installationsanleitung. Zusaetzlich setzt update.sh nach dem Umschalten selbst ein chmod +x auf scripts/*.sh. Das faengt den Fall ab, dass jemand Dateien von Hand kopiert und das Recht dabei verliert - genau so kam man bisher an dieses Skript, bevor es in der laufenden Fassung existierte. Neu: tests/skripte.test.ts prueft nicht Verhalten, sondern Verpackung - Ausfuehrungsrecht im Index, Shebang, scripts/ im Docker-Abbild, die Sicherungsskripte in der Compose-Datei. Es ist der zweite Fehler dieser Art (vorher fehlte scripts/ ganz im Abbild, 1.0.1); beide Male war der Code richtig und kein Test sah hin, wie die Dateien beim Server ankommen. Gegenprobe gemacht: mit zurueckgesetztem Recht schlaegt er fehl und nennt die Datei. Nebenbei aufgefallen: scripts/version.mjs datierte in UTC. Diese Fassung waere um 00:08 deutscher Zeit auf den Vortag datiert worden. Rechnet jetzt in Europe/Berlin.
523 lines
24 KiB
Markdown
523 lines
24 KiB
Markdown
# Ä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.1.1] – 2026-08-23
|
||
|
||
### Behoben
|
||
|
||
- **`./scripts/update.sh` endete in „Permission denied".** Die
|
||
Shell-Skripte lagen ohne Ausführungsrecht im Repository (Modus 644 statt
|
||
755). Die Anleitung sagt `./scripts/update.sh` — auf Linux ging genau
|
||
das nicht.
|
||
|
||
Ursache ist der Entwicklungsrechner: Unter Windows steht
|
||
`core.filemode=false`, dort merkt git von einem fehlenden
|
||
Ausführungsrecht nichts. Aufgefallen ist es erst auf dem Server.
|
||
|
||
**Wer von 1.1.0 oder älter kommt**, braucht einmalig den Umweg — das
|
||
alte Skript ist ja noch das nicht ausführbare:
|
||
|
||
```bash
|
||
bash scripts/update.sh
|
||
```
|
||
|
||
Danach stimmt das Recht, und der Punktschrägstrich funktioniert.
|
||
|
||
- **`update.sh` setzt das Recht nach dem Umschalten selbst.** Wer Dateien
|
||
von Hand kopiert hat — etwa um an das Skript zu kommen, bevor es in der
|
||
laufenden Fassung existierte —, verliert es dabei. Ein `chmod +x` nach
|
||
dem Umschalten fängt das ab.
|
||
|
||
- **Das Versionsskript datierte in UTC.** Eine Veröffentlichung nach
|
||
22 Uhr deutscher Sommerzeit bekam im Changelog das Datum des Vortages —
|
||
diese Fassung hier war der erste Fall. Es rechnet jetzt in
|
||
`Europe/Berlin`, wie alles andere in dieser Anwendung auch.
|
||
|
||
### Geprüft
|
||
|
||
- Vier neue Prüfungen (`tests/skripte.test.ts`) sehen sich nicht das
|
||
Programm an, sondern die **Verpackung**: Liegt jedes `.sh` ausführbar im
|
||
Index? Hat es eine Shebang-Zeile? Kommt `scripts/` ins Docker-Abbild?
|
||
Sind die Sicherungsskripte in der Compose-Datei eingehängt?
|
||
|
||
Das ist der zweite Fehler dieser Art — vorher fehlte `scripts/` ganz im
|
||
Abbild (1.0.1). Beide Male war der Code richtig und kein Test schlug an,
|
||
weil keiner hinsah, wie die Dateien beim Server ankommen. Jetzt tut es
|
||
einer. Die Gegenprobe ist gemacht: Mit zurückgesetztem Recht schlägt er
|
||
fehl und nennt die Datei.
|
||
|
||
## [1.1.0] – 2026-08-22
|
||
|
||
### Hinzugefügt
|
||
|
||
- **Anmelden mit Passkey.** Auf der Anmeldeseite steht jetzt unter dem
|
||
Formular ein zweiter Weg: *Mit Passkey anmelden*. Ein Fingerabdruck, ein
|
||
Blick in die Kamera oder die Geräte-PIN — keine E-Mail, kein Passwort,
|
||
kein abgetippter Code.
|
||
|
||
**Der Passkey ersetzt den zweiten Faktor, er kommt nicht zusätzlich.**
|
||
Das ist kein Nachlassen: Ein Passkey verlangt den Besitz des Geräts
|
||
*und* dessen Entsperrung, das sind dieselben zwei Faktoren wie vorher.
|
||
Die Anwendung fordert die Nutzerverifikation ausdrücklich an und weist
|
||
eine Antwort ohne sie zurück. Ein Gerät, das auf blosses Antippen hin
|
||
signiert, kommt nicht herein.
|
||
|
||
In einem Punkt ist er dem bisherigen Weg sogar überlegen: Ein Passkey
|
||
ist an die Adresse gebunden, unter der er eingerichtet wurde. Auf einer
|
||
nachgebauten Anmeldeseite funktioniert er nicht — und Phishing ist der
|
||
übliche Weg, an einen TOTP-Code zu kommen.
|
||
|
||
**Die Authenticator-App muss trotzdem eingerichtet sein**, bevor sich
|
||
ein Passkey anlegen lässt. Ein Passkey hängt an einem Gerät. Ginge das
|
||
verloren und wäre er der einzige Weg hinein, käme niemand mehr an die
|
||
Akte — und darin stehen Unterlagen, die eine betreute Person braucht.
|
||
Der Passkey ist die bequeme Tür, nicht die einzige.
|
||
|
||
Verwaltet werden sie unter **Mein Konto → Passkeys**: einrichten,
|
||
benennen, entfernen. Die Liste zeigt, wann ein Gerät zuletzt benutzt
|
||
wurde und ob der Schlüssel gesichert ist (iCloud, Google, Bitwarden)
|
||
oder nur auf diesem einen Gerät liegt. Einrichten und Entfernen stehen
|
||
im Protokoll, jede Anmeldung nennt den verwendeten Passkey namentlich.
|
||
|
||
- **Bestätigen mit Passkey.** Export, endgültiges Löschen und die
|
||
Benutzerverwaltung verlangen eine frische Anmeldung. Auch die geht jetzt
|
||
mit dem Passkey. Geprüft wird zusätzlich, dass er zum angemeldeten
|
||
Zugang gehört — sonst liesse sich mit dem eigenen Finger eine fremde,
|
||
offen stehende Sitzung freischalten. Genau der Fall, gegen den diese
|
||
Zwischenfrage gebaut ist.
|
||
|
||
### Zu beachten
|
||
|
||
- **Passkeys brauchen `https`.** Der Browser gibt das Verfahren nur in
|
||
einem sicheren Kontext frei. Läuft die Anwendung ohne TLS, erscheint der
|
||
Knopf gar nicht erst, statt beim Klick mit einer kryptischen Meldung
|
||
abzubrechen.
|
||
|
||
- **`AUTH_URL` muss stimmen — jetzt noch mehr als vorher.** Aus ihr wird
|
||
die Kennung abgeleitet, an die der Authenticator den Schlüssel bindet.
|
||
Steht dort eine andere Adresse als die im Browser, lässt sich zwar ein
|
||
Passkey einrichten, aber nie wieder verwenden.
|
||
|
||
**Ein Wechsel der Domain macht alle Passkeys unbrauchbar.** Das ist
|
||
keine Panne, sondern der Phishingschutz. Nach einem Umzug richtet man
|
||
sie neu ein; die Anmeldung mit Passwort und Code bleibt währenddessen
|
||
offen.
|
||
|
||
- **Eine Datenbank-Migration ist nötig** (`20260822160000_passkey_anmeldung`).
|
||
Sie läuft beim Start des Behälters automatisch mit. Bestehende Zugänge
|
||
sind nicht betroffen: Ohne eingerichteten Passkey ändert sich nichts.
|
||
|
||
### Geprüft
|
||
|
||
- 21 neue Prüfungen (`tests/passkey.test.ts`), vor allem für die Herleitung
|
||
von Kennung und Herkunft aus `AUTH_URL`: Port, Schrägstrich am Ende,
|
||
Unterdomain, `http` gegen `https`, `localhost`. Das ist die Stelle, an
|
||
der eine Installation still kaputtginge — dieselbe Fehlerklasse wie
|
||
seinerzeit bei `APP_BIND` und `ENC_KEY_V2`.
|
||
- Drei End-to-End-Tests gegen einen echten Browser (`e2e/passkey.spec.ts`),
|
||
mit Chromiums virtuellem Authenticator: einrichten, abmelden, mit Passkey
|
||
anmelden, Benutzung vermerkt, entfernen. Dazu die Bestätigung vor dem
|
||
Vollexport und der Fall, dass ein Gerät ohne Nutzerverifikation nicht
|
||
hereinkommt.
|
||
|
||
## [1.0.5] – 2026-08-22
|
||
|
||
### Hinzugefügt
|
||
|
||
- **`scripts/update.sh`** — aktualisiert die Anwendung mit einem Befehl.
|
||
|
||
```bash
|
||
./scripts/update.sh # auf die neueste Fassung
|
||
./scripts/update.sh --pruefen # nur nachsehen, nichts ändern
|
||
./scripts/update.sh v1.2.0 # auf eine bestimmte Fassung
|
||
```
|
||
|
||
Es nimmt die Schritte ab, die man von Hand vergisst: Sicherung
|
||
anstoßen und bei Misserfolg **abbrechen**, den Changelog zwischen altem
|
||
und neuem Stand anzeigen, umschalten, neu bauen, warten bis die
|
||
Anwendung antwortet, **die beiden SQL-Skripte ausführen** und zum
|
||
Schluss prüfen, ob wirklich die neue Fassung läuft.
|
||
|
||
Zwei Eigenschaften, die dabei zählen:
|
||
|
||
**Bis zur Rückfrage wird nichts verändert.** Bricht etwas vorher ab —
|
||
Server nicht erreichbar, falsche Versionsangabe — findest du alles so
|
||
vor wie zuvor. Kein Halbzustand.
|
||
|
||
**Eigene Änderungen an versionierten Dateien blockieren nicht.** Im
|
||
Betrieb passt man die `docker-compose.yml` an, bis etwas läuft; genau
|
||
diese Anpassungen sind später oft schon eingearbeitet. Das Skript legt
|
||
sie vor dem Umschalten mit `git stash` beiseite und sagt, wie man sie
|
||
zurückholt. Mit `--verwerfen` werden sie stattdessen weggeworfen. Die
|
||
`.env` bleibt immer unangetastet — sie ist nicht versioniert.
|
||
|
||
Schlägt der Bau fehl, nennt das Skript den Weg zurück auf den
|
||
vorherigen Stand.
|
||
|
||
### Behoben
|
||
|
||
- **Der Port der MinIO-Konsole ließ sich nicht ändern.** Er stand fest auf
|
||
`9001`; lief dort schon etwas, startete der ganze Stapel nicht
|
||
(`port is already allocated`). Jetzt über `MINIO_KONSOLE_PORT` in der
|
||
`.env` einstellbar — dieselbe Möglichkeit, die `APP_PORT` schon hatte.
|
||
|
||
## [1.0.4] – 2026-08-22
|
||
|
||
### Behoben
|
||
|
||
- **Die Ersteinrichtung ließ sich nicht abschließen.** Schritt 3 meldete
|
||
„Bitte prüfe die markierten Felder" — markierte aber keines. Man kam an
|
||
dieser Stelle nicht weiter.
|
||
|
||
Ursache: Das kurze Formular der Ersteinrichtung schickt neun Felder, das
|
||
vollständige unter *Stammdaten* alle. Beide gehen durch dasselbe Schema,
|
||
und die optionalen Felder waren zwar `nullable`, aber nicht `optional` —
|
||
ein Feld, das gar nicht abgeschickt wurde, ist `undefined`, nicht
|
||
`null`. Beanstandet wurden also zwei Dutzend Felder, die auf dem
|
||
Bildschirm nie standen.
|
||
|
||
- **Eine Meldung ohne zugehöriges Feld kann nicht mehr unsichtbar
|
||
bleiben.** Beanstandet die Prüfung ein Feld, das das Formular gar nicht
|
||
gesendet hat, sagt die Anwendung das jetzt ausdrücklich und schreibt es
|
||
ins Serverlog — statt es als Eingabefehler auszugeben, den niemand
|
||
finden kann. Das ist ein Fehler im Programm, und er soll auch so
|
||
aussehen.
|
||
|
||
- **Eine betreute Person ließ sich nicht endgültig löschen.** Beim Löschen
|
||
setzt Postgres den Verweis im Audit-Log auf NULL (`ON DELETE SET NULL`),
|
||
und genau dieses UPDATE hat der Unveränderlichkeits-Trigger abgewiesen.
|
||
Betroffen war damit auch das Leeren des Papierkorbs nach 30 Tagen und
|
||
das Entfernen des Demofalls.
|
||
|
||
Der Trigger erlaubt jetzt genau eine Ausnahme: das Nullen der beiden
|
||
Fremdschlüssel `betreuteId` und `userId`. Jede andere Änderung bleibt
|
||
verboten, auch das Setzen eines Fremdschlüssels auf einen **anderen**
|
||
Wert. Der Nachweis bleibt vollständig — Zeitpunkt, Aktion, Bezeichnung,
|
||
die verschlüsselte Änderung und die Momentaufnahmen von Name und
|
||
E-Mail sind unberührt. Es verschwindet nur der Verweis auf einen
|
||
Datensatz, den es nicht mehr gibt.
|
||
|
||
**Beim Update nötig:** das SQL-Skript erneut ausführen, sonst bleibt der
|
||
alte Trigger stehen.
|
||
|
||
```bash
|
||
docker compose exec app node node_modules/prisma/build/index.js db execute --schema prisma/schema.prisma --file prisma/sql/audit-schutz.sql
|
||
```
|
||
|
||
### Geprüft
|
||
|
||
- Sieben neue Tests (`tests/stammdaten.test.ts`) prüfen genau die
|
||
Formularinhalte der Ersteinrichtung, dazu das vollständige Formular mit
|
||
leeren Feldern und die weiterhin verlangten Pflichtangaben.
|
||
- Der Ablauf ist zusätzlich im Browser durchgespielt worden: Anmeldung,
|
||
zweiter Faktor, Schritt 3, Landung auf dem Dashboard — und die daraus
|
||
abgeleiteten Pflichtfristen samt Ausschlussfrist für die
|
||
Aufwandspauschale.
|
||
- Der geänderte Trigger ist gegen eine laufende Datenbank geprüft:
|
||
Löschen gelingt, Fälschen und Löschen von Einträgen scheitert weiterhin.
|
||
|
||
## [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.1.1...HEAD
|
||
[1.1.1]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.1.0...v1.1.1
|
||
[1.1.0]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.0.5...v1.1.0
|
||
[1.0.5]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.0.4...v1.0.5
|
||
[1.0.4]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.0.3...v1.0.4
|
||
[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
|