- Introduced a new section for the Jinkendo Foundation, detailing design principles for the product family. - Updated README files to include references to the new design principles documentation. - Enhanced the overall documentation structure to improve navigation and accessibility of design resources. - Ensured consistency across documentation related to the Jinkendo Foundation and its principles.
16 KiB
Feature & Entitlement System – Designprinzipien (Extraktion)
Status: Analyse / Arbeitspapier
Stand: 2026-07-04
Geltungsbereich: Membership-, Tier- und Feature-Limit-System (v9c) — keine Mitai-Domänenlogik, kein zentrales SSO/Stripe (Vision)
Serie: Designprinzipien für Produktfamilie · Dokument 3 von n
Vorgänger: DATA_LAYER_DESIGN_PRINCIPLES.md
Kernkomponenten:
| Bereich | Pfade |
|---|---|
| Entitlement-Auflösung | backend/auth.py (get_effective_tier, check_feature_access, increment_feature_usage) |
| Monitoring | backend/feature_logger.py |
| Nutzer-API | backend/routers/subscription.py, backend/routers/features.py |
| Admin | routers/tiers_mgmt.py, tier_limits.py, coupons.py, access_grants.py, user_restrictions.py |
| Widget-Gating | backend/dashboard_widget_entitlements.py, widget_feature_requirements_db.py |
| Frontend | UsageBadge.jsx, Feature-Usage in Seiten (z. B. Analysis.jsx, WeightPage) |
| Doku | MEMBERSHIP_SYSTEM.md, FEATURE_ENFORCEMENT.md, CENTRAL_SUBSCRIPTION_SYSTEM.md (Vision) |
Modul
Feature & Entitlement System (Membership v9c)
Zentrale Schicht für „Darf dieser Nutzer diese Funktion wie oft nutzen?“ — unabhängig von Auth (Identität) und unabhängig von fachlicher Business-Logik in Routern.
Fachliche Verantwortung
Das System übernimmt:
- Feature-Registry — Deklarative Liste aller limitierbaren Produktfunktionen mit Metadaten.
- Tier-Auflösung — Effektiver Tarif eines Profils (Basis-Tier + zeitliche Grants).
- Limit-Auflösung — Pro Feature: Override → Tier-Limit → Feature-Default.
- Usage-Tracking — Zähler für Count-Features mit optionalem Reset (daily/monthly/never).
- Enforcement — HTTP 403 bei Überschreitung; Frontend-Vorschaum via Badges.
- Beobachtbarkeit — Strukturiertes JSON-Logging aller Access-Checks.
- Promotionen — Coupons → Access Grants (temporäre Tier-Elevation, Pause/Resume).
Es übernimmt nicht:
- Login, Session, Passwort (Auth-Modul)
- Zahlungsabwicklung / Stripe (geplant,
CENTRAL_SUBSCRIPTION_SYSTEM.md) - Mandanten-Isolation (Org/Workspace) — Entitlements sind profile-scoped
- Inhaltliche Berechtigung pro Datensatz (nur Feature-Gates)
Zwei Entscheidungsebenen
| Ebene | Frage | Funktion |
|---|---|---|
| Tier | Welcher Tarif gilt? | get_effective_tier() |
| Feature | Darf Feature X genutzt werden (wie oft)? | check_feature_access() |
Tier beeinflusst Feature-Limits über tier_limits; User-Overrides können Limits unabhängig vom Tier setzen.
Administrierte Konfigurationen
| Konfiguration | Speicherort | Admin-UI |
|---|---|---|
| Feature-Definitionen | features |
Admin Features |
| Tier-Stufen | tiers |
Admin Tiers |
| Tier × Feature Matrix | tier_limits |
Admin Tier Limits |
| User-Overrides | user_feature_restrictions |
Admin User Restrictions |
| Coupons | coupons, coupon_redemptions |
Admin Coupons |
| Temporäre Tier-Grants | access_grants |
(via Coupon/Admin) |
| Widget → Feature Mapping | widget_feature_requirements, Katalog |
Admin Widget Features |
| Usage-Zähler | user_feature_usage |
(automatisch) |
Nicht hardcodiert: Limits pro Tier, Feature-Metadaten, Coupon-Parameter, User-Overrides.
Hardcodiert (Code): Feature-IDs in Routern ('ai_calls', 'weight_entries', …), Reset-Berechnung, 4-Phasen-Muster, 11 initial registrierte Features.
Auflösungs-Hierarchien
Effektiver Tier (get_effective_tier):
- Aktiver
access_grants-Eintrag (is_active,valid_from/valid_until) - Fallback:
profiles.tier
Feature-Limit (check_feature_access → _check_impl):
user_feature_restrictions.limit_value(höchste Priorität)tier_limitsfür effektiven Tierfeatures.default_limit
Limit-Semantik:
limit_type |
Bedeutung |
|---|---|
count |
Zählbares Kontingent; used < limit |
boolean |
An/Aus; limit == 1 erlaubt, 0 gesperrt |
limit_value |
Bedeutung |
|---|---|
NULL |
Unbegrenzt |
0 |
Deaktiviert |
> 0 |
Kontingent oder Boolean „an“ |
Rollen
| Rolle | Darf |
|---|---|
| Admin | Features/Tiers/Limits/Coupons/Restrictions CRUD; alle Nutzer-Overrides |
| Nutzer | Eigene Subscription/Usage lesen (/subscription/me, /features/usage); keine Limit-Änderung |
Enforcement gilt für alle authentifizierten Nutzer gleich — Admins haben keine automatische Bypass-Logik in check_feature_access.
Versionierung, Freigabe, Test
| Mechanismus | Status |
|---|---|
| 4-Phasen-Rollout (Monitor → UI → Enforce) | ✅ dokumentiert & angewendet |
JSON-Log feature-usage.log |
✅ Phase 2 Monitoring |
| DB-Migration v9c für Schema | ✅ |
| Automatisierte Enforcement-Tests pro Router | ⚠️ teilweise (Widgets getestet) |
| Zentrale Policy „jeder Endpoint muss checken“ | ❌ nicht erzwungen |
Designprinzipien
1. Feature-Registry statt hardcodierter Limits
| Prinzip | Jedes limitierbare Produkt-Feature ist Zeile in features — neue Features ohne Schema-Migration für Limits. |
| Begründung | Admin-UI, Usage-API und Backend-Checks teilen dieselbe ID und Metadaten. |
| Quelle | MEMBERSHIP_SYSTEM.md § Feature-Registry; routers/features.py |
| Tragfähigkeit | hoch |
| Einschränkung | Feature-IDs müssen trotzdem in Router-Code referenziert werden. |
2. Eine Auflösungsfunktion für Entitlements
| Prinzip | Alle Backend- und Widget-Checks rufen check_feature_access(profile_id, feature_id) auf. |
| Begründung | Keine duplizierte Tier/Limit-Logik in Routern, Widgets oder Frontend. |
| Quelle | auth.py; dashboard_widget_entitlements.py |
| Tragfähigkeit | hoch |
| Einschränkung | Nicht alle Endpoints nutzen es (z. B. /prompts/execute fehlt). |
3. Getrennte Tier- und Feature-Auflösung
| Prinzip | get_effective_tier() für Tarif; check_feature_access() für konkretes Feature — Tier ist Input, nicht Output der Feature-Prüfung. |
| Begründung | Temporäre Grants heben Tier an; User-Override kann einzelnes Feature unabhängig anpassen. |
| Quelle | auth.py |
| Tragfähigkeit | hoch |
| Einschränkung | get_effective_tier im Code einfacher als in MEMBERSHIP_SYSTEM.md (kein tier_locked, Trial nicht in Tier-Funktion). |
4. Prioritäts-Kette für Limits
| Prinzip | User-Override > Tier-Limit > Feature-Default — explizit und dokumentiert. |
| Begründung | Support/Beta-Fälle ohne Tier-Wechsel; vorhersehbares Verhalten. |
| Quelle | _check_impl() in auth.py; MEMBERSHIP_SYSTEM.md § Zugriffs-Hierarchie |
| Tragfähigkeit | hoch |
| Einschränkung | user_feature_restrictions.enabled im Schema, aber nicht in _check_impl ausgewertet. |
5. Count vs. Boolean als zwei Feature-Klassen
| Prinzip | Zählbare Aktionen (count + Usage) vs. Schalter-Features (boolean, kein Counter). |
| Begründung | Pipeline-An/Aus vs. monatliche KI-Calls — unterschiedliche UX und Backend-Logik. |
| Quelle | features.limit_type; FEATURE_ENFORCEMENT.md |
| Tragfähigkeit | hoch |
| Einschränkung | Boolean-Features nutzen limit_value 0/1 — leicht mit Count zu verwechseln. |
6. Reset-Perioden für Count-Features
| Prinzip | reset_period: never | daily | monthly — Counter-Reset in check_feature_access bei abgelaufenem reset_at. |
| Begründung | Monats-Kontingente vs. Lifetime-Limits in einem Modell. |
| Quelle | auth.py → _calculate_next_reset() |
| Tragfähigkeit | hoch |
| Einschränkung | Reset beim Check, nicht per Cron — Edge Cases bei seltenem Zugriff. |
7. Usage nur bei neuen Entitäten incrementieren
| Prinzip | increment_feature_usage() nur nach INSERT, nicht nach UPDATE/Upsert-Deduplikat. |
| Begründung | Limits messen „neue Nutzung“, nicht Bearbeitung bestehender Daten. |
| Quelle | FEATURE_ENFORCEMENT.md § Wichtige Regeln |
| Tragfähigkeit | hoch |
| Einschränkung | Bulk-Import muss explizit zählen; Fehler anfällig. |
8. Vier-Phasen-Rollout (Observe before Enforce)
| Prinzip | Phase 1 Cleanup → 2 Logging → 3 Frontend-Badges → 4 HTTP 403. |
| Begründung | Limits einführen ohne blind Nutzer zu blockieren; Daten für Limit-Kalibrierung. |
| Quelle | FEATURE_ENFORCEMENT.md |
| Tragfähigkeit | hoch |
| Einschränkung | Disziplin pro Feature; kein zentraler Feature-Flag pro Endpoint-Phase. |
9. Strukturiertes Feature-Logging
| Prinzip | Jeder Check: log_feature_usage(profile_id, feature_id, access, action) → JSON in feature-usage.log. |
| Begründung | Audit, Debugging, Kalibrierung — auch wenn noch nicht enforced. |
| Quelle | feature_logger.py |
| Tragfähigkeit | hoch |
| Einschränkung | Log-Pfad /app/logs container-spezifisch. |
10. Defense in Depth: API 403 + Frontend-Gate
| Prinzip | Backend blockiert autoritativ; Frontend zeigt UsageBadge, deaktiviert Buttons, Tooltip bei Limit. |
| Begründung | UX (frühes Feedback) + Sicherheit (API nicht umgehbar via curl). |
| Quelle | FEATURE_ENFORCEMENT.md; UsageBadge.jsx |
| Tragfähigkeit | hoch |
| Einschränkung | Frontend-Gate optional pro Seite; nicht generisch erzwungen. |
11. Nutzer-Usage-API ohne Code-Änderung bei neuen Features
| Prinzip | GET /features/usage iteriert alle aktiven features und ruft check_feature_access pro Zeile. |
| Begründung | Neues DB-Feature erscheint automatisch in Quota-Übersicht. |
| Quelle | routers/features.py → get_feature_usage() |
| Tragfähigkeit | hoch |
| Einschränkung | Frontend muss Feature-ID kennen, um Badge zu binden. |
12. Access Grants für temporäre Tier-Elevation
| Prinzip | Coupons/Admin erzeugen access_grants; effektiver Tier steigt zeitlich begrenzt. |
| Begründung | Promotions, Partner (Wellpass), Trials ohne permanente Tier-Änderung. |
| Quelle | access_grants; routers/coupons.py (Pause/Resume) |
| Tragfähigkeit | hoch |
| Einschränkung | Coupon-Stacking-Logik komplex; dokumentiert vs. Code prüfen bei Neuentwicklung. |
13. Entitlements als Querschnitt für UI-Module (Widgets)
| Prinzip | Dashboard-Widgets mappen auf features.id; Katalog liefert allowed pro Profil. |
| Begründung | Tier-Logik nicht in React-Widgets duplizieren (DASHBOARD_WIDGETS_AGENT_GUIDE §0). |
| Quelle | dashboard_widget_entitlements.py; ARCHITECTURE.md §9 |
| Tragfähigkeit | hoch |
| Einschränkung | Widget-Sichtbarkeit ≠ API-Schutz — Chart-Endpoints brauchen eigenes Gating (A4). |
14. Admin-konfigurierbare Tier × Feature Matrix
| Prinzip | tier_limits trennt Tier-Definition von Limits; Tiers ohne hardcodierte Spalten pro Feature. |
| Begründung | Neue Tiers/Preise ohne Code-Deploy der Limit-Logik. |
| Quelle | MEMBERSHIP_SYSTEM.md § Tier-System; tier_limits Tabelle |
| Tragfähigkeit | hoch |
| Einschränkung | Tier-Namen in Seed-Daten (free, premium, …) — erweiterbar, aber Konvention. |
15. NULL = unlimited, 0 = disabled
| Prinzip | Einheitliche Semantik für Limit-Werte in allen Schichten. |
| Begründung | Vermeidet Sonderfälle „-1 means unlimited“; klare Admin-UI. |
| Quelle | _check_impl() in auth.py |
| Tragfähigkeit | hoch |
| Einschränkung | SQL NULL vs. Python None — konsistent, aber in UI erklärungsbedürftig. |
Registrierte Features (Referenz)
| Feature ID | Typ | Reset | Typische Aktion |
|---|---|---|---|
weight_entries |
count | never | Gewicht anlegen |
circumference_entries |
count | never | Umfang anlegen |
caliper_entries |
count | never | Caliper anlegen |
activity_entries |
count | monthly | Training anlegen/import |
nutrition_entries |
count | monthly | Ernährung anlegen/import |
photos |
count | monthly | Foto hochladen |
ai_calls |
count | monthly | KI-Analyse |
ai_pipeline |
boolean | — | Pipeline-Analyse |
data_export |
count | monthly | Export/PDF |
data_import |
count | monthly | ZIP/Universal-Import |
Enforcement-Lücken (Ist): routers/prompts.py (/execute, /execute-stream) ohne check_feature_access — Legacy insights.py hat Enforcement für ai_calls/ai_pipeline.
Nicht übernehmen
-
Dokumentations-Drift —
MEMBERSHIP_SYSTEM.md(„Enforcement deaktiviert“) vs.FEATURE_ENFORCEMENT.md(Phase 4 komplett) vs. Ist-Code; bei Neuentwicklung einen Kanon festlegen. -
Unvollständige Tier-Auflösung — Doku beschreibt
tier_locked, Trial-in-Tier; Code nutzt primär Grants +profiles.tier. Trial (trial_ends_at) eher UI-Banner als Tier-Engine. -
Feature-IDs in Routern verstreut — kein zentraler Endpoint-Registry-Eintrag „welcher Router prüft welches Feature“.
-
Check und Increment nicht atomar — Race bei parallelen Requests möglich; kein DB-Level Locking.
-
Legacy Profil-Spalten parallel —
ai_enabled,ai_limit_day,export_enabledin Sessions-Query neben Feature-System. -
Frontend ohne Backend-Gate — reine UI-Deaktivierung ohne 403 ist unsicher (manche Seiten nur teilweise umgesetzt).
-
Boolean via limit_value 0/1 — funktioniert, aber für Familien-Architektur explizites
enabled-Flag oder Capability-Tokens erwägen. -
Unused Schema-Felder —
user_feature_restrictions.enablednicht in Auflösung eingebunden. -
App-lokales Abo ohne Zahlungsanbindung — Stripe/SSO nur Vision (
CENTRAL_SUBSCRIPTION_SYSTEM.md); nicht als fertiges Familien-Muster übernehmen. -
Profile als Entitlement-Subject — kein Org/Mandant; Multi-App-Familie braucht separates Identity/Subscription-Boundary.
-
Self-hosted Tier als Sonderfall —
selfhostedist Deploy-Modell, kein generisches SaaS-Tier-Muster. -
Increment-Schleifen bei Bulk —
for _ in range(new_entries): increment_feature_usage()— ineffizient; batch-Inkrement besser.
Modul-Inventar (Ist-Stand)
backend/
├── auth.py # get_effective_tier, check_feature_access, increment_feature_usage
├── feature_logger.py # JSON-Logging
├── dashboard_widget_entitlements.py # Widget allowed + Layout-Sanitisierung
├── widget_feature_requirements_db.py
└── routers/
├── subscription.py # /me, /usage, /limits (Nutzer)
├── features.py # Admin CRUD + /usage, /check-access
├── tiers_mgmt.py, tier_limits.py
├── coupons.py, access_grants.py
└── user_restrictions.py
frontend/src/components/
└── UsageBadge.jsx # Quota-Anzeige (Phase 3)
DB (v9c): features, tiers, tier_limits, user_feature_restrictions, user_feature_usage, coupons, coupon_redemptions, access_grants, user_activity_log
Verwandte Dokumentation
- Membership-Detail: MEMBERSHIP_SYSTEM.md
- Enforcement-Howto: FEATURE_ENFORCEMENT.md
- Vision Produktfamilie: CENTRAL_SUBSCRIPTION_SYSTEM.md
- Widget-Gating: DASHBOARD_WIDGETS_AGENT_GUIDE.md §0
- Prompt Engine (Enforcement-Lücke): PROMPT_ENGINE_DESIGN_PRINCIPLES.md
Geplante Folgedokumente (Serie)
| # | Modul | Status |
|---|---|---|
| 1 | Prompt Engine | ✅ |
| 2 | Data Layer | ✅ |
| 3 | Feature & Entitlement | ✅ dieses Dokument |
| 4 | Registry-/Plugin-Muster | ✅ |
| 5 | Auth & Session | ✅ |
| 6 | Universal Import | ✅ |
| 7 | Dashboard Widgets | ✅ |
| 8 | Navigation / IA | ✅ |
| 9 | Migration & Deploy | ✅ MIGRATION_DEPLOY_DESIGN_PRINCIPLES.md |