Das Dashboard beantwortet die Frage, was heute ansteht - nicht, welche
Daten es gibt. Jede Kachel endet in einer Handlung: Fristen-Ampel,
wartet auf andere (mit Tagen seit dem letzten Kontakt), offene
Nachforderungen des Bezirks mit Fortschrittsbalken, ungepruefter
Posteingang, unverbuchte Belege, Kennzahlen.
Zwoelf Abfragen in einem Promise.all, kein N+1. Cent-Betraege werden
beim Verlassen der Serverseite gewandelt.
Kacheln zu Modulen, die ein Mitleser nicht freigegeben bekommen hat,
entfallen ganz - sie zeigen nicht "0", denn das waere eine Aussage ueber
Daten, die er nicht sehen darf.
Kontaktprotokoll als Schnellerfassung: Datum vorbelegt, Art als grosse
Knopfreihe, Dauer als Schnellwahl, ein Freitextfeld. Alles andere
eingeklappt. Ziel sind unter 20 Sekunden am Handy.
Das Haekchen "persoenlicher Kontakt zur betreuten Person" ist bewusst
NICHT vorbelegt - es wandert in den Jahresbericht nach § 1863 BGB, und
ein versehentlich gesetztes Haekchen waere dort eine falsche Angabe
gegenueber dem Gericht.
Aus demselben Grund gilt der Textbaustein "regelmaessiger persoenlicher
Kontakt" erst ab persoenlichem Kontakt in mindestens 75 Prozent der
Monate. Sonst schreibt die Auswertung ausdruecklich, dass kein
persoenlicher Kontakt dokumentiert ist. Ein geschoenter Bericht hilft
niemandem.
Protokolldaten werden als 12:00 UTC gespeichert und durchgaengig in UTC
gerechnet, sonst kippt die Zeitzone einzelne Besuchstage.
51 Tests.
Etappe: 2
Phase: Alltag
Die gesetzlichen Fristen entstehen von selbst, sobald das
Bestellungsdatum in den Stammdaten steht - Vermoegensverzeichnis und
Anfangsbericht nach drei Monaten, Jahresbericht und Vermoegensuebersicht
zum Ende jedes Betreuungsjahres, Aufwandspauschale, Landespflegegeld,
Zuzahlungsbefreiung, Rueckkaufswerte.
Zwei Punkte, an denen es sonst schiefgeht:
Das Betreuungsjahr endet am Tag VOR dem Jahrestag (§ 188 Abs. 2 BGB),
bei Bestellung am 29. Februar am 28. (§ 188 Abs. 3). Ohne diese Regel
verrutscht die ganze Kette um einen Tag.
Faellt eine Frist auf Samstag, Sonntag oder Feiertag, wird sie NICHT
verschoben. § 193 BGB verschiebt zwar den Ablauf, aber als Betreuer will
ich frueher fertig sein, nicht spaeter. Stattdessen steht ein Hinweis in
der Beschreibung. Bayerische Feiertage inklusive, ueber die Osterformel
berechnet.
Pflichtfristen tragen bewusst keine RRULE: sonst entstuende beim
Erledigen eine Dublette neben der ohnehin abgeleiteten Folgefrist. Beim
erneuten Ableiten werden nur offene Fristen nachgezogen, Erledigtes
bleibt unangetastet.
Der ICS-Feed kommt ohne Token-Feld im Schema aus - die Signatur ist ein
HMAC ueber betreuteId und userId. VALARM je Vorwarnstufe, Zeilenfaltung
nach RFC 5545.
51 Tests.
Etappe: 2
Phase: Alltag
Jeder Vorgang ist eine kleine Akte: Kopfdaten, Aufgabenliste zum
Abhaken, Genehmigungsstufen und ein Zeitstrahl, der Dokumente,
Kontaktprotokolle, Fristen, Buchungen und Statuswechsel zusammenfuehrt.
Die abnahmerelevante Regel: Ein genehmigungspflichtiger Vorgang laesst
sich nicht auf VOLLZOGEN setzen, solange kein Beschlussdokument
hinterlegt ist. Geprueft wird in darfStatusWechseln() UND in der Server
Action - nicht nur im UI, wo das Auswahlfeld die Stufe ohnehin gar nicht
erst anbietet. Hintergrund ist § 1858 BGB: die Genehmigung muss vor dem
Rechtsgeschaeft vorliegen, nicht danach.
Neun Vorlagen mit durchdachter Aufgabenreihenfolge. Bei Wohnungs-
aufloesung und Hausverkauf erzwingen sie die Kette Mitteilung ->
Genehmigung -> Rechtsgeschaeft; ein Test prueft das.
Kanban ohne Drag-and-Drop: Statuswechsel laufen ueber Auswahlfeld und
Knopf. Am Handy ist das verlaesslicher, und am Schreibtisch kostet es
einen Klick mehr statt einer verlorenen Karte.
Zeitzonen: alsTag() bildet den oertlichen Kalendertag auf Mitternacht
UTC ab. Ohne das rutscht in Deutschland jede Faelligkeit einen Tag
zurueck.
33 Tests.
Etappe: 2
Phase: Alltag
Die Sicherheitsschicht, auf der alles Weitere aufsetzt.
Feldverschluesselung (AES-256-GCM):
- Umschlagformat bc1.<version>.<iv>.<tag>.<ct>. Die Schluesselversion
erlaubt Rotation, ohne alte Daten unlesbar zu machen.
- Der Feldname wird als AAD mitauthentifiziert. Ein Geheimtext laesst
sich damit nicht von diagnosen nach notizen umhaengen.
- Leere Werte werden zu NULL statt zu einem Umschlag - sonst verriete
die Datenbank, dass ueberhaupt etwas eingetragen war.
- VERSCHLUESSELTE_FELDER ist der einzige Ort, an dem steht, was
verschluesselt gehoert. sealen()/oeffnen() arbeiten darauf.
Argon2id nach OWASP-Empfehlung (19 MiB, t=2, p=1), mit hashVeraltet()
fuer spaetere Parametererhoehung ohne Migration.
Blindindex per HMAC-SHA256 mit eigenem Schluessel: erlaubt die Frage
"kenne ich diese IBAN schon?", ohne sie im Klartext zu halten.
Derselbe Mechanismus pseudonymisiert IP-Adressen fuers Audit-Log.
TOTP mit otpauth, QR-Code serverseitig als Data-URI - kein externer
QR-Dienst, kein CDN. Wiederherstellungscodes aus einem Alphabet ohne
0/O und 1/I, einzeln Argon2id-gehasht, Pruefung ohne fruehen Abbruch.
37 Tests decken Rundlauf, Manipulation, Feldbindung, Rotation,
Salzung und Normalisierung ab.
Etappe: 1
Phase: Fundament