371 lines
16 KiB
Markdown
371 lines
16 KiB
Markdown
|
|
# 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](./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.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
|
|||
|
|
|
|||
|
|
1. **Dokumentations-Drift** — `MEMBERSHIP_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 parallel** — `ai_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-Felder** — `user_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 Sonderfall** — `selfhosted` ist Deploy-Modell, kein generisches SaaS-Tier-Muster.
|
|||
|
|
|
|||
|
|
12. **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](../../technical/MEMBERSHIP_SYSTEM.md)
|
|||
|
|
- Enforcement-Howto: [FEATURE_ENFORCEMENT.md](../../architecture/FEATURE_ENFORCEMENT.md)
|
|||
|
|
- Vision Produktfamilie: [CENTRAL_SUBSCRIPTION_SYSTEM.md](../../technical/CENTRAL_SUBSCRIPTION_SYSTEM.md)
|
|||
|
|
- Widget-Gating: [DASHBOARD_WIDGETS_AGENT_GUIDE.md](../../technical/DASHBOARD_WIDGETS_AGENT_GUIDE.md) §0
|
|||
|
|
- Prompt Engine (Enforcement-Lücke): [PROMPT_ENGINE_DESIGN_PRINCIPLES.md](./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` |
|