Passkeys (WebAuthn/FIDO2) als zweiter Anmeldeweg - auf der Anmeldeseite und bei der erneuten Bestaetigung vor sensiblen Aktionen. Verwaltet unter "Mein Konto". Der Passkey ERSETZT den zweiten Faktor, statt zu ihm hinzuzukommen. Das ist tragbar, weil er zwei Faktoren in sich vereint: Besitz des Geraets und dessen Entsperrung. Damit das keine Annahme bleibt, wird die Nutzerverifikation angefordert (userVerification: 'required') und serverseitig nachgeprueft - eine Antwort ohne sie wird abgewiesen. TOTP muss vorher eingerichtet sein. Ein Passkey haengt an einem Geraet; waere er der einzige Weg hinein, koennte ein verlorenes Handy die Akte schliessen. Aufbau: - Die Pruefung laeuft vollstaendig im Credentials-Provider "passkey", nicht in der Server Action davor. Ein "war schon geprueft" ueber die Grenze zu reichen waere die Stelle, an der sich Anmeldungen faelschen lassen. - Challenges liegen serverseitig und werden per DELETE genau einmal verbraucht - die Datenbank entscheidet, wer sie bekommt. - Bereichskennung und Herkunft kommen aus AUTH_URL, nicht aus einer zweiten Konfigurationsquelle. - Ohne https wird der Knopf gar nicht erst angeboten. - Rate-Limiting, Kontosperre und Audit-Log gelten unveraendert; die Anmeldung nennt den verwendeten Passkey namentlich. Zwei Anmerkungen zur Migration: - "prisma migrate diff" wollte zusaetzlich die Trigramm-Indizes aus prisma/sql/suche.sql loeschen, die Prisma nicht kennt. Die Zeilen sind entfernt und im Migrationskopf vermerkt - ein DROP haette die unscharfe Suche stillgelegt, ohne dass etwas fehlgeschlagen waere. - "prisma format" hat das Schema durchgaengig neu ausgerichtet. Ohne Whitespace betrachtet sind es 88 hinzugefuegte Zeilen und keine geloeschte. Geprueft: 21 Einheitstests, drei End-to-End-Tests gegen Chromiums virtuellen Authenticator (einrichten, anmelden, bestaetigen, entfernen, Geraet ohne Verifikation abgewiesen), beide Geraeteprofile. 496 Tests, null Typfehler, Produktionsbau steht. Nebenbei: Die Zahlen im README waren veraltet (24 statt 33 Modelle, 46 statt 79 Seiten). Sie stehen jetzt mit dem Befehl daneben, mit dem man sie nachzaehlt.
295 lines
11 KiB
Markdown
295 lines
11 KiB
Markdown
# Roadmap
|
|
|
|
Was als Nächstes drankommt, und warum in dieser Reihenfolge.
|
|
|
|
**Maßstab ist der Alltag, nicht die Vollständigkeit.** Ein Punkt steht
|
|
weit oben, wenn er entweder etwas Falsches richtigstellt oder jeden Monat
|
|
Zeit spart. Er steht weit unten, wenn er nur schön wäre.
|
|
|
|
Diese Datei ist eine Absichtserklärung, kein Vertrag. Was sich im Betrieb
|
|
als wichtiger herausstellt, rutscht nach oben.
|
|
|
|
Stand: 22.08.2026 · Aktuelle Fassung: **1.1.0** ([CHANGELOG](../CHANGELOG.md))
|
|
|
|
---
|
|
|
|
## Woher die Punkte kommen
|
|
|
|
Beim Bauen sind **44 Schema-Wünsche** aufgelaufen — Stellen, an denen das
|
|
Datenmodell etwas nicht abbildet, was die Fachlogik gebraucht hätte. Sie
|
|
liegen einzeln und begründet in [`schema-wuensche/`](schema-wuensche/),
|
|
nach Modul getrennt. Diese Roadmap sortiert sie nach Dringlichkeit und
|
|
bündelt sie zu Releases, die sich in einem Rutsch migrieren lassen.
|
|
|
|
Dazu kommen die bekannten Einschränkungen aus dem Changelog und das, was
|
|
sich im Betrieb noch zeigen wird.
|
|
|
|
---
|
|
|
|
## 1.1 — Was heute noch falsch sein kann
|
|
|
|
**Ziel:** Kein Wert in der Anwendung soll unter ungünstigen Umständen
|
|
falsch sein, ohne dass man es merkt. Das ist die einzige Art von Fehler,
|
|
die man einem Betreuungsgericht nicht erklären kann.
|
|
|
|
### Kostenkonto der Immobilie richtigstellen
|
|
|
|
`Buchung` hat kein `immobilieId`. Das Kostenkonto wertet deshalb über
|
|
Buchungskategorien aus — bei **einem** Grundstück richtig, bei einem
|
|
zweiten still falsch. Die Oberfläche sagt das derzeit an der Auswertung
|
|
dazu; das ist ein Pflaster, keine Lösung.
|
|
|
|
*Aufwand: klein. Migration: ein Feld, ein Index.*
|
|
|
|
### Umbuchungen kennen ihr Gegenkonto
|
|
|
|
Eine Umbuchung zwischen zwei Konten erscheint heute als zwei unverbundene
|
|
Buchungen. In der Rechnungslegung sieht das aus wie eine Ausgabe und eine
|
|
Einnahme — und wer nachrechnet, fragt zu Recht nach.
|
|
|
|
*Aufwand: klein. Migration: ein selbstbezüglicher Fremdschlüssel.*
|
|
|
|
### Dublettenschutz beim Import ohne Konto
|
|
|
|
Der Schutz vor Doppelbuchungen greift über `(kontoId, importReferenz)`.
|
|
Ist kein Konto zugeordnet, greift er nicht — ein zweimal eingelesener
|
|
Auszug erzeugt dann doppelte Buchungen.
|
|
|
|
*Aufwand: klein. Migration: partieller eindeutiger Index.*
|
|
|
|
### Rückkaufswert am Vertrag
|
|
|
|
Der Wert hängt heute am Vermögensposten. In der Vertragsübersicht steht
|
|
deshalb kein Betrag — ausgerechnet dort, wo man ihn beim Telefonat mit dem
|
|
Versicherer braucht.
|
|
|
|
*Aufwand: klein.*
|
|
|
|
### Genau eine Zielspalte je Dokumentverknüpfung
|
|
|
|
`DokumentVerknuepfung` hat zwölf mögliche Zielspalten; dass genau eine
|
|
gesetzt ist, erzwingt bisher nur die Anwendung. Ein CHECK-Constraint macht
|
|
daraus eine Zusage, die auch bei direktem Datenbankzugriff hält.
|
|
|
|
*Aufwand: klein. Migration: ein Constraint.*
|
|
|
|
### Papierkorb für Saldo- und Wertstände
|
|
|
|
Beide Modelle haben kein `geloeschtAm`. Ein versehentlich eingetragener
|
|
Kontostand lässt sich nur endgültig löschen — was der Zusage widerspricht,
|
|
dass Löschen 30 Tage rückgängig zu machen ist.
|
|
|
|
*Aufwand: klein.*
|
|
|
|
### Aufgaben aus Vorlagen entfernen können
|
|
|
|
Passt eine Aufgabe aus einer Vorgangs-Vorlage im Einzelfall nicht, bleibt
|
|
sie dauerhaft offen stehen und verfälscht jede Fortschrittsanzeige.
|
|
|
|
*Aufwand: klein.*
|
|
|
|
---
|
|
|
|
## 1.2 — Weniger tippen
|
|
|
|
**Ziel:** Die Handgriffe, die sich jeden Monat wiederholen, kürzer machen.
|
|
|
|
### Nachforderungen mit stabilem Schlüssel
|
|
|
|
Der Dublettenschutz beim Übernehmen der Standardcheckliste läuft über die
|
|
Bezeichnung. Wer eine Zeile umbenennt, bekommt sie beim nächsten Mal
|
|
doppelt.
|
|
|
|
### Bescheid und Frist verbinden
|
|
|
|
Aus einem Bescheid entsteht die Widerspruchsfrist heute über einen
|
|
Textschlüssel statt über einen Fremdschlüssel. Ändert sich das
|
|
Zugangsdatum, wandert die Frist nicht mit.
|
|
|
|
### Statuswechsel eines Vorgangs als eigene Tabelle
|
|
|
|
Der Zeitstrahl liest Statuswechsel aus dem entschlüsselten Audit-Log. Das
|
|
funktioniert, ist aber langsam und hängt an einem Format, das eigentlich
|
|
nur Nachweis sein soll.
|
|
|
|
### Wer hat was erfasst
|
|
|
|
Fristen, Saldo- und Wertstände tragen kein Feld für den erfassenden
|
|
Benutzer. Bei einer Betreuung zu zweit ist das die erste Frage.
|
|
|
|
### Ansprechpartner am Vorgang
|
|
|
|
Die Sachstandsanfrage kann namentlich anreden, bekommt den Ansprechpartner
|
|
mangels Feld aber nicht übergeben.
|
|
|
|
### Inventarliste als eigenes Modell
|
|
|
|
Wertgegenstände hängen heute an Freitext und Fotos. Für die
|
|
Wohnungsauflösung wäre eine Liste mit Bezeichnung, Raum, geschätztem Wert
|
|
und Verbleib das richtige Werkzeug.
|
|
|
|
### Pflegegrad-Historie
|
|
|
|
Der Pflegegrad steht als einzelnes Feld in den Stammdaten. Frühere Grade
|
|
mit ihren Zeiträumen gehören in eine Historie — sie werden im
|
|
Jahresbericht und bei einer Höherstufung gebraucht.
|
|
|
|
---
|
|
|
|
## 1.2b — Passkeys abrunden
|
|
|
|
Der Grundstock steht seit 1.1.0. Was noch fehlt, ist Bequemlichkeit, nicht
|
|
Sicherheit.
|
|
|
|
### Passkey direkt im Anmeldefeld anbieten
|
|
|
|
Browser können einen Passkey im Ausfüllvorschlag des E-Mail-Feldes
|
|
anbieten (*conditional UI*), statt hinter einem eigenen Knopf. Ein Schritt
|
|
weniger. Braucht einen zweiten Challenge-Weg und sorgfältiges Abbrechen,
|
|
wenn stattdessen doch das Passwort getippt wird.
|
|
|
|
### Passkey umbenennen
|
|
|
|
Heute geht nur anlegen und entfernen. Wer sein Gerät „Handy" genannt hat
|
|
und inzwischen zwei hat, muss den Passkey neu einrichten.
|
|
|
|
### Warnen, wenn der letzte Passkey nur auf einem Gerät liegt
|
|
|
|
Die Liste sagt bereits, ob ein Schlüssel gesichert ist. Wer ausschließlich
|
|
ungesicherte Passkeys hat und dazu keine Wiederherstellungscodes mehr,
|
|
sollte das deutlicher zu sehen bekommen als in einer Zeile Kleingedrucktem.
|
|
|
|
---
|
|
|
|
## 1.3 — Belastbarkeit
|
|
|
|
**Ziel:** Die Stellen absichern, die bisher nur unter Laborbedingungen
|
|
geprüft sind.
|
|
|
|
### Texterkennung gegen echtes Tesseract
|
|
|
|
Bisher ist nur der Weg „nicht verfügbar, Upload funktioniert trotzdem"
|
|
getestet. Ein Test im Container gegen echte Schreiben — auch schlechte
|
|
Handyfotos, auch mehrseitige Bescheide — fehlt.
|
|
|
|
### CAMT.053 gegen einen echten Bankauszug
|
|
|
|
Der Leser ist gegen selbst gebaute Beispiele geprüft. Ein echter Auszug
|
|
der Sparkasse ist der eigentliche Test.
|
|
|
|
### Suche und Belegmappe gegen Postgres
|
|
|
|
Beide sind nur in Einzelteilen geprüft, nicht end-to-end gegen die
|
|
Datenbank mit einigen hundert Dokumenten.
|
|
|
|
### Wiederherstellung als Test
|
|
|
|
Die Anleitung dafür steht in der README. Ein Skript, das sie einmal im
|
|
Monat automatisch durchspielt — Sicherung zurückspielen, Diagnosen im
|
|
Klartext prüfen, Testdatenbank verwerfen — wäre der Beweis statt der
|
|
Absichtserklärung.
|
|
|
|
### Passkey-Ablehnung ohne Browser nachstellen
|
|
|
|
Die Prüfung „Passkey ohne Nutzerverifikation wird abgewiesen" ist im Code
|
|
doppelt abgesichert und im Browsertest belegt — dort weist allerdings
|
|
schon der Browser ab, der Server kommt gar nicht dran. Ein Test, der die
|
|
Antwort von Hand baut und den Browser umgeht, würde den serverseitigen
|
|
Rückhalt tatsächlich beweisen.
|
|
|
|
### Barrierefreiheits-Durchgang mit einem Screenreader
|
|
|
|
Semantik, Fokusreihenfolge und Kontraste sind beim Bauen beachtet und in
|
|
Teilen getestet. Ein Durchgang mit NVDA oder VoiceOver ist etwas anderes
|
|
als eine Testzusicherung.
|
|
|
|
### `@react-pdf/renderer` ohne Krücke
|
|
|
|
`src/lib/pdf/standardschrift.ts` gleicht aus, dass die Unterabhängigkeiten
|
|
für Standardschriften kein Schriftobjekt mehr liefern. Ein `overrides`-
|
|
Eintrag in der `package.json` oder eine neuere Fassung macht die Datei
|
|
überflüssig — sie baut sich dann selbst ab.
|
|
|
|
---
|
|
|
|
## 2.0 — Mehr als eine Betreuung
|
|
|
|
**Ziel:** Was sich nur mit einem Bruch lösen lässt. Deshalb eine eigene
|
|
Hauptversion — und deshalb nicht vorher.
|
|
|
|
### Zweite betreute Person im Alltag erprobt
|
|
|
|
Das Datenmodell trägt es von Anfang an: Alles hängt an einer `betreuteId`,
|
|
der Zugriff wird gegen sie geprüft, die Auswahl steht in der Seitenleiste.
|
|
**Gelaufen ist es bisher nur mit einer.** Was fehlt, ist Erfahrung — und
|
|
vermutlich ein Dashboard, das über beide hinwegsieht.
|
|
|
|
### Heimkostenmodell entwirren
|
|
|
|
Der einrichtungseinheitliche Eigenanteil auf der Heimrechnung ist bereits
|
|
um die Leistung der Pflegekasse gekürzt. Das Modul rechnet deshalb
|
|
ausdrücklich nach der Lesart `EIGENANTEIL_NETTO` und warnt, wenn die
|
|
Pflegekassenleistung zusätzlich erfasst wird.
|
|
|
|
Sauberer wäre, die beiden Lesarten im Modell zu trennen, statt sie im Kopf
|
|
auseinanderzuhalten. Das ändert bestehende Datensätze — also 2.0.
|
|
|
|
### Mehrere Fassungen je Bericht
|
|
|
|
Heute verdrängt die DOCX-Ausgabe die abgegebene PDF-Fassung. Was einmal
|
|
beim Gericht lag, sollte unverändert nachweisbar bleiben.
|
|
|
|
### Verschlüsselte Ablage auch bei S3
|
|
|
|
Beim Dateitreiber liegen Dokumente zusätzlich AES-256-GCM-verschlüsselt.
|
|
Bei S3 geht das nicht, weil signierte URLs am Server vorbei ausgeliefert
|
|
werden. Der Ausweg wäre, Dateien durch die Anwendung zu reichen — das
|
|
kostet Durchsatz und ist eine bewusste Abwägung, keine Selbstverständlichkeit.
|
|
|
|
---
|
|
|
|
## Später, ohne Datum
|
|
|
|
Sinnvoll, aber nicht dringend:
|
|
|
|
- **Kalendarische Wiedervorlage per E-Mail als Wochenübersicht** statt
|
|
einzelner Erinnerungen.
|
|
- **Vorlagen für eigene Anschreiben**, über die mitgelieferten hinaus.
|
|
- **Import eines Grundbuchauszugs** als strukturierte Daten statt als PDF.
|
|
- **Mehrere Betreuungsgerichte** je betreuter Person (bei Umzug).
|
|
- **Zwei-Personen-Prinzip** für besonders sensible Aktionen — technisch
|
|
vorbereitet durch die erneute Anmeldung, fachlich noch nicht gebraucht.
|
|
- **Statistik über mehrere Betreuungsjahre** für den eigenen Überblick.
|
|
|
|
---
|
|
|
|
## Bewusst nicht geplant
|
|
|
|
Damit klar ist, worauf niemand warten muss:
|
|
|
|
| Was | Warum nicht |
|
|
|---|---|
|
|
| **Automatische Rechtsberatung** | Die Anwendung kennt den Einzelfall nicht. Sie rechnet und dokumentiert; entscheiden tun Gericht, Träger und im Zweifel das Sozialgericht. |
|
|
| **Prognosen zu Bewilligungschancen** | Eine Zahl, die niemand belegen kann, wird trotzdem geglaubt. Das ist schlimmer als keine Zahl. |
|
|
| **Direkte Bankanbindung** | Ein dauerhafter Kontozugriff ist ein Risiko, das der Bequemlichkeit nicht wert ist. CSV und CAMT reichen. |
|
|
| **Mehrmandantenfähigkeit für fremde Betreuungen** | Sobald mehrere Betreuer mit fremden Fällen auf derselben Installation arbeiten, ändert sich die datenschutzrechtliche Lage grundlegend. Mehrere Betreute **einer** Person bleiben möglich. |
|
|
| **Native App für Handy und Tablet** | Die Web-Anwendung ist am Telefon vollwertig bedienbar. Eine zweite Oberfläche wäre eine zweite Oberfläche, die veraltet. |
|
|
| **Cloud-Angebot für andere Betreuer** | Dann wäre ich Auftragsverarbeiter für fremde Gesundheitsdaten. Eine andere Aufgabe als die, für die das hier gebaut wurde. |
|
|
| **KI-Auswertung der Akte** | Gesundheitsdaten einer nicht entscheidungsfähigen Person verlassen diesen Server nicht. Die Texterkennung läuft lokal, und dabei bleibt es. |
|
|
|
|
---
|
|
|
|
## Wie hier priorisiert wird
|
|
|
|
Drei Fragen, in dieser Reihenfolge:
|
|
|
|
1. **Kann daraus ein falscher Wert in einem Bericht ans Gericht werden?**
|
|
Dann sofort — auch wenn es unbequem ist.
|
|
2. **Kostet es jeden Monat Zeit?** Dann bald.
|
|
3. **Wäre es schön?** Dann irgendwann, und ehrlich gesagt vielleicht nie.
|
|
|
|
Fällt ein Punkt in Kategorie 1 und wird trotzdem nicht sofort behoben,
|
|
steht der Grund dabei — und die Oberfläche sagt an der betroffenen Stelle,
|
|
worauf man achten muss. Ein stillschweigend falscher Wert ist das
|
|
Schlimmste, was diese Anwendung produzieren kann.
|