# Phase 2: Authentication & Multi-Tenancy - Context **Gathered:** 2026-06-18 **Status:** Ready for planning ## Phase Boundary Benutzerauthentifizierung (initialer Admin via Docker-ENV, manuelles CRUD, LDAP-Import), Login/Logout mit langlebiger Session, rollenbasierte Zugriffskontrolle (Super-Admin, Admin, User), Mandantenverwaltung mit PostgreSQL Row-Level Security. Kein SSO/OIDC, kein Payment — das kommt spaeter. ## Implementation Decisions ### Login-Flow - **D-01:** Login-Seite als Split-Screen (links Branding/Bild, rechts Login-Formular) - **D-02:** Session-Dauer 30 Tage mit "Angemeldet bleiben" Option (Remember-me Checkbox) - **D-03:** Passwort-Reset per E-Mail (Self-Service) + Admin kann Passwort manuell zuruecksetzen — erfordert SMTP-Konfiguration - **D-04:** Login-Seite zeigt kein Sidebar/Header — eigenstaendiges Layout ### Admin-Setup - **D-05:** Initialer Admin via Docker-ENV: TESSERA_ADMIN_USER, TESSERA_ADMIN_EMAIL, TESSERA_ADMIN_PASSWORD - **D-06:** Force-Password-Change beim ersten Login optional konfigurierbar via ENV: TESSERA_FORCE_CHANGE=true/false - **D-07:** Admin wird beim ersten Container-Start automatisch erstellt wenn er noch nicht existiert ### Mandanten-Modell - **D-08:** Tenant-Zuordnung per Benutzer (kein URL-Unterschied, kein Subdomain-Routing) — Claude entscheidet technische Details - **D-09:** Erstmal ein Mandant pro Benutzer — Multi-Tenant-Zugehoerigkeit kommt spaeter - **D-10:** Super-Admin Rolle existiert: kann alle Mandanten sehen/verwalten, Mandanten anlegen, zwischen ihnen wechseln, globale Einstellungen aendern - **D-11:** RLS auf PostgreSQL-Ebene — Tenant-ID wird per Request-Context gesetzt ### RBAC - **D-12:** Drei Rollen: Super-Admin (plattformweit), Admin (mandantenspezifisch), User (mandantenspezifisch) - **D-13:** Super-Admin wird ueber den initialen Admin-Account angelegt (erster Account = Super-Admin) ### LDAP-Import - **D-14:** Manueller Button ("LDAP synchronisieren") in der Benutzerverwaltung + konfigurierbares Auto-Sync-Intervall - **D-15:** Benutzer die aus LDAP geloescht werden: in Tessera deaktiviert (nicht geloescht) - **D-16:** Feld-Mapping konfigurierbar in den LDAP-Einstellungen, Standard-Defaults vorausgewaehlt: displayName → Name, mail → E-Mail, sAMAccountName → Username - **D-17:** Custom-Felder muessen auch gemappt werden koennen (erweiterbare Mapping-Tabelle) - **D-18:** LDAP-Konfiguration pro Mandant (Server-URL, Base-DN, Bind-User, Filter, Mapping) ### Claude's Discretion - Tenant-Identifikation technisch (JWT-Claim, Middleware-Pattern, Header) — Benutzer hat "du entscheidest" gewaehlt - JWT vs. Session-Cookie Implementierung — soll sicher und langlebig sein - SMTP-Konfiguration Struktur (ENV-Variablen fuer Mailserver) - Keycloak-Nutzung: Research soll entscheiden ob eigene Auth oder Keycloak sinnvoller ist fuer diesen Scope ## Canonical References **Downstream agents MUST read these before planning or implementing.** ### Projekt-Kontext - `.planning/PROJECT.md` — Gesamtprojekt, Core Value, Constraints - `.planning/REQUIREMENTS.md` — Phase-2-Requirements: AUTH-01..06, TNNT-01..03 - `.planning/ROADMAP.md` — Phase-Ziel und Success Criteria ### Research - `.planning/research/STACK.md` — Technologie-Stack (Keycloak 26.6 empfohlen, Prisma 7, PostgreSQL RLS) - `.planning/research/ARCHITECTURE.md` — Auth-Modul, Tenant-Modul, RLS-Pattern - `.planning/research/PITFALLS.md` — LDAP als Auth-Antipattern, Tenant-Context in Async, RLS von Tag 1 ### Vorherige Phase - `.planning/phases/01-foundation-portal-shell/01-CONTEXT.md` — Design-Entscheidungen Phase 1 - `.planning/phases/01-foundation-portal-shell/01-01-SUMMARY.md` — Walking Skeleton (Prisma-Schema, NestJS-Struktur) - `.planning/phases/01-foundation-portal-shell/01-02-SUMMARY.md` — Portal Shell (Header User-Placeholder, Sidebar User-Placeholder) ## Existing Code Insights ### Reusable Assets - `apps/api/src/prisma/schema.prisma` — Prisma-Schema mit Tenant-Model-Grundlage aus Phase 1 - `apps/api/src/health/health.controller.ts` — NestJS Controller-Pattern als Vorlage - `apps/web/src/components/layout/header.tsx` — User-Avatar-Placeholder der mit Auth verdrahtet werden muss - `apps/web/src/components/layout/sidebar-footer.tsx` — User-Info-Placeholder der mit Auth verdrahtet werden muss ### Established Patterns - NestJS mit Prisma-Client fuer DB-Zugriff - Next.js App Router mit Server Components + Client Components - next-intl fuer i18n (alle neuen Seiten muessen t() verwenden) - Zustand-Stores mit Persist-Middleware fuer Client-State ### Integration Points - Login-Seite braucht eigenes Layout (kein AppShell) - Auth-Guard muss alle bestehenden Routen schuetzen - Header und Sidebar-Footer muessen den eingeloggten Benutzer anzeigen - SMTP-Konfiguration als Docker-ENV-Variablen ## Specific Ideas - Split-Screen Login: links Tessera-Branding mit gelber Primaerfarbe (#ffed00), rechts Formular auf weissem/dunklem Hintergrund - Super-Admin Dashboard: eigener Bereich zum Verwalten aller Mandanten (Mandanten-Liste, Benutzer-Uebersicht) - LDAP-Einstellungen: eigene Seite in den Admin-Einstellungen mit Test-Connection-Button und Mapping-Editor ## Deferred Ideas None — discussion stayed within phase scope --- *Phase: 2-Authentication & Multi-Tenancy* *Context gathered: 2026-06-18*