feat: client monorepo (Flutter app) + web fallback redesign #1
@@ -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`).
|
||||
|
||||
|
||||
@@ -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 (0–6) 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 0–6 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).
|
||||
|
||||
Reference in New Issue
Block a user