New screens (client/app/lib/screens/): - wahl_admin_screen.dart — per KC: list/create Wahlen; per Wahl: add workshops, run the assignment (POST /wahl/:id/zuteilung/run), view the result table. - teamer_admin_screen.dart — per Gemeinde: list/create local Teamer accounts, create group-link or per-email invites (shows the token). - verantwortliche_register_screen.dart — enter a KC invite code (GET /onboarding/kc/:code), pick a Gemeinde, submit (POST /onboarding/verantwortliche); shown on the home screen to a logged-in Authentik user who has no membership yet. - ui.dart — shared toast / ErrorText / SectionHeader / promptText. KcDetailScreen now links to Wahl admin and each Gemeinde row opens Teamer admin. Backend: widen the wahl + files LT routes to AuthGuard(['authentik','team']) for consistency with the other LT controllers. Rebrand web/index.html + manifest from "kc_app" to "KC-App". Verified against local Postgres with an isLeitungsteam team token: create KC/Gemeinde/Wahl/Workshop, run Zuteilung, create Teamer + invite, resolve an invite code. flutter analyze/test/build web green; backend npm test 56. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
KC-APP
Multi-tenant event, election and communication platform for Konfi-Castle events (KCs), replacing the WordPress plugin "Workshop-Wahlen". See plan-kcAppMultiTenantPlatform.prompt.md for the full architecture and phased roadmap.
Structure
backend/— NestJS API (Prisma/PostgreSQL, Authentik OIDC as resource server, guest/Konfi local accounts, roles/permissions foundation, file sharing, chat, local/cloud sync). See 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/web/— minimal dependency-free HTML/CSS/JS placeholder web client, served by the backend at/. Superseded by the Flutter web build; kept for now as a zero-dependency fallback.
Status
Phase 0/1 foundation implemented: monorepo skeleton, Prisma data model (Kc, Gemeinde, User, Membership, GuestAccount, Wahl/Workshop/Teilnehmer/Zuteilung, File, Chat), Authentik JWT resource-server strategy, guest invite-code login, Role-based guard scoped per KC.
Phase 2 (Workshop-Wahl engine) implemented: Wahl/Workshop administration,
guest Teilnehmer submission, Force-Zuteilung overrides, and the assignment
algorithm ported from the WP plugin's kc_run_zuteilung (force-assignments →
wish rounds 1-3 → random fill → consolidation of underfilled workshops),
plus CSV export.
Phase 3 (Dateifreigabe) implemented: Leitungsteam-only upload tagged with a
visibility tier (alle / alle außer Konfis / nur LT), list/download for
Authentik or guest callers filtered by their allowed tiers, storage behind a
provider abstraction defaulting to Nextcloud/WebDAV (S3-compatible storage
as an alternative via STORAGE_PROVIDER=s3).
Phase 5 (Kommunikation) implemented: Gemeinde-Gruppenchat, 1:1-DMs, LT- kanalübergreifende Kanäle, Broadcast (read-only für Konfis); channel/history via REST, real-time send/receive via a raw WebSocket gateway authenticated with the same Authentik/guest tokens as the REST API.
Phase 6 (Hybrid Lokal/Cloud-Server & Sync) implemented: an append-only
replication log (SyncLogEntry) captured by every feature service after its
writes; the local (on-site) server periodically pushes/pulls against the
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.
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).
Phase 7 (Flutter client) in progress: client/app/ is a single Flutter
codebase with the web target enabled — guest / local-Teamer / invite
login, the Authentik Authorization-Code + PKCE flow (lib/oidc.dart) for
Leitungsteam/Verantwortliche, role-aware home, guest Workshop-Wahl (wishes +
result), file list, live WebSocket chat, and a Leitungsteam admin screen
(KCs, Gemeinden, onboarding approvals). flutter build web / flutter test
pass; the backend serves the build at / (SPA fallback covers the OIDC
redirect /v1/auth/callback). Still to do: a live browser test of the OIDC
round-trip, the Teamer-management and Verantwortlichen-self-registration
screens, LT Wahl administration, mobile/desktop targets, and push.
Running end to end needs the Authentik redirect registered + a test account,
plus Nextcloud/S3 credentials (see backend/.env.example).