- Revised the status in the Capability Catalog to reflect partial implementation (M3). - Added a new reference to `MEMBERSHIP_RBAC_DECISIONS_2026-06.md` in both the Capability Catalog and Club Membership documentation. - Enhanced the Club Membership documentation with details on product decisions and onboarding phases. - Implemented middleware in the backend to restrict access for unverified users and those pending club membership. - Updated versioning in `version.py` to reflect changes in account lifecycle management.
8.6 KiB
Membership, RBAC & Kontingente — Produktentscheidungen
Status: Verbindlich (Zielbild & Roadmap-Priorisierung)
Stand: 2026-06-06
Bezüge: CAPABILITY_CATALOG.v1.md, CLUB_MEMBERSHIP_AND_FEATURES.v1.md, ACCESS_LAYER_AND_GOVERNANCE_PLAN.md
Dieses Dokument hält getroffene Produktentscheidungen fest (Session 2026-06-06) und ergänzt die v1-Konzept-Specs um Umsetzungsrichtung. Technischer Implementierungsstand: Abschnitt 2.
1. Getroffene Entscheidungen
1.1 Onboarding: verified_pending_club
Nutzer ohne aktive Vereinsmitgliedschaft (E-Mail verifiziert) dürfen nur:
| Erlaubt | Nicht erlaubt (Zielbild) |
|---|---|
| Konto / Einstellungen | Übungen, Planung, KI, Medien |
| Vereinsverzeichnis lesen | Vereinsinterne Inhalte (club), private Fremdinhalte |
| Beitrittsantrag an bestehenden Verein | Vollzugriff auf Bibliothek / offizielle Inhalte (Lesen) — bewusst gesperrt bis Mitgliedschaft |
| Vereinsgründung beantragen (Prozess M7, Superadmin-Freigabe) |
Kein „Bibliothek durchstöbern“ für Bewerber — reduziert Datenexposition und vereinfacht UX („erst Verein, dann Arbeit“).
Technischer Zustand: account_state = verified_pending_club (siehe CAPABILITY_CATALOG.v1.md §3).
1.2 Rollenmodell: Risikoarm statt Big-Bang
Zielbild (langfristig):
- Fest: nur
superadmin(Plattform) als nicht konfigurierbare Systemrolle. - Dynamisch konfigurierbar: alle Vereinsrollen und deren Capability-Bundles (später
club_custom_roles). - Optional:
admin(Plattform) als abgeschwächter Portal-Admin bleibt vorerst bestehen (Ist-Code).
Entscheidung v1 (risikoarm):
| Maßnahme | Jetzt | Später |
|---|---|---|
Alte Helfer (can_plan_in_club, if (club_admin) in JSX) |
Behalten — weiter produktiv | Schrittweise durch entitlements ersetzen |
| Neue Endpoints / Features | Nur über Capability-IDs + Audit | — |
| Neue Vereinsrollen | Als Systemrollen ergänzen (z. B. co_trainer) |
Custom Roles UI |
club_custom_roles |
Nicht in v1 | v2 Epic |
Begründung: Backend und Frontend haben hunderte Verdrahtungen auf trainer / club_admin / Plattform-Rollen. Parallelbetrieb Capability-System + Legacy-Helfer ist sicherer als einmaliges Aufbrechen.
Co-Trainer (geplant als Systemrolle): weniger Capabilities als trainer (z. B. kein planning.*, kein exercises.create) — Umsetzung nach Onboarding-Gates + Entitlements-Rollout, nicht vorher.
1.3 Vereins-Kontingente (Membership-Pakete)
Jetzt: Schema und Anzeige vorbereiten; keine detaillierte Paket-Logik (z. B. „3 Trainer + 10 Co-Trainer“) implementieren.
| Vorbereitet (DB/Module) | Bewusst zurückgestellt |
|---|---|
features, club_plans, club_subscriptions |
Eigene Feature-IDs trainer_seats / co_trainer_seats |
Bestands-Limits (exercises, training_groups, ai_calls, …) |
Zählregel „nur planungsberechtigte Mitglieder“ vs. alle Mitglieder |
GET /me/entitlements Feature-Teil |
Stripe / Rechnung (M8) |
Prinzip: Neue Kontingent-Typen = neue features-Zeile + Plan-Limits + optional Capability-linked_feature_id — ohne Schema-Bruch.
1.4 Trainer-Budget innerhalb Vereins-Kontingent (v2)
Anforderung: Vereins-KI-Kontingent liegt beim Verein; Vereinsadmin kann pro Trainer ein Sub-Budget vergeben (Fairness, „Kontingent-Fresser“).
Entscheidung:
- v1: nur Vereins-Ebene (
club_plan_limits,club_feature_usage). - v2: neue Tabellen (Skizze):
-- Skizze — noch nicht migriert
club_member_feature_budgets (club_id, profile_id, feature_id, limit_value, …)
club_member_feature_usage (club_id, profile_id, feature_id, usage_count, reset_at, …)
Prüf-Kette v2: Capability → Mitglieds-Budget (falls gesetzt) → Vereins-Kontingent.
Fairness-Modell (offen, Tendenz): harte Sub-Budgets (Modell A) — Trainer darf sein Budget nicht überschreiten, auch wenn Verein noch Rest hat.
1.5 Enforcement-Phasen (unverändert, bestätigt)
| Phase | Verhalten | Nutzer sichtbar |
|---|---|---|
| 2 (M2/M3) | JSON-Log, kein Block | Nein (außer Logs) |
| 3 (M4) | GET /me/entitlements + Badge |
Kontingent-Anzeige |
| 4 (M5+) | HTTP 403 + increment |
Hard-Block |
Env-Schalter: ACCOUNT_GATE_ENFORCE (Default 1, Endpoint-Helfer), ACCOUNT_GATE_API_ENFORCE (Default 1, API-Middleware Phase A), CAPABILITY_ENFORCE / CLUB_FEATURE_ENFORCE (Default 0).
2. Implementierungsstand (Ist, Codebase)
DB-Schema: 20260606079 (backend/version.py)
Deploy-Referenz: Dev mit M2-Logging verifiziert (club-feature-usage.log).
M1 — Feature-Schema v9c ✅
| Deliverable | Status |
|---|---|
Migration 078_club_features_and_plans.sql |
✅ |
Legacy 001 archiviert |
✅ |
club_plans, club_subscriptions, Usage-Tabellen |
✅ |
Seed Features + Pläne (free, …) |
✅ |
club_features.py: check_club_feature_access, get_effective_club_plan |
✅ |
Backfill Vereine → Plan free |
✅ |
M2 — Feature-Probe (Log only) ✅
| Deliverable | Status |
|---|---|
club_feature_logger.py → club-feature-usage.log |
✅ |
probe_club_feature_access() |
✅ |
Hooks: KI-Endpoints, POST /exercises, Medien-Upload, Planungs-KI |
✅ |
CLUB_FEATURE_ENFORCE=0 (Default) |
✅ |
M3 — Account-Lifecycle + Capability-Grants ⚠️ teilweise
| Deliverable | Status | Lücke |
|---|---|---|
Migration 079_capabilities.sql + Seed |
✅ | — |
account_lifecycle.py, resolve_account_state |
✅ | — |
capabilities.py, check_capability, probe_capability |
✅ | — |
TenantContext.account_state |
✅ | — |
GET /profiles/me → account_state, club_roles |
✅ | — |
| Account-Gates auf Schreib-/KI-Endpoints | ✅ | Lesepfade für Bewerber noch offen |
CAPABILITY_ENFORCE=0 (nur Log) |
✅ | — |
| Onboarding UX: nur Bewerbung/Gründung | ✅ | Phase A: API-Middleware + /onboarding + reduzierte Nav |
club_creation_requests (M7) |
❌ | — |
| Custom Roles / Co-Trainer | ❌ | bewusst v2 |
| Legacy-Helfer entfernt | ❌ | bewusst parallel |
Bewusst zurückgestellt (Roadmap)
| ID | Inhalt |
|---|---|
| M0 | CI-Isolation / Test-DB |
| M5 | Hard-Block Kontingente |
| M6 | Superadmin Admin-UI (Pläne, Capability-Matrix) |
| M7 | Vereinsgründung beantragen |
| M8 | Stripe |
Hinweis: M4 im Repo (über M3 hinaus)
Falls bereits deployed: GET /api/me/entitlements, EntitlementsContext, FeatureUsageBadge — gehört zur Anzeige-Phase 3, nicht zum M3-Kern. Siehe entitlements Modul v1.0.0.
3. Architektur-Zielbild (kompakt)
Request
→ require_auth
→ account_state (Gate)
→ TenantContext
→ assert_capability (Rolle / Funktion)
→ check_club_feature_access (Vereins-Kontingent)
→ [v2] member_feature_budget (Trainer-Budget)
→ Governance (Objekt)
Drei Achsen: Account-Lifecycle · Capabilities · Features (Kontingente). Governance bleibt vierte Prüfung.
4. Empfohlene Roadmap (nach Entscheidungen)
| Phase | Paket | Warum zuerst |
|---|---|---|
| A | Onboarding-Gates vollständig | ✅ umgesetzt (API + Frontend /onboarding) |
| B | M7 Vereinsgründung beantragen | Als Nächstes — zweiter Pfad für verified_pending_club |
| C | M5 Hard-Block ai_calls |
Free-Plan 0 wird real; Badge (M4) liefert Erklärung |
| D | M6 Superadmin-UI | Pläne + Capability-Matrix ohne SQL |
| E | Systemrolle co_trainer + Entitlements im Frontend |
Entscheidung 1.2 risikoarm |
| F | Member-Budgets (v2) | Entscheidung 1.4 |
M0 parallel, nicht blockierend.
5. Offene Punkte (vor M6 / v2)
- Fairness Modell A/B/C für Trainer-Budget (Tendenz: A).
- Ob
admin(Portal) langfristig nebensuperadminbleibt. - Ob offizielle Inhalte für Bewerber nie lesbar bleiben (aktuell: ja).
6. Referenzen
| Pfad | Inhalt |
|---|---|
CAPABILITY_CATALOG.v1.md |
Capability-IDs, Account-States |
CLUB_MEMBERSHIP_AND_FEATURES.v1.md |
Feature-Registry, Kontingente |
backend/club_features.py |
Vereins-Features |
backend/capabilities.py |
Capability-Auflösung |
backend/account_lifecycle.py |
Account-Gates |
Changelog
- 2026-06-06: Initial — Entscheidungen Onboarding, Rollen-Risiko, Kontingente, Trainer-Budget v2; Ist-Stand M1–M3; Roadmap A–F.
- 2026-06-06: Phase A —
account_onboarding_gate.py, Frontend/onboarding, reduzierte Navigation.