Fundament Benutzer-/Rollenverwaltung: Schema, Passwort-Policy, Force-Change

Vorbereitung für die Benutzer- & Rollenverwaltung (Pakete A–C) ohne E-Mail-Flow.

- Schema: User.mustChangePassword (erzwungener Wechsel), User.mfaEnrolledAt +
  recoveryCodes (optionale Nutzer-MFA, Paket C); neues Singleton PlatformSetting
  mit mfaRequired (Default aus → MFA optional). Migration additiv + Grant/Seed.
- RBAC: neue Permission role:manage (Rollenverwaltung), dem Mandanten-Admin
  zugewiesen; für den bestehenden Demo-Mandanten nachgezogen (neue Tenants via
  provision/seed automatisch).
- Passwort-Policy: lib/password-policy.ts (client-safe Validierung/Beschreibung,
  Defaults + Ableitung aus TenantSettings.securityPolicy) und server/password.ts
  (Argon2id-Hash + policy-konformer Einmal-Passwort-Generator).
- Force-Change-Flow: /change-password (außerhalb der (app)-Shell) + Self-Service-
  Action changeOwnPassword (policy-geprüft, Audit). (app)-Layout erzwingt den
  Wechsel autoritativ aus der DB und sperrt deaktivierte Konten (Abmelden-Screen).

tsc + lint + build + Guard-Check grün.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-22 09:18:05 +02:00
co-authored by Claude Opus 4.8
parent e07dcd9f2a
commit db36c795bd
10 changed files with 262 additions and 2 deletions
+16 -1
View File
@@ -102,7 +102,12 @@ model User {
passwordHash String @map("password_hash")
name String
status UserStatus @default(ACTIVE)
mfaSecret String? @map("mfa_secret")
// Erzwungener Passwortwechsel beim nächsten Login (Initial-/Reset-Passwort).
mustChangePassword Boolean @default(false) @map("must_change_password")
// Optionale TOTP-MFA je Nutzer (Paket C). recoveryCodes = SHA-256-Hashes.
mfaSecret String? @map("mfa_secret")
mfaEnrolledAt DateTime? @map("mfa_enrolled_at")
recoveryCodes Json @default("[]") @map("recovery_codes")
// Plattform-Admin ist mandantenübergreifend (Betreiberrolle)
isPlatformAdmin Boolean @default(false) @map("is_platform_admin")
createdAt DateTime @default(now()) @map("created_at")
@@ -187,6 +192,16 @@ model PlatformAdmin {
@@map("platform_admins")
}
// Plattformweite Betriebseinstellungen (Singleton). Steuert u. a., ob MFA für
// Plattform-Admins verpflichtend ist (Default: aus → MFA optional, Paket C).
model PlatformSetting {
id String @id @default("singleton")
mfaRequired Boolean @default(false) @map("mfa_required")
updatedAt DateTime @updatedAt @map("updated_at")
@@map("platform_settings")
}
// ── Assets & BIA (ein Modul, SPEC §4.1) ─────────────────────────────────────
enum AssetType {