diff --git a/.planning/phases/02-authentication-multi-tenancy/02-CONTEXT.md b/.planning/phases/02-authentication-multi-tenancy/02-CONTEXT.md new file mode 100644 index 0000000..f136334 --- /dev/null +++ b/.planning/phases/02-authentication-multi-tenancy/02-CONTEXT.md @@ -0,0 +1,116 @@ +# 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* diff --git a/.planning/phases/02-authentication-multi-tenancy/02-DISCUSSION-LOG.md b/.planning/phases/02-authentication-multi-tenancy/02-DISCUSSION-LOG.md new file mode 100644 index 0000000..c3c8071 --- /dev/null +++ b/.planning/phases/02-authentication-multi-tenancy/02-DISCUSSION-LOG.md @@ -0,0 +1,120 @@ +# Phase 2: Authentication & Multi-Tenancy - Discussion Log + +> **Audit trail only.** Do not use as input to planning, research, or execution agents. + +**Date:** 2026-06-18 +**Phase:** 2-Authentication & Multi-Tenancy +**Areas discussed:** Login-Flow, Admin-Setup, Mandanten-Modell, LDAP-Import + +--- + +## Login-Flow + +| Option | Description | Selected | +|--------|-------------|----------| +| Zentriert/Minimal | Logo + Formular mittig | | +| Split-Screen | Links Branding/Bild, rechts Formular | ✓ | +| Du entscheidest | Claude waehlt | | + +**User's choice:** Split-Screen + +| Option | Description | Selected | +|--------|-------------|----------| +| 8 Stunden | Arbeitstag | | +| 24 Stunden | Ein Tag | | +| 30 Tage + Remember | Langlebig mit Angemeldet-bleiben | ✓ | +| Du entscheidest | Claude waehlt | | + +**User's choice:** 30 Tage + Remember + +| Option | Description | Selected | +|--------|-------------|----------| +| Ja, per E-Mail | Reset-Link per E-Mail | | +| Nur Admin-Reset | Admin setzt manuell zurueck | | +| Beides | Self-Service + Admin-Reset | ✓ | + +**User's choice:** Beides + +--- + +## Admin-Setup + +| Option | Description | Selected | +|--------|-------------|----------| +| E-Mail + Passwort | TESSERA_ADMIN_EMAIL + PASSWORD | | +| Username + Passwort | TESSERA_ADMIN_USER + PASSWORD | | +| Beides | Username + E-Mail + Passwort | ✓ | + +**User's choice:** Beides (alle drei ENV-Variablen) + +| Option | Description | Selected | +|--------|-------------|----------| +| Ja, Pflicht | Force-Change beim ersten Login | | +| Nein | ENV-Passwort bleibt | | +| Optional konfigurierbar | Per ENV einstellbar | ✓ | + +**User's choice:** Optional konfigurierbar (TESSERA_FORCE_CHANGE) + +--- + +## Mandanten-Modell + +| Option | Description | Selected | +|--------|-------------|----------| +| Subdomain | firma.tessera.de | | +| Nach Login | Tenant per Benutzer-Zuordnung | | +| Tenant-Auswahl | Benutzer waehlt Mandant | | +| Du entscheidest | Claude waehlt | ✓ | + +**User's choice:** Du entscheidest + +| Option | Description | Selected | +|--------|-------------|----------| +| Ja | Multi-Tenant pro User | | +| Nein | Ein Mandant pro User | | +| Spaeter | Erstmal einer, spaeter mehrere | ✓ | + +**User's choice:** Spaeter (erstmal ein Mandant pro User) + +| Option | Description | Selected | +|--------|-------------|----------| +| Ja | Super-Admin fuer alle Mandanten | ✓ | +| Nein | Jeder Admin nur eigener Mandant | | +| Ja, spaeter | Super-Admin kommt spaeter | | + +**User's choice:** Ja (Super-Admin von Anfang an) + +--- + +## LDAP-Import + +| Option | Description | Selected | +|--------|-------------|----------| +| Manuell per Button | Admin klickt Sync | | +| Manuell + Auto-Sync | Button + Intervall | ✓ | +| Nur Auto-Sync | Nur automatisch | | + +**User's choice:** Manuell + Auto-Sync + +| Option | Description | Selected | +|--------|-------------|----------| +| Deaktivieren | User wird deaktiviert | ✓ | +| Loeschen | User wird entfernt | | +| Nichts | Nur Import, keine Sync | | + +**User's choice:** Deaktivieren + +**LDAP Feld-Mapping:** Konfigurierbar mit Standard-Defaults (displayName → Name, mail → E-Mail, sAMAccountName → Username). Custom-Felder muessen auch mappbar sein. + +--- + +## Claude's Discretion + +- Tenant-Identifikation (JWT-Claim vs Header vs Middleware) +- JWT vs Session-Cookie Implementierung +- SMTP-Konfiguration Struktur +- Keycloak vs eigene Auth-Loesung + +## Deferred Ideas + +None