# Capability & Club Features – Designprinzipien (Extraktion) **Status:** Analyse / Arbeitspapier **Stand:** 2026-07-04 **Geltungsbereich:** Modul „Capabilities & Vereins-Feature-Kontingente“ — nicht Billing/Stripe **Serie:** Designprinzipien für Produktfamilie · Shinkan Dokument 2 von 15 **Mitai-Vergleich:** [FEATURE_ENTITLEMENT_DESIGN_PRINCIPLES.md](file:///c:/Dev/mitai-jinkendo/.claude/docs/technical/FEATURE_ENTITLEMENT_DESIGN_PRINCIPLES.md) (#3) **Kernkomponenten:** | Bereich | Pfade | |---------|-------| | Capabilities | `backend/capabilities.py` | | Vereins-Features | `backend/club_features.py` | | Entitlements-API | `backend/entitlements.py`, `backend/routers/me_entitlements.py` | | Quota-Bypass | `backend/club_quota_bypass.py` | | Spez | `CAPABILITY_CATALOG.v1.md`, `CLUB_MEMBERSHIP_AND_FEATURES.v1.md` | --- ## Modul **Capability & Club Feature Entitlements** Zwei Schichten: **Capabilities** (darf Nutzer X im Verein Y?) und **Club Features** (Kontingente/Limits pro Verein, Subjekt `club_id`). Zusammenführung in `GET /api/me/entitlements`. --- ## Fachliche Verantwortung 1. **Capability-Checks** — `check_capability`, `probe_capability`, `require_capability` mit Env `CAPABILITY_ENFORCE`. 2. **Vereins-Kontingente** — `probe_club_feature_access`, `consume_club_feature_with_usage` mit Env `CLUB_FEATURE_ENFORCE`. 3. **Entitlements-Snapshot** — Frontend erhält `capabilities` + `features` + Plan für UI-Gating ohne Tier-Logik in Widgets. 4. **Account-Lifecycle** — `min_account_state` blockiert Capabilities vor Verifizierung. ### Unterschied zu Mitai | Aspekt | Mitai | Shinkan | |--------|-------|---------| | Limit-Subjekt | Profil / Subscription | **Verein** (`club_id`) | | Rollen | Tier + Features | Vereinsrollen + Portal-Rolle | | Legacy | `check_feature_access` (001) | Explizit **nicht** für Shinkan-Limits nutzen | --- ## Designprinzipien ### 1. Eine Entitlements-API für das Frontend | | | |---|---| | **Prinzip** | `GET /api/me/entitlements?club_id=` liefert Capabilities-Map + Feature-Kontingente + Plan. | | **Begründung** | Keine Tier-Logik in React-Komponenten; ein Roundtrip pro Mandantenwechsel. | | **Quelle** | `entitlements.py`, `me_entitlements.py` | | **Tragfähigkeit** | **hoch** | | **Einschränkung** | Nicht alle UI-Stellen nutzen Entitlements konsequent. | ### 2. 4-Phasen-Rollout (Probe → Enforce) | | | |---|---| | **Prinzip** | Phase 2: JSON-Log ohne Block; Phase 3+: `CAPABILITY_ENFORCE=1` / `CLUB_FEATURE_ENFORCE=1` → HTTP 403. | | **Begründung** | Sicheres Einführen ohne Produktions-Crash; Audit vor Hard-Block. | | **Quelle** | `capabilities.py`, `club_features.py`; Mitai-Vorbild in Spec | | **Tragfähigkeit** | **hoch** | | **Einschränkung** | Env-Flags müssen pro Umgebung bewusst gesetzt werden. | ### 3. Capabilities verknüpft mit Features | | | |---|---| | **Prinzip** | Capability kann `linked_feature_id` haben — Kontingent-Check vor Ausführung. | | **Begründung** | Recht und Limit bleiben getrennt modelliert aber gemeinsam enforcebar. | | **Quelle** | `capabilities`-Tabelle; `check_capability` | | **Tragfähigkeit** | **hoch** | | **Einschränkung** | Nicht jede Capability hat linked Feature. | ### 4. Enforcement an der API, nicht in der UI | | | |---|---| | **Prinzip** | Router rufen `require_capability` / `probe_club_feature_access` — UI blendet nur vor. | | **Begründung** | API ist Source of Truth; UI-Gating allein ist umgehbar. | | **Quelle** | `exercise_ai.py`, Planungs-KI-Router | | **Tragfähigkeit** | **hoch** | | **Einschränkung** | Teilweise noch Probe-only in Prod. | ### 5. Bestands-Features als Live-Zählung | | | |---|---| | **Prinzip** | Inventar-Features (`exercises`, `training_groups`, …) zählen live in DB, nicht nur `club_feature_usage`. | | **Begründung** | Keine Drift zwischen tatsächlichem Bestand und Usage-Tabelle. | | **Quelle** | `_INVENTORY_FEATURES` in `club_features.py` | | **Tragfähigkeit** | **mittel** | | **Einschränkung** | Performance bei großen Vereinen — ggf. Cache nötig. | ### 6. Quota-Bypass für Plattform-Rollen | | | |---|---| | **Prinzip** | Konfigurierbare Bypass-Capabilities (`domain=quota_bypass`) für Support/Admin ohne harte Limits. | | **Begründung** | Betrieb und Demos ohne Plan-Upgrade. | | **Quelle** | `club_quota_bypass.py`; `entitlements.py` | | **Tragfähigkeit** | **mittel** | | **Einschränkung** | Missbrauchsrisiko — nur dokumentierte Grants. | --- ## Nicht übernehmen 1. **Mitai `auth.check_feature_access` für Shinkan-Vereinslimits** — profil-zentriert, falscher Subjekt-Scope. 2. **Tier-Logik in Frontend-Widgets** — gehört in Entitlements-Response. 3. **Enforcement ohne Probe-Phase** — bricht bestehende Vereine ohne Vorwarnung. 4. **Capabilities ohne DB-Sync aus Registry** — siehe Rights-Registry-Dokument. --- ## Verwandte Dokumentation - [CAPABILITY_CATALOG.v1.md](../../../.claude/docs/technical/CAPABILITY_CATALOG.v1.md) - [CLUB_MEMBERSHIP_AND_FEATURES.v1.md](../../../.claude/docs/technical/CLUB_MEMBERSHIP_AND_FEATURES.v1.md) - [RIGHTS_REGISTRY_DESIGN_PRINCIPLES.md](./RIGHTS_REGISTRY_DESIGN_PRINCIPLES.md) - [DESIGN_PRINCIPLES_INDEX.md](./DESIGN_PRINCIPLES_INDEX.md)