Kein Addon — fixer Core-Bereich (Sidebar nach „Personen") bzw. Standard-Funktionalität. Live seit v0.20.0 (2026-07-27, Phasen B0–B3 in einem Zug); Bereich «Berechtigungen» komplett umgebaut in v0.26.0 (2026-09-01: drei Register, Berechtigungs-Rollen, Owner = Admin, Admin-Meldungen, Spesen-Freigabe hier pflegbar). Konzept mit allen User-Entscheiden: docs/konzept-berechtigungen-portal.md (Nachtrag v0.26.0 am Ende).
Vor v0.20.0 galt in CluCore „eingeloggt = Vollzugriff" (fast alle Views nur @login_required). Seit v0.20.0:
AuthRoleTemplate.access_level: clucore (volle Verwaltung — owner, admin, eigene Vorstands-Rollen) oder portal (nur Clu-Portal — member, eigene Rollen wie Trainer).
- CluCoreGateMiddleware:
/clucore/* und /api/* nur noch mit aktiver clucore-Rolle (Superuser ok). Portal-User → Redirect /portal/; APIs → 403. Ausnahmen: logout, password-reset, /portal/*, /zugang/*, Kalender-Magic-Links/ICS.
- ⚠️ Jede NEUE API unter
/api/ ist automatisch clucore-only — APIs für Mitglieder gehören unter /portal/api/.
- TenantEmailBackend: Login per E-Mail im Vereins-Kontext der Subdomain (EmailAddress → Person → User). Löst die Kollision:
User.username ist global unique, dieselbe E-Mail kann aber in mehreren Vereinen existieren (interner username bekommt dann ein Suffix). ⚠️ In Tests funktioniert Client.login() damit NICHT (kein request) — Login-POST auf /clucore/ oder force_login verwenden.
- Nach dem Login landen ALLE auf
/portal/ (User-Entscheid: auch der Admin soll zuerst seinen Kalender sehen); CluCore-Berechtigte haben dort den Button „Zum Clu-Core". Lesezeichen auf /clucore/ funktionieren direkt.
Vor v0.26.0 war alles auf einer Seite: Personenliste plus ein Aufklapp-Panel «Rollen verwalten», in dem Feld-Matrix, Werkzeug-Schalter und Ebenen-Schalter in EINEM Block standen, dazu ein Button «Genehmiger» (wofür? Spesen? Self-Service?). Jetzt:
Liste aller Personen (Vorname, Nachname, primäre E-Mail) mit:
- Rollen-Chips (Clu-Core violett / Portal grün), klickbar pro Zeile; Bulk-Zuweisung auf die Auswahl (nur für Admins sichtbar); Namensuche, Rollenfilter (Rolle / «ohne Rolle» / «mit Login») und Quellenfilter Gruppe / Firma / Mitgliedschaft (Gruppen lösen Personen-, Mitglieds- und Firmen-Einträge auf).
- Login-Spalte (Lebenszyklus, Modell
AuthAccess/auth_access):
- keine E-Mail → zuerst bei der Person erfassen
- Login aktivieren → Bestätigungs-Popup, dann Einladungs-Mail mit Set-Password-Link
/zugang/<token>/ (Token nur als SHA-256-Hash gespeichert, Einmalgebrauch; Gültigkeit 3 Wochen bei clucore-Rolle, sonst 3 Monate)
- eingeladen (mit Gültigkeitsdatum) → „Neu versenden"
- abgelaufen (rot) → „Neu versenden" (neues Token)
- aktiv seit → „Login entfernen" (=
user.is_active=False + Session-Kill; der User wird NIE gelöscht — created_by-Referenzen)
- deaktiviert → „Wieder aktivieren" (neue Einladung)
- Regeln: Login ohne Rolle → automatisch „Mitglied". Owner und Admin sind aus User-Sicht EIN Ding («Admin»): Die Owner-Rolle ist unsichtbar, jeder Owner hat seit Migration 0008 zusätzlich die Admin-Rolle. Geschützt ist der letzte Admin mit aktivem Login — er kann weder degradiert noch sein Login entfernt werden (Button gesperrt, Server prüft nochmals). Admins ohne aktives Login zählen dafür nicht.
- Kein Initial-Passwort per Mail (User-Entscheid: Einladungslink); die Set-Password-Seite loggt nach dem Setzen direkt ein.
Links die Rollenliste (Systemrollen Admin und Mitglied mit Erklärtext, darunter die eigenen Rollen mit Personen-Zähler), rechts das Detail in Abschnitten:
- Name + Beschreibung
- «Wo arbeitet diese Rolle?» — Mitglieder-Portal oder Clu-Core (Ebenen-Schalter; Clu-Core öffnet heute den ganzen Verwaltungsbereich ausser Buchhaltung/Faktura/Berechtigungen — echte Teilrechte je Bereich sind das Endziel, B4).
- Werkzeuge im Mitglieder-Portal mit je einem Satz Erklärung: 📁 Datei-Browser, 📅 Kalender, ✏️ Eigene Daten bearbeiten, 🧾 Spesen einreichen (nur mit Buchhaltungs-Addon), 🔍 Revision.
- «Eigene Daten bearbeiten — wie?» — nur informieren / Freigabe nötig, plus die Feld-Matrix (ausgeblendet / anzeigen / bearbeitbar je Feld, inkl. Custom-Spalten und eigener Mitgliedschaft).
- Personen mit dieser Rolle → Sprung in den Personen-Tab mit gesetztem Rollenfilter.
Vorlagen beim Anlegen («+ Neue Rolle»): Trainer/Leiter · Selbstbedienung · Spesen einreichen · Revisor · Verwaltung (Clu-Core) · Leer — jede Vorlage setzt Ebene, Werkzeuge und Selfservice-Modus vor, alles bleibt editierbar. «⊞ Übersicht» zeigt die Matrix Rollen × Werkzeuge auf einen Blick. Deep-Links: ?tab=rollen, ?role=<id>.
- ✏️ Änderungen an eigenen Daten: die Freigabe-Personen für Self-Service-Anträge (früher «Genehmiger»; leer → alle Admins).
- 🧾 Spesen: dieselbe Komponente wie in Buchhaltung › Einstellungen › Spesen (zwei Personen je Stufe, Betragslimite, Stellvertretung nach n Tagen) — nur sichtbar mit aktivem Buchhaltungs-Addon.
Admin hinzufügen oder entfernen, Login eines Admins entfernen oder reaktivieren: Bestätigungs-Popup (beim Entzug der eigenen Admin-Rolle mit Warnung — danach Redirect, das Gate greift sofort), dann Meldung + Mail an alle aktiven Admins und die betroffene Person (notify_admin_change, Meldungstyp admin_change, Link auf den Bereich). Jede Mutation im Bereich (Rolle zuweisen/entziehen, Rolle anlegen/ändern/löschen, Einladen, Login entfernen, Freigabe-Personen) landet mit Vorher/Nachher im AuthMutationAuditLog (context clucore).
Sicherheits-Fix in derselben Version: Die mutierenden Berechtigungs-APIs hingen bis v0.25.x nur am CluCore-Gate — eine eigene Rolle mit Ebene Clu-Core (z.B. «Vorstand») konnte sich damit selbst die Owner-Rolle geben. Jetzt dürfen nur owner/admin ändern (_admin_required, 403); Clu-Core-Rollen ohne Admin sehen den Bereich lesend (Banner, keine Buttons).
¶ Warum so gebaut — und warum nicht anders
- Drei Register statt Aufklapp-Panels: Personen/Logins, Rollen und Freigaben sind drei verschiedene Fragen («wer darf rein», «was darf eine Rolle», «wer entscheidet»). Auf einer Seite verschmolzen sie zu einem Block, den niemand ohne Erklärung verstand.
- Owner = Admin statt zwei Rollen: Für einen Verein gibt es keinen fachlichen Unterschied — der «Owner» war nur der Gründer aus dem Onboarding. Der technische
owner-Key bleibt in der DB (Onboarding vergibt owner + admin), ist aber nirgends mehr sichtbar oder zuweisbar; aufgeräumt wird er erst, wenn nichts mehr daran hängt.
- Letzter Admin statt letzter Clu-Core-Zugang: Eine eigene Clu-Core-Rolle ist keine Absicherung gegen Aussperrung — sie darf Berechtigungen gar nicht ändern.
- Meldungen + Popup bei Admin-Änderungen: Die Admin-Rolle ist der Vollzugriff; ein stiller Wechsel wäre genau das, was ein Vorstand später nicht mehr rekonstruieren kann.
- Vorlagen statt leerer Rolle: Die typischen Vereins-Rollen sind immer dieselben (Trainer, Revisor, Spesen-Einreicher). Wer mit einer leeren Rolle startet, muss das Rechtemodell erst verstehen — die Vorlage erklärt es durch Vorbelegung.
- Ebenen-Schalter bleibt (statt schon jetzt Teilrechte): Teilrechte je Bereich sind ein eigener Umbau (B4); bis dahin ist «Clu-Core» ehrlich als Vollzugriff beschriftet.
Eigenständige, schlanke Seite in der Vereins-Primärfarbe (aus ClubProfile; bewusst KEINE Einbettung in die extern gerenderte Builder-Webseite — CSP/Proxy):
- Meine Termine: eigene Einladungen (kommende), Zusagen/Absagen direkt im Portal (nur eigene Invites, serverseitig erzwungen; „fixe" Termine sind nur zur Info), ICS-Abo-Link (persönlicher Feed).
- Meine Daten: Person, Adresse, Kontakte, Mitgliedschaften — lesend (User-Entscheid; Feld-Editierbarkeit kommt mit Rollen-Modellen/B4) + „Korrektur melden" (Mail an alle CluCore-Berechtigten).
- Passwort ändern, Abmelden; „Zum Clu-Core"-Button nur für Berechtigte.
- Addon Nr. 23 „Intranet/mitglieder-portal" aus dem Katalog entfernt (Standard statt Addon).
has_login-Spalte („Login") aus der Personen-Liste entfernt — Zugriffsstatus lebt im Berechtigungen-Bereich.
- Hinweis-Kachel „wenig Logins" verlinkt auf den neuen Bereich.
Echte Teilrechte je Bereich für Clu-Core-Rollen (Endziel laut User; ersetzt den Ebenen-Schalter), Trainer-Tools (Termine für die eigene Gruppe u.ä.), Kassier-Teilrechte in der Buchhaltung.