docs: reflect Postgres, migration, and the Flutter client

Root README + plan updated: local PostgreSQL 16 + first Prisma migration,
end-to-end guest-flow verification, and the started Flutter client
(client/app/, web target). Phase 7 marked in progress with the remaining
client work spelled out.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-10 08:54:15 +02:00
co-authored by Claude Sonnet 5
parent 0886424526
commit 138d782ca3
2 changed files with 34 additions and 19 deletions
+25 -12
View File
@@ -12,12 +12,13 @@ for the full architecture and phased roadmap.
sharing, chat, local/cloud sync). See [backend/README.md](backend/README.md)
for setup. Also serves the web client (see below) directly, so it's the
single entry point for the web experience.
- `client/app/` — the Flutter client (single codebase; **web** target
enabled, mobile/desktop can be added later). Login (guest / local Teamer /
invite redemption), role-aware home, guest Workshop-Wahl, file list,
read-only chat. See [client/app/README.md](client/app/README.md).
- `client/web/` — minimal dependency-free HTML/CSS/JS placeholder web
client (guest join, Wahl submission, file list, chat) exercising the real
API, served by the backend at `/`. Will be replaced by the Flutter web
build once Flutter is available.
- `client/` (mobile/desktop) — planned Flutter app, not yet scaffolded
(Flutter is not installed in this environment).
client, served by the backend at `/`. Superseded by the Flutter web build;
kept for now as a zero-dependency fallback.
## Status
@@ -50,12 +51,24 @@ cloud server's `/sync/ingest` + `/sync/export` endpoints (shared-secret
authenticated, not user auth). No conflict resolution needed by design - the
local server is the sole source of truth while an event is live.
The backend now also serves the web client directly (static files from
`client/web/`, API under `/api`), so the same process is the single entry
point for the web experience.
Since then: local (non-Authentik) Gemeinde Teamer accounts + invites
(`teamer/`, `auth/team-login`), Gemeinde CRUD (`gemeinde/`), Gemeinde
Verantwortliche self-registration with LT approval (`onboarding/`), JIT
`User` provisioning on first Authentik login, LEITUNGSTEAM derived from the
Authentik `groups` claim, and an email module (`mail/`, log-only by default,
SMTP opt-in) that sends personal Teamer invites. First Prisma migration is
in (`backend/prisma/migrations/`); the backend has been run end to end
against a local PostgreSQL 16. `npm test` covers the assignment algorithm
and the new auth/onboarding services (56 tests).
Backend builds and boots cleanly (`npm run build`, `node dist/main.js`) but
requires a real PostgreSQL database, Authentik instance, and Nextcloud/S3
credentials (see `backend/.env.example`) to run end to end. Remaining: the
Flutter clients (mobile/desktop; web has an interim plain-HTML client).
Phase 7 (Flutter client) started: `client/app/` is a single Flutter
codebase with the **web** target enabled — login (guest / local Teamer /
invite redemption), role-aware home, guest Workshop-Wahl, file list,
read-only chat. `flutter build web` and `flutter test` pass. Mobile/desktop
targets, the Authentik Authorization-Code flow, WebSocket chat send, and LT
admin screens are still to come.
The backend also serves the interim `client/web/` placeholder at `/` (API
under `/api`). Running end to end still needs a real Authentik instance and
Nextcloud/S3 credentials (see `backend/.env.example`).
+9 -7
View File
@@ -2,7 +2,7 @@
Neuentwicklung, die das WordPress-Plugin **Workshop-Wahlen** (Wahlen/Workshops/Teilnehmer/Zuteilungslogik) ablöst und um Rollen-/Rechteverwaltung via Authentik, gestaffelte Dateifreigabe, mehrstufigen Chat und eine Hybrid-Server-Architektur (online + lokal mit Sync) erweitert. Backend: **NestJS 10 + PostgreSQL + Prisma 5**. Client: **Flutter** (eine Codebase für Mobile, Web, Desktop) — bis Flutter verfügbar ist, liefert das Backend selbst einen minimalen Platzhalter-Web-Client aus.
> Status (Stand dieser Session): **Alle geplanten Backend-Phasen (06) sind implementiert und verifiziert** (Typecheck, Build, Boot-Test). Offen ist ausschließlich der Flutter-Client (Mobile/Desktop), da Flutter in dieser Umgebung nicht installiert ist.
> Status: **Backend-Phasen 06 komplett** plus lokale Teamer-Accounts/Invites, Gemeinde-CRUD, Verantwortlichen-Selbstregistrierung (`onboarding/`), Authentik-JIT + LT-aus-`groups`, `mail/`-Modul. Erste Prisma-Migration vorhanden, Backend lief Ende-zu-Ende gegen lokales PostgreSQL 16 (`npm test`: 56). **Phase 7 (Flutter) begonnen**: `client/app/` — eine Codebase, Web-Target aktiv, Login/Home/Wahl/Dateien/Chat(read-only); `flutter build web` + `flutter test` grün. Offen: Mobile/Desktop-Targets, Authentik-Auth-Code-Flow im Client, WS-Chat-Senden, LT-Admin-Screens, Push, echte Authentik/Nextcloud-Infra.
---
@@ -37,7 +37,7 @@ Vollständiges Schema: [backend/prisma/schema.prisma](backend/prisma/schema.pris
| Bereich | Entscheidung | Begründung |
|---|---|---|
| Backend | NestJS 10 + PostgreSQL + Prisma 5 | bestätigt vom Nutzer; Nest 10 statt CLI-Default (siehe unten) |
| Client | Flutter, eine Codebase Mobile/Web/Desktop | vom Nutzer delegiert; noch nicht scaffoldbar (Flutter fehlt lokal) |
| Client | Flutter, eine Codebase Mobile/Web/Desktop `client/app/`, aktuell nur Web-Target aktiviert | vom Nutzer delegiert; Flutter-SDK lokal via Homebrew installiert (nur Web-Toolchain, Android/iOS wegen Speicher weggelassen); `lib/` ist plattformneutral, weitere Targets per `flutter create --platforms=…` nachrüstbar |
| Web-Interimslösung | Backend liefert `client/web/` (reines HTML/CSS/JS, kein Build-Schritt) über `ServeStaticModule` aus; REST-API liegt unter `/api/*` | Nutzerwunsch: "Server soll auch Web-Client bereitstellen"; vermeidet Kollision zwischen API-Routen und statischen Dateien |
| Auth (Team) | Authentik als OIDC Resource Server (JWKS-Verifikation), kein lokaler Autorisierungscode-Flow im Backend | Clients machen Authorization Code + PKCE direkt gegen Authentik; Backend validiert nur Access Token + löst lokale `Membership` auf |
| Auth (Guest) | Rein lokale JWTs (`GUEST_JWT_SECRET`), kein Authentik | explizite Nutzervorgabe: Konfi-Accounts sind nie in Authentik |
@@ -97,7 +97,7 @@ Details, Setup-Anleitung und `.env`-Variablen: [backend/README.md](backend/READM
4. **Dateifreigabe** Storage-Abstraktion, Sichtbarkeitsstufen. ✅
5. **Kommunikation** Chat (Gruppen/DM/LT/Broadcast), WebSocket. ✅ (Push-Integration noch offen)
6. **Hybrid Lokal/Cloud-Server & Sync** Replikationslog, Scheduler, Shared-Secret-Auth. ✅
7. **Flutter-Clients** gemeinsame Codebase; Screens: Invite/Login, rollenspezifisches Dashboard, Wahl-Formular/Ergebnis, Dateien, Chat, Admin/Nutzerverwaltung. ❌ **offen** (Flutter nicht installiert); Web-Interimslösung siehe Abschnitt 3.
7. **Flutter-Clients** gemeinsame Codebase (`client/app/`, Web-Target). ✅ Grundgerüst: Login (Guest / lokaler Teamer / Invite-Redemption, Token in `shared_preferences`, `GET /auth/me` für rollenabhängige Startseite), Guest-Wahl-Formular (`/wahl/guest/overview` → geordnete Wunsch-Auswahl → Absenden), Datei-Liste, Chat (nur lesen). 🔜 Mobile/Desktop-Targets, Authentik-Auth-Code-Flow, Wahl-**Ergebnis**-Ansicht, WS-Chat-Senden, LT-/Verantwortlichen-Admin-Screens (KC/Gemeinde/Teamer/Onboarding-Freigaben).
---
@@ -112,6 +112,8 @@ Details, Setup-Anleitung und `.env`-Variablen: [backend/README.md](backend/READM
1. Nach jeder Phase: `npx tsc -p tsconfig.build.json --noEmit`, `npx nest build`, sowie ein kurzer Boot-Test (`node dist/main.js`) zur Prüfung, dass der DI-Graph auflöst und alle Routen korrekt gemappt werden (ohne Live-DB/Authentik/Nextcloud).
2. Sync-Modul: manuell verifiziert, dass `SyncSecretGuard` Requests ohne `x-sync-secret` mit 403 ablehnt und mit korrektem Secret durchlässt (DB-Fehler in der Sandbox ist erwartet, da kein Postgres läuft).
3. Web-Client: `GET /` liefert die statische Seite (200), `GET /api/kc` trifft die echte, geschützte API (401 ohne Token).
3a. Gegen lokales **PostgreSQL 16** (Homebrew): `prisma migrate dev --name init` erzeugt/appliziert die erste Migration; Guest-Flow Ende-zu-Ende geprüft (`/auth/guest``/auth/me``/wahl/guest/overview``POST …/teilnehmer` → Re-Fetch zeigt `meinePrioritaeten`). Seed: `prisma/seed-dev.js`.
3b. Flutter-Client (`client/app/`): `flutter analyze` sauber, `flutter build web --release` erfolgreich, `flutter test` grün (Login-Screen-Smoke-Test); CORS-Preflight vom Browser-Origin ok.
4. Jest-Unit-Tests (Prisma/Sync/Mail gemockt, `npm test` grün, 56 Tests):
- `src/wahl/zuteilung.service.spec.ts`: Force-Vorrang, Wunschrunden-Fallback bei voller Kapazität, Unzugeteilt-Fall, Konsolidierung unterbesetzter Workshops, Sync-Capture-Anzahl.
- `src/auth/team-auth.service.spec.ts`: Invite-Redemption (unbekannt/widerrufen/abgelaufen/aufgebraucht, Gruppen-Link ohne E-Mail, E-Mail-Mismatch, Dublette) + Passwort-Login.
@@ -124,8 +126,8 @@ Details, Setup-Anleitung und `.env`-Variablen: [backend/README.md](backend/READM
## 8. Nächste Schritte
1. Sobald Flutter verfügbar ist: Client-Grundgerüst aufsetzen (Mobile + Web + Desktop, eine Codebase), beginnend mit Invite/Login-Flow gegen die bestehende API.
2. Authentik-Provider so konfigurieren, dass das Access-Token den `groups`-Claim trägt (Scope „groups"), und die LT-Gruppe auf `AUTHENTIK_LEITUNGSTEAM_GROUP` abstimmen — sonst greift der LT-Abgleich nicht. (Reine Ops-/Config-Aufgabe, Code ist fertig.)
3. SMTP konfigurieren (`MAIL_PROVIDER=smtp` + `SMTP_*`/`MAIL_FROM`/`APP_BASE_URL`) und die Invite-Mail-Templates finalisieren (aktuell nur Plain-Text); optional Onboarding-Benachrichtigungen an LT.
1. Flutter-Client ausbauen: Authentik-Authorization-Code-Flow (LT/Verantwortliche), Wahl-Ergebnis-Ansicht, LT-/Verantwortlichen-Admin-Screens (KC/Gemeinde/Teamer anlegen, Onboarding-Anfragen freigeben), WS-Chat-Senden, dann Mobile/Desktop-Targets aktivieren.
2. Authentik-Provider so konfigurieren, dass das Access-Token den `groups`-Claim trägt (Scope „groups"), LT-Gruppe = `AUTHENTIK_LEITUNGSTEAM_GROUP`. (Ops/Config, Code ist fertig.)
3. SMTP konfigurieren (`MAIL_PROVIDER=smtp` + `SMTP_*`/`MAIL_FROM`/`APP_BASE_URL`) und Invite-Mail-Templates finalisieren (aktuell Plain-Text); optional Onboarding-Benachrichtigungen an LT.
4. Push-Benachrichtigungen (FCM/APNs) für Chat/Ankündigungen.
5. Echte Infrastruktur (Postgres, Authentik, Nextcloud/S3) aufsetzen, erste Prisma-Migration erzeugen (`prisma migrate dev`, bisher nur `schema.prisma`) und die in Abschnitt 7 offenen Verifikationsschritte durchführen.
5. Echte Authentik- + Nextcloud/S3-Infra anbinden und die in Abschnitt 7 offenen E2E-Verifikationsschritte durchführen (lokales Postgres + Migration sind erledigt).