/api/health meldet Status, Version, Instanz und Erreichbarkeit der
Datenbank – ohne Anmeldung, deshalb ohne Zählstände, Namen oder Adressen.
update.sh wird sich später darauf stützen.
Der Seed legt die vier Bereiche an und ein erstes Verwaltungskonto aus
ADMIN_EMAIL und ADMIN_PASSWORT. Er läuft mehrfach ohne Schaden; ohne
ADMIN_PASSWORT entsteht ein Konto, das sich nur über OIDC oder Passkey
anmelden kann.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bereiche mit Farbe, Arbeitsfenster und Tageskapazität – die erste
schreibende Funktion und damit der Beleg, dass die Kette trägt: zod prüft
jede Eingabe, die Rolle wird in der Seite und noch einmal in der Server
Action geprüft, jede Änderung hinterlässt einen Audit-Eintrag.
Die Audit-Details werden vor dem Speichern gesäubert: Felder, deren Name
nach Passwort, Token, Betreff oder Mailinhalt aussieht, werden ersetzt.
Das gilt auch in verschachtelten Objekten und Listen.
Dazu die Protokollseite für die Verwaltung und die Startseite.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Drei Wege hinein, je Instanz zuschaltbar: generischer OIDC-Anbieter
(Entra ID beziehungsweise authentik), Passkeys und wahlweise E-Mail mit
Passwort.
Entscheidungen:
- Passkeys laufen direkt über SimpleWebAuthn 14, nicht über den
experimentellen WebAuthn-Provider von Auth.js, der noch auf Fassung 9
festgelegt ist.
- Eigener Prisma-Adapter, weil der mitgelieferte fest auf prisma.user und
prisma.account zugreift, unsere Modelle aber Benutzer und Konto heißen.
- Sitzungen als JWT, weil Credentials-Provider das verlangen. Damit eine
Sperre trotzdem sofort wirkt, liest der session-Callback Rolle und
Status bei jeder Anfrage frisch aus der Datenbank. Die Tabellen sitzung
und verifizierungs_token entfallen deshalb wieder.
- allowDangerousEmailAccountLinking ist bewusst an: je Instanz gibt es
genau einen vertrauenswürdigen Anbieter, der die Adresse selbst prüft.
Anmeldung, Passwort und Passkey antworten bei Fehlschlag immer gleich,
damit sich nicht abfragen lässt, wer hier ein Konto hat. Die
WebAuthn-Herausforderung wird nach einem Versuch verworfen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Deutsche Oberfläche, Hell und Dunkel über next-themes, Navigation mit
Rollenfilter und die shadcn-Primitiven, die M1 braucht.
Der Farbschema-Knopf kommt ohne Effekt und ohne Zustand aus: welches
Symbol gilt, entscheidet die dark-Klasse und damit CSS. next-themes setzt
sie schon vor der Hydratation, deshalb blitzt nichts auf — und die
React-Compiler-Regel gegen setState im Effekt bleibt eingehalten.
Farben als OKLCH, damit Hell und Dunkel dieselbe wahrgenommene Helligkeit
halten.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>