feat(bereiche): Bereiche verwalten mit Rollenprüfung und Audit

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>
This commit is contained in:
Florian Wilde
2026-09-10 13:02:49 +02:00
co-authored by Claude Opus 5
parent cc013fd6a1
commit e9a2b4b463
14 changed files with 1432 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
import { Kopfleiste } from '@/components/kopfleiste'
import { INSTANZ_NAME } from '@/lib/instanz'
import { versionAnzeige } from '@/lib/version'
import { verlangeAnmeldung } from '@/server/berechtigung'
import { aktuelleInstanz } from '@/server/instanz'
/**
* Alles unterhalb von (app) setzt eine Anmeldung voraus. Der Riegel sitzt
* hier im Layout und zusaetzlich in jeder Server Action – nicht nur in der
* Oberflaeche.
*/
export default async function AngemeldetesLayout({
children,
}: {
children: React.ReactNode
}) {
const benutzer = await verlangeAnmeldung()
const instanz = aktuelleInstanz()
return (
<div className="flex min-h-dvh flex-col">
<Kopfleiste
name={benutzer.name ?? benutzer.email}
email={benutzer.email}
rolle={benutzer.rolle}
instanzName={INSTANZ_NAME[instanz]}
/>
<main className="mx-auto w-full max-w-5xl flex-1 px-4 py-8">{children}</main>
<footer className="text-gedaempft-vordergrund border-rand border-t px-4 py-4 text-center text-xs">
Planer {versionAnzeige()} · {INSTANZ_NAME[instanz]}
</footer>
</div>
)
}