mitai-jinkendo/.claude/docs/jinkendo-foundation/design-principles/FEATURE_ENTITLEMENT_DESIGN_PRINCIPLES.md
Lars 532e17c4cd
All checks were successful
Deploy Development / deploy (push) Successful in 1m5s
Build Test / pytest-backend (push) Successful in 4s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 24s
feat: add Jinkendo Foundation design principles documentation
- 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.
2026-07-22 11:11:07 +02:00

16 KiB
Raw Blame History

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:

  1. Feature-Registry — Deklarative Liste aller limitierbaren Produktfunktionen mit Metadaten.
  2. Tier-Auflösung — Effektiver Tarif eines Profils (Basis-Tier + zeitliche Grants).
  3. Limit-Auflösung — Pro Feature: Override → Tier-Limit → Feature-Default.
  4. Usage-Tracking — Zähler für Count-Features mit optionalem Reset (daily/monthly/never).
  5. Enforcement — HTTP 403 bei Überschreitung; Frontend-Vorschaum via Badges.
  6. Beobachtbarkeit — Strukturiertes JSON-Logging aller Access-Checks.
  7. 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):

  1. Aktiver access_grants-Eintrag (is_active, valid_from/valid_until)
  2. Fallback: profiles.tier

Feature-Limit (check_feature_access_check_impl):

  1. user_feature_restrictions.limit_value (höchste Priorität)
  2. tier_limits für effektiven Tier
  3. features.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.pyget_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

  1. Dokumentations-DriftMEMBERSHIP_SYSTEM.md („Enforcement deaktiviert“) vs. FEATURE_ENFORCEMENT.md (Phase 4 komplett) vs. Ist-Code; bei Neuentwicklung einen Kanon festlegen.

  2. 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.

  3. Feature-IDs in Routern verstreut — kein zentraler Endpoint-Registry-Eintrag „welcher Router prüft welches Feature“.

  4. Check und Increment nicht atomar — Race bei parallelen Requests möglich; kein DB-Level Locking.

  5. Legacy Profil-Spalten parallelai_enabled, ai_limit_day, export_enabled in Sessions-Query neben Feature-System.

  6. Frontend ohne Backend-Gate — reine UI-Deaktivierung ohne 403 ist unsicher (manche Seiten nur teilweise umgesetzt).

  7. Boolean via limit_value 0/1 — funktioniert, aber für Familien-Architektur explizites enabled-Flag oder Capability-Tokens erwägen.

  8. Unused Schema-Felderuser_feature_restrictions.enabled nicht in Auflösung eingebunden.

  9. App-lokales Abo ohne Zahlungsanbindung — Stripe/SSO nur Vision (CENTRAL_SUBSCRIPTION_SYSTEM.md); nicht als fertiges Familien-Muster übernehmen.

  10. Profile als Entitlement-Subject — kein Org/Mandant; Multi-App-Familie braucht separates Identity/Subscription-Boundary.

  11. Self-hosted Tier als Sonderfallselfhosted ist Deploy-Modell, kein generisches SaaS-Tier-Muster.

  12. Increment-Schleifen bei Bulkfor _ 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


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