shinkan-jinkendo/docs/jinkendo-family/FAMILY_ENTITLEMENT_MODEL.md
Lars 6c7c24e887
All checks were successful
Deploy Development / deploy (push) Successful in 48s
Test Suite / pytest-backend (push) Successful in 45s
Test Suite / lint-backend (push) Successful in 1s
Test Suite / build-frontend (push) Successful in 15s
Test Suite / k6 /health Baseline (push) Successful in 34s
Test Suite / playwright-tests (push) Successful in 1m35s
Add Jinkendo family design principles and entitlement model docs.
Document cross-app architecture patterns, Mitai alignment, and family entitlement standards. Documentation only; no runtime changes.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 09:12:48 +02:00

317 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Familien-Modell: Entitlements & Limits
**Status:** Entwurf / verbindliche Zielrichtung (mit bewussten Produkt-Ausnahmen)
**Stand:** 2026-07-04
**Bezüge:**
- [DESIGN_PRINCIPLES_ALIGNMENT.md](./DESIGN_PRINCIPLES_ALIGNMENT.md) — Abgleich Mitai ↔ Shinkan
- Mitai: [FEATURE_ENTITLEMENT_DESIGN_PRINCIPLES.md](file:///c:/Dev/mitai-jinkendo/.claude/docs/jinkendo-foundation/design-principles/FEATURE_ENTITLEMENT_DESIGN_PRINCIPLES.md)
- Shinkan: [CAPABILITY_ENTITLEMENT_DESIGN_PRINCIPLES.md](./design-principles/CAPABILITY_ENTITLEMENT_DESIGN_PRINCIPLES.md)
---
## 1. Zweck
Dieses Dokument definiert das **gemeinsame Entitlement-Modell** der Jinkendo-Produktfamilie:
- **Was** für neue Apps und Refactors **Standard** ist
- **Welche Produkt-Profile** welche Scopes nutzen (Account, Tenant, beides, keins)
- **Wie** bewusste Abweichungen dokumentiert werden — Abweichung ist erlaubt, **Undokumentiertheit** nicht
**Nicht enthalten:** Stripe/SSO (`auth.jinkendo.de`), vollständige Billing-Implementierung, app-spezifische Feature-IDs.
---
## 2. Leitgedanke: Vier getrennte Fragen
Jede geschützte Aktion durchläuft konzeptionell **vier unabhängige Prüfungen**. Nicht jede App implementiert alle vier — siehe §6.
| # | Frage | Familien-Begriff | Typische Quelle |
|---|--------|------------------|-----------------|
| **A** | Wer ist eingeloggt? | **Auth** (Identität) | Session → `profile_id` |
| **B** | Darf diese Rolle die **Funktion** ausführen? | **Capability** (Permission) | Rollen-Matrix, `min_account_state` |
| **C** | Ist das **Kontingent** erschöpft? | **Feature / Limit** (Quota) | Plan, Tier, Usage-Zähler |
| **D** | Darf ich **dieses Objekt** lesen/ändern? | **Governance** (Object ACL) | `visibility`, `club_id`, Owner |
```
Request → Auth (A) → [Capability (B)] → [Feature-Limit (C)] → [Governance (D)] → Handler
```
**Familien-Regel:** B, C und D **nicht** in React-Widgets oder Router-Inline-Logik vermischen — jeweils eine Auflösungsfunktion pro Ebene.
**Shinkan-Ergänzung:** Governance ist dort ausgebaut (`TenantContext`, Access Layer); Mitai fokussiert A+B+C auf Profil-Ebene.
---
## 3. Familien-Standard: Zwei Subjekt-Ebenen
Limits und Pläne können an **zwei Subjekte** hängen. Beide sind im Familienmodell **first-class** — Apps wählen, welche sie nutzen (§6).
| Subjekt | ID | Typische Frage | Beispiel |
|---------|-----|----------------|----------|
| **Account** | `profile_id` | Was darf **ich** als Nutzer (Tarif)? | Mitai Free vs. Premium |
| **Tenant** | `tenant_id` (z. B. `club_id`) | Was darf **meine Organisation**? | Shinkan Vereinsplan, KI-Kontingent |
### 3.1 Auflösungs-Reihenfolge (wenn beide Ebenen aktiv)
Für eine Aktion mit Capability `X` und Feature `Y`:
1. **Account-Lifecycle** — z. B. E-Mail verifiziert, Onboarding abgeschlossen
2. **Capability(B)** — Rolle darf Funktion (Account- und/oder Tenant-Rollen)
3. **Feature(C)** — Kontingent am **primären Billing-Subjekt** der App (siehe Produkt-Profil)
4. **Governance(D)** — Objekt sichtbar/bearbeitbar
**AND-Verknüpfung:** Alle aktiven Ebenen müssen passieren. Ausnahmen nur in §6.3 dokumentiert.
### 3.2 Primäres Billing-Subjekt pro App
| Profil | Primäres Subjekt für Limits | Capability-Subjekt |
|--------|----------------------------|-------------------|
| Personal App (Mitai) | **Account** | Account |
| Mandanten-App (Shinkan) | **Tenant** | Account + Tenant-Rolle |
| Hybrid (Zukunft) | konfigurierbar | beide |
---
## 4. Familien-Standard: Capabilities vs. Features
| Konzept | Familien-Definition | Subjekt | Beispiel |
|---------|---------------------|---------|----------|
| **Capability** | Binäre oder rollenbasierte **Erlaubnis** („darf ich?“) | meist Account + Tenant-Kontext | `exercises.ai.suggest` |
| **Feature** | **Kontingent** oder Boolean-Limit („wie oft/noch?“) | Account **oder** Tenant | `ai_calls` / Monat |
| **Verknüpfung** | Capability kann `linked_feature_id` haben | — | KI-Capability → KI-Kontingent |
**Familien-Regel:**
- Capabilities **registry-first** registrieren (Code → DB-Sync, Shinkan-Muster).
- Feature-IDs **nicht** in UI hardcoden — nur aus Entitlements-Response.
- `NULL` Limit = unbegrenzt; `0` = deaktiviert (Mitai-Semantik, familienweit).
---
## 5. Familien-Standard: API & Enforcement
### 5.1 Ziel-API (neue Apps)
Ein **einheitlicher Snapshot** für das Frontend:
```
GET /api/me/entitlements
?tenant_id=<optional>
Response (skizziert):
{
"account": {
"profile_id": 1,
"account_state": "active_member",
"tier_id": "premium", // optional, Account-Apps
"features": { "ai_calls": { "allowed", "used", "limit", "remaining", "reset_at" } },
"capabilities": { "analysis.run": { "allowed": true, "reason": null } }
},
"tenant": { // null wenn App keinen Tenant kennt
"tenant_id": 42,
"tenant_type": "club",
"plan_id": "pro",
"features": { ... },
"capabilities": { ... },
"roles": ["trainer"]
},
"enforcement": {
"capabilities": "enforce|probe",
"features": "enforce|probe"
}
}
```
**Familien-Regel:** UI liest **nur** diesen Snapshot (oder domänenspezifische Teilmenge) — keine parallelen `/subscription/me` + `/features/usage` + Ad-hoc-Checks in neuen Apps.
### 5.2 Ist-API (bestehende Apps — Abweichung dokumentiert)
| App | Endpoint heute | Familien-Ziel |
|-----|----------------|---------------|
| **Mitai** | `/subscription/me`, `/features/usage`, `check_feature_access` | Snapshot schrittweise; Account-Block reicht |
| **Shinkan** | `GET /api/me/entitlements?club_id=` | Tenant-Block + Capabilities; Account-Tier fehlt bewusst |
Migration: **kein Big-Bang** — alte Endpoints als Facade auf Snapshot mappen.
### 5.3 Vier-Phasen-Rollout (familienweit verbindlich)
| Phase | Verhalten | Env-Beispiel |
|-------|-----------|--------------|
| **1** | Cleanup Legacy-Flags | — |
| **2** | **Probe** — JSON-Log, HTTP 200 | `*_ENFORCE=0` |
| **3** | Frontend-Gates aus Entitlements | — |
| **4** | **Enforce** — HTTP 403 | `*_ENFORCE=1` |
**Familien-Regel:** Phase 4 für **neue** kritische Features von Anfang an planbar; Bestands-Apps dürfen in Phase 23 bleiben bis kalibriert.
### 5.4 Enforcement-Priorität
1. **API** — autoritativ (`403`)
2. **Frontend** — UX (Badges, disabled Buttons)
3. **Niemals** — nur UI ohne API-Gate
---
## 6. Produkt-Profile & bewusste Abweichungen
Abweichungen vom Familien-Standard sind **zulässig**, wenn sie in der Tabelle **§6.2** stehen und begründet sind.
### 6.1 Profil-Matrix (Soll)
| Profil | Apps | Account-Limits | Tenant-Limits | Capabilities | Governance (Objekt) |
|--------|------|----------------|---------------|--------------|---------------------|
| **P1 Personal** | Mitai | ✅ primär | ❌ | ✅ Account | minimal / privat |
| **P2 Mandant** | Shinkan | ⚠️ Lifecycle only | ✅ primär | ✅ Account + Tenant-Rollen | ✅ Access Layer |
| **P3 Minimal** | Miken, Ikigai (geplant) | optional | ❌ | optional | minimal |
| **P4 Hybrid** | (Reserve) | ✅ | ✅ | ✅ beide | ✅ |
### 6.2 Registrierter Abweichungs-Katalog
| ID | App | Abweichung vom Familien-Standard | Begründung | Review |
|----|-----|----------------------------------|------------|--------|
| **DEV-01** | Mitai | Kein `tenant`-Block in Entitlements | Persönliche Tracking-App; kein Verein | Beibehalten (P1) |
| **DEV-02** | Mitai | Kein Capability-Katalog (nur Features+Tier) | RBAC = admin/user ausreichend | Optional später `account.*` Capabilities |
| **DEV-03** | Mitai | Mehrere Nutzer-APIs statt einem Snapshot | Historisch gewachsen | Facade → Snapshot (mittelfristig) |
| **DEV-04** | Mitai | Legacy Session-Spalten (`ai_enabled`, …) parallel Features | Migrationsschuld | Bereinigen, nicht in neue Apps |
| **DEV-05** | Shinkan | Kein Account-Tier / `profiles.tier` | Verein zahlt, nicht Trainer | Beibehalten (P2) |
| **DEV-06** | Shinkan | Capabilities **und** Governance (zwei Achsen) | Trainer vs. Objekt-Rechte | Familien-Vorbild für P2/P4 |
| **DEV-07** | Shinkan | `check_feature_access` (Mitai-Legacy) explizit verboten | Falsches Subjekt | Beibehalten |
| **DEV-08** | Shinkan | Enforcement oft Probe-only | Rollout-Sicherheit | → Phase 4 bis Datum X |
| **DEV-09** | Shinkan | Inventar-Features live gezählt | Drift-Vermeidung | Abweichung OK; in P2 dokumentieren |
| **DEV-10** | Beide | Kein atomares Check+Increment | Race bei Parallel-Requests | Familien-Backlog; Workaround dokumentieren |
| **DEV-11** | Neue Apps | dürfen **nur** Account **oder** nur Tenant wählen | MVP | Eintrag hier anlegen vor Launch |
**Neue Abweichung:** Zeile in §6.2 + ggf. ein Satz im App-`CLAUDE.md`.
### 6.3 Dokumentierte Ausnahmen (Bypass)
| Ausnahme | Apps | Regel |
|----------|------|-------|
| Plattform-Admin Audit | Shinkan | Quota-Bypass über Grants, nicht pauschal superadmin |
| Admin ohne Auto-Bypass | Mitai | Admins unterliegen Limits (Produktentscheid) |
| Öffentliche Routen ohne Auth | alle | Kein Entitlement-Check |
---
## 7. Mapping: Familien-Begriff ↔ Implementierung
### 7.1 Mitai (Profil P1)
| Familien | Mitai-Implementierung |
|----------|----------------------|
| Account-Features | `features`, `tier_limits`, `user_feature_usage` |
| Account-Tier | `get_effective_tier()`, `access_grants` |
| Check | `check_feature_access(profile_id, feature_id)` |
| Increment | `increment_feature_usage(profile_id, …)` |
| UI | `UsageBadge`, Widget `allowed` |
### 7.2 Shinkan (Profil P2)
| Familien | Shinkan-Implementierung |
|----------|-------------------------|
| Tenant-Features | `club_plan_limits`, `club_feature_usage`, `club_features.py` |
| Tenant-Plan | `get_effective_club_plan(club_id)` |
| Capabilities | `check_capability`, `capabilities` + `rights_registry` |
| Snapshot | `build_me_entitlements()``GET /me/entitlements` |
| Governance | `TenantContext`, `club_tenancy`**kein** Ersatz für Capabilities |
### 7.3 Gemeinsame Muster (copy-ready)
| Muster | Mitai | Shinkan |
|--------|-------|---------|
| Feature-Registry in DB | ✅ | ✅ (`app='shinkan'`) |
| Plan × Feature Matrix | `tier_limits` | `club_plan_limits` |
| Admin-Override | `user_feature_restrictions` | `club_feature_overrides` |
| Promo/Trial | `access_grants` | `club_access_grants` |
| 4-Phasen-Rollout | ✅ | ✅ |
| Registry-first neue IDs | ⚠️ teils hardcoded | ✅ `rights_registrations/` |
---
## 8. Entscheidungsregeln für neue Produkte
### 8.1 Pflicht (alle Apps mit Auth)
- [ ] Session → `profile_id`; kein Client-Header als Autorität
- [ ] Entitlements-Auflösung **eine Funktion pro Ebene** (Capability, Feature)
- [ ] API-Enforcement vor UI-Gate
- [ ] 4-Phasen-Rollout dokumentiert
- [ ] Produkt-Profil (P1P4) gewählt + Abweichungen in §6.2
### 8.2 Wenn Personal App (P1)
- [ ] Primäres Subjekt = Account
- [ ] `tenant`-Block in API = `null` (DEV-01-Analog)
- [ ] Feature-Registry + Tier-Matrix
### 8.3 Wenn Mandanten-App (P2)
- [ ] Primäres Subjekt = Tenant
- [ ] `TenantContext` + Governance getrennt von Capabilities
- [ ] Capabilities registry-first
- [ ] Account nur Lifecycle (verified, member) — kein Tier nötig (DEV-05-Analog erlaubt)
### 8.4 Wenn Minimal App (P3)
- [ ] Explizit: „keine Limits“ oder nur Boolean-Features — in §6.2 eintragen
- [ ] Kein halbes Mitai-v9c kopieren
---
## 9. Konvergenz-Roadmap (optional, nicht blockierend)
| Schritt | Mitai | Shinkan | Familie |
|---------|-------|---------|---------|
| **Kurz** | Legacy Session-Flags entfernen | `CAPABILITY_ENFORCE` / `CLUB_FEATURE_ENFORCE` Prod | DEV-04, DEV-08 schließen |
| **Mittel** | `/me/entitlements` Account-Block | Snapshot um `tenant`-Typ metadata erweitern | Facade alte APIs |
| **Lang** | Optional `tenant_id` reservieren (null) | Optional Account-Tier für Cross-Sell | Shared package `jinkendo_entitlements` |
| **Vision** | SSO + zentraler Billing | Vereins-Abo Stripe | `CENTRAL_SUBSCRIPTION_SYSTEM` |
**Wichtig:** Konvergenz ist **empfohlen**, nicht Pflicht — solange §6.2 aktuell bleibt.
---
## 10. Anti-Patterns (familienweit verboten)
1. Tier- oder Plan-Namen in React-Komponenten hardcoden
2. Limit-Logik nur im Frontend
3. Shinkan-Vereinslimits über Mitai `check_feature_access(profile_id)`
4. Capability-Check durch Governance ersetzen (oder umgekehrt)
5. Neue Feature-IDs nur in SQL-Migration ohne Registry
6. Enforcement Phase 4 „vergessen“ bei paid Features ohne dokumentierte Probe-Phase
7. Undokumentierte Produkt-Abweichung (nicht in §6.2)
---
## 11. Offene Familien-Entscheidungen (Backlog)
| ID | Frage | Optionen | Default wenn unentschieden |
|----|-------|----------|----------------------------|
| **FD-01** | Atomares check+increment | DB-Lock / Transaction / Queue | Status quo + Retry-Hinweis in Doku |
| **FD-02** | Shared Python-Modul | Monorepo-Paket vs. Copy+Sync | Copy+Sync mit gleicher API-Shape |
| **FD-03** | Capability-Namespace global | `jinkendo.*` vs. app-prefix | `{app}.{domain}.{action}` |
| **FD-04** | Mitai bekommt Capability-Layer? | ja/nein/später | nein (DEV-02) bis Bedarf |
| **FD-05** | Ein `features.app` für alle Apps | gemeinsame DB vs. pro Deploy | pro Deploy (heute) |
---
## 12. Verwandte Dokumente
| Dokument | Inhalt |
|----------|--------|
| [DESIGN_PRINCIPLES_ALIGNMENT.md](./DESIGN_PRINCIPLES_ALIGNMENT.md) | Vollständiger Mitai ↔ Shinkan Abgleich |
| [design-principles/CAPABILITY_ENTITLEMENT_DESIGN_PRINCIPLES.md](./design-principles/CAPABILITY_ENTITLEMENT_DESIGN_PRINCIPLES.md) | Shinkan Ist-Prinzipien |
| [ACCESS_LAYER_DESIGN_PRINCIPLES.md](./design-principles/ACCESS_LAYER_DESIGN_PRINCIPLES.md) | Governance (Ebene D) |
| Mitai Foundation #3 | Feature & Entitlement Ist Mitai |
| Shinkan `CLUB_MEMBERSHIP_AND_FEATURES.v1.md` | Vereins-Abo Detail |
| Shinkan `CAPABILITY_CATALOG.v1.md` | Capability-IDs |
---
## 13. Changelog
| Datum | Änderung |
|-------|----------|
| 2026-07-04 | Entwurf: Familien-Standard, Produkt-Profile P1P4, Abweichungs-Katalog DEV-0111 |