All checks were successful
Deploy Development / deploy (push) Successful in 44s
Test Suite / pytest-backend (push) Successful in 42s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 13s
Test Suite / k6 /health Baseline (push) Successful in 35s
Test Suite / playwright-tests (push) Successful in 1m51s
- Updated the capability catalog to reflect a registry-first approach, requiring modules to register rights and quotas upon implementation. - Enhanced the backend to synchronize the rights registry with the database, ensuring only registered capabilities and features are displayed in the admin matrix. - Modified SQL queries in the admin rights router to filter capabilities and features based on module registration. - Updated documentation to clarify the new rights and features registry process, replacing the previous catalog-first method. - Incremented application version to 0.8.201 and updated database schema version to 20260606084 to reflect these changes.
332 lines
16 KiB
Markdown
332 lines
16 KiB
Markdown
# Capability-Katalog Shinkan v1
|
||
|
||
**Status:** Konzept (verbindliche Zieldefinition; M3 teilweise umgesetzt)
|
||
**Stand:** 2026-06-06
|
||
**Bezüge:** `ACCESS_LAYER_AND_GOVERNANCE_PLAN.md` (Stufe E), `MULTI_TENANCY_RBAC_ARCHITECTURE.md`, `CLUB_MEMBERSHIP_AND_FEATURES.v1.md`, **`MEMBERSHIP_RBAC_DECISIONS_2026-06.md`** (Produktentscheidungen)
|
||
|
||
---
|
||
|
||
## 1. Zweck
|
||
|
||
Dieses Dokument definiert **benannte Capabilities** (Wer darf welche **Funktion** ausführen?) — getrennt von:
|
||
|
||
- **Governance** (Darf ich *dieses Objekt* lesen/ändern? → `visibility`, `club_id`, `created_by`)
|
||
- **Feature-Limits** (Wie viel darf der **Verein**? → `CLUB_MEMBERSHIP_AND_FEATURES.v1.md`)
|
||
|
||
Capabilities beantworten: *„Darf ein Trainer mit Rolle X die Funktion Y im Verein Z überhaupt nutzen?“*
|
||
|
||
---
|
||
|
||
## 2. Namenskonvention
|
||
|
||
```
|
||
{domain}.{action}[.{qualifier}]
|
||
```
|
||
|
||
| Segment | Beispiele |
|
||
|---------|-----------|
|
||
| `domain` | `exercises`, `media`, `planning`, `org`, `platform` |
|
||
| `action` | `read`, `create`, `update`, `delete`, `manage`, `execute` |
|
||
| `qualifier` | `ai.suggest`, `join_request`, `inbox.review` |
|
||
|
||
**CRUD-Mapping:**
|
||
|
||
| Aktion | Capability-Suffix | Bedeutung |
|
||
|--------|-------------------|-----------|
|
||
| Lesen (Listen/Detail) | `.read` | Navigation + API-Lesen erlaubt |
|
||
| Anlegen | `.create` | POST/INSERT |
|
||
| Bearbeiten | `.update` | PUT/PATCH (eigenes + berechtigtes Fremdes) |
|
||
| Löschen | `.delete` | DELETE (strenger als update) |
|
||
| Verwalten | `.manage` | Org-Funktionen, Freigaben, Mitglieder |
|
||
| Ausführen (ohne Persistenz) | `.execute` | z. B. KI-Vorschau, Coach-Lauf |
|
||
|
||
Objektbezogene Feinheiten (nur Ersteller, nur Vereinsadmin des Objekt-Vereins) bleiben in **Governance** — Capabilities sind das **Tür-Schloss** davor.
|
||
|
||
---
|
||
|
||
## 3. Account-Lifecycle (Voraussetzung für Capabilities)
|
||
|
||
| `account_state` | Bedingung | Typische Capabilities |
|
||
|-----------------|-----------|------------------------|
|
||
| `anonymous` | Keine Session | nur öffentliche Routen (`/login`, Rechtstexte, `clubs/public-directory`) |
|
||
| `unverified` | Session, `email_verified=false` | `account.resend_verification`, `account.logout` |
|
||
| `verified_pending_club` | Verifiziert, keine aktive `club_members` | `club.join_request`, `club.creation_request` (M7), `account.settings` — **kein** Lesezugriff auf Domänen-Inhalte (siehe Entscheidungs-Doc §1.1) |
|
||
| `active_member` | Mind. eine aktive Vereinsmitgliedschaft | Domänen-Capabilities gemäß Vereinsrolle |
|
||
| `platform_admin` | `role` ∈ `admin`, `superadmin` | `platform.*` zusätzlich |
|
||
|
||
**Regel:** Domänen-Capabilities (`exercises.*`, `planning.*`, …) erfordern mindestens `active_member`, sofern nicht `platform_admin`.
|
||
|
||
---
|
||
|
||
## 4. Rollen-Scopes
|
||
|
||
### 4.1 Portal-Rollen (`profiles.role`)
|
||
|
||
| Rolle | Scope | Kurz |
|
||
|-------|-------|------|
|
||
| `user` | Portal | Standard nach Registrierung (Zielbild; heute oft `trainer` Legacy) |
|
||
| `trainer` | Portal | Legacy — mittelfristig durch `user` + Vereinsrollen ersetzen |
|
||
| `admin` | Portal | Plattform-Admin (Vereine anlegen, erweiterte Ops) |
|
||
| `superadmin` | Portal | Vollzugriff Plattform + Superadmin-Werkzeuge |
|
||
|
||
### 4.2 Vereinsrollen (`club_member_roles.role_code`)
|
||
|
||
| Rolle | Fachlich |
|
||
|-------|----------|
|
||
| `club_admin` | Vereinsorganisation, Mitglieder, Struktur |
|
||
| `trainer` | Planung, Übungen, Durchführung |
|
||
| `content_editor` | Inhalte pflegen (Bibliothek) |
|
||
| `division_lead` | Spartenleitung (später division-scope) |
|
||
|
||
Mehrfachrollen pro Mitgliedschaft sind möglich (OR-Verknüpfung der Capabilities).
|
||
|
||
### 4.3 Mapping heutiger Helfer → Capabilities
|
||
|
||
| Heutiger Code (`club_tenancy.py`) | Ziel-Capability-Cluster |
|
||
|-----------------------------------|-------------------------|
|
||
| `can_manage_club_org` | `org.structure.manage`, `org.members.manage`, `org.inbox.review` |
|
||
| `can_plan_in_club` | `planning.*`, `exercises.create/update`, `modules.*`, `framework.*` |
|
||
| `is_platform_admin` | `platform.*` (Bypass Mandant, Audit-Pflicht) |
|
||
| `is_superadmin` | `platform.superadmin.*` |
|
||
|
||
---
|
||
|
||
## 5. Capability-Katalog (v1)
|
||
|
||
Legende Spalten:
|
||
|
||
- **Min. Account:** `verified_pending_club` | `active_member` | `platform_admin`
|
||
- **Vereinsrollen:** leer = alle aktiven Mitglieder; sonst mindestens eine Rolle
|
||
- **Feature-ID:** optionales Kontingent (siehe Club-Membership-Doc); leer = kein Limit
|
||
- **Governance:** zusätzliche Objektprüfung ja/nein
|
||
|
||
### 5.1 Account & Onboarding
|
||
|
||
| Capability-ID | Min. Account | Vereinsrollen | Feature-ID | Endpoints / UI |
|
||
|---------------|--------------|---------------|------------|----------------|
|
||
| `account.settings.read` | `unverified` | — | — | `GET /profiles/me`, Einstellungen |
|
||
| `account.settings.update` | `unverified` | — | — | `PUT /profiles/{id}` (eigenes Profil) |
|
||
| `account.password.change` | `unverified` | — | — | `PUT /api/auth/pin` |
|
||
| `account.resend_verification` | `unverified` | — | — | `POST /api/auth/resend-verification` |
|
||
| `club.directory.read` | `verified_pending_club` | — | — | `GET /clubs/public-directory` |
|
||
| `club.join_request.create` | `verified_pending_club` | — | — | `POST /me/club-join-requests`, Registrierung mit `requested_club_id` |
|
||
| `club.join_request.withdraw` | `verified_pending_club` | — | — | `DELETE /me/club-join-requests/{id}` |
|
||
| `club.join_request.read_own` | `verified_pending_club` | — | — | `GET /me/club-join-requests` |
|
||
|
||
### 5.2 Organisation (Verein)
|
||
|
||
| Capability-ID | Min. Account | Vereinsrollen | Feature-ID | Endpoints / UI |
|
||
|---------------|--------------|---------------|------------|----------------|
|
||
| `org.club.read` | `active_member` | * | — | `GET /clubs`, `GET /clubs/{id}` (eigene Vereine) |
|
||
| `org.club.create` | `platform_admin` | — | — | `POST /clubs` |
|
||
| `org.club.update` | `platform_admin` | `club_admin` | — | `PUT /clubs/{id}` |
|
||
| `org.club.delete` | `platform_admin` | — | — | `DELETE /clubs/{id}` |
|
||
| `org.structure.manage` | `active_member` | `club_admin` | `training_groups` | Sparten, Gruppen CRUD |
|
||
| `org.members.read` | `active_member` | `club_admin` | — | `GET /clubs/{id}/members` |
|
||
| `org.members.manage` | `active_member` | `club_admin` | `active_members` | POST/PUT/DELETE Mitglieder |
|
||
| `org.members.directory` | `active_member` | * | — | `GET /clubs/{id}/members/directory` (ohne E-Mail für Nicht-Admins) |
|
||
| `org.join_request.review` | `active_member` | `club_admin` | — | Join-Request accept/reject, Inbox |
|
||
| `org.inbox.read` | `active_member` | `club_admin` | — | Posteingang Join + Content-Reports |
|
||
|
||
### 5.3 Übungen
|
||
|
||
| Capability-ID | Min. Account | Vereinsrollen | Feature-ID | Governance |
|
||
|---------------|--------------|---------------|------------|------------|
|
||
| `exercises.read` | `active_member` | * | — | ja (visibility) |
|
||
| `exercises.create` | `active_member` | `trainer`, `content_editor`, `club_admin`, `division_lead` | `exercises` | — |
|
||
| `exercises.update` | `active_member` | `trainer`, `content_editor`, `club_admin`, `division_lead` | — | ja |
|
||
| `exercises.delete` | `active_member` | `club_admin` (+ Ersteller privat) | — | ja |
|
||
| `exercises.bulk_metadata` | `active_member` | `content_editor`, `club_admin` | — | ja |
|
||
| `exercises.ai.suggest` | `active_member` | `trainer`, `content_editor`, `club_admin` | `ai_calls` | — |
|
||
| `exercises.ai.regenerate` | `active_member` | `trainer`, `content_editor`, `club_admin` | `ai_calls` | ja (edit) |
|
||
| `exercises.media.read` | `active_member` | * | — | ja |
|
||
| `exercises.media.upload` | `active_member` | `trainer`, `content_editor`, `club_admin` | `exercise_media` | ja |
|
||
| `exercises.variants.manage` | `active_member` | `trainer`, `content_editor`, `club_admin` | — | ja |
|
||
|
||
**Representative Endpoints:** `/api/exercises*`, `/api/exercises/ai/*`, Medien-Datei-Download.
|
||
|
||
### 5.4 Medien-Bibliothek (Archiv)
|
||
|
||
| Capability-ID | Min. Account | Vereinsrollen | Feature-ID | Governance |
|
||
|---------------|--------------|---------------|------------|------------|
|
||
| `media.library.read` | `active_member` | * | — | ja |
|
||
| `media.library.upload` | `active_member` | `trainer`, `content_editor`, `club_admin` | `exercise_media` | ja |
|
||
| `media.library.update` | `active_member` | `trainer`, `content_editor`, `club_admin` | — | ja |
|
||
| `media.library.lifecycle` | `active_member` | `trainer`, `club_admin` | — | ja |
|
||
| `media.rights.declare` | `active_member` | `trainer`, `club_admin` | — | ja |
|
||
| `media.admin.rights_review` | `platform_admin` | — | — | Plattform-Admin Legacy-Review |
|
||
|
||
### 5.5 Trainingsmodule & Rahmenprogramme
|
||
|
||
| Capability-ID | Min. Account | Vereinsrollen | Feature-ID | Governance |
|
||
|---------------|--------------|---------------|------------|------------|
|
||
| `modules.read` | `active_member` | * | — | ja |
|
||
| `modules.create` | `active_member` | `trainer`, `content_editor`, `club_admin` | `training_programs` | — |
|
||
| `modules.update` | `active_member` | `trainer`, `content_editor`, `club_admin` | — | ja |
|
||
| `modules.delete` | `active_member` | `club_admin` (+ Ersteller) | — | ja |
|
||
| `framework.read` | `active_member` | * | — | ja |
|
||
| `framework.create` | `active_member` | `trainer`, `club_admin` | `training_programs` | — |
|
||
| `framework.update` | `active_member` | `trainer`, `club_admin` | — | ja |
|
||
| `framework.delete` | `active_member` | `club_admin` (+ Ersteller) | — | ja |
|
||
| `plan_templates.read` | `active_member` | * | — | ja |
|
||
| `plan_templates.manage` | `active_member` | `trainer`, `club_admin` | — | ja |
|
||
|
||
### 5.6 Progressionspfade
|
||
|
||
| Capability-ID | Min. Account | Vereinsrollen | Feature-ID | Governance |
|
||
|---------------|--------------|---------------|------------|------------|
|
||
| `progression.read` | `active_member` | * | — | ja |
|
||
| `progression.manage` | `active_member` | `trainer`, `content_editor`, `club_admin` | — | ja |
|
||
|
||
### 5.7 Planung & Durchführung
|
||
|
||
| Capability-ID | Min. Account | Vereinsrollen | Feature-ID | Governance |
|
||
|---------------|--------------|---------------|------------|------------|
|
||
| `planning.calendar.read` | `active_member` | * | — | ja (Gruppe/Verein) |
|
||
| `planning.units.create` | `active_member` | `trainer`, `club_admin`, `division_lead` | `training_units` | ja |
|
||
| `planning.units.update` | `active_member` | `trainer`, `club_admin`, `division_lead` | — | ja |
|
||
| `planning.units.delete` | `active_member` | `club_admin`, `trainer` (eigene) | — | ja |
|
||
| `planning.units.run` | `active_member` | `trainer`, `club_admin`, `division_lead` | — | ja |
|
||
| `planning.coach.execute` | `active_member` | `trainer`, `club_admin` | — | ja |
|
||
| `planning.ai.suggest` | `active_member` | `trainer`, `club_admin` | `ai_calls` | — |
|
||
| `planning.ai.progression_path` | `active_member` | `trainer`, `club_admin` | `ai_calls` | — |
|
||
|
||
### 5.8 Fähigkeiten & Scoring
|
||
|
||
| Capability-ID | Min. Account | Vereinsrollen | Feature-ID | Governance |
|
||
|---------------|--------------|---------------|------------|------------|
|
||
| `skills.catalog.read` | `active_member` | * | — | globaler Katalog |
|
||
| `skills.discovery.read` | `active_member` | `trainer`, `content_editor` | — | — |
|
||
| `skill_profiles.read` | `active_member` | * | — | ja (Artefakt) |
|
||
|
||
### 5.9 Governance & Meldungen
|
||
|
||
| Capability-ID | Min. Account | Vereinsrollen | Feature-ID |
|
||
|---------------|--------------|---------------|------------|
|
||
| `governance.content_report.create` | `active_member` | * | — |
|
||
| `governance.content_report.review` | `active_member` | `club_admin` | — |
|
||
| `governance.change_request.*` | `active_member` | `content_editor`, `club_admin` | — |
|
||
|
||
### 5.10 Plattform (nur Portal-Admin / Superadmin)
|
||
|
||
| Capability-ID | Min. Account | Portal-Rolle | Feature-ID |
|
||
|---------------|--------------|--------------|------------|
|
||
| `platform.admin.access` | `platform_admin` | `admin`, `superadmin` | — |
|
||
| `platform.users.manage` | `platform_admin` | `superadmin` | — |
|
||
| `platform.catalogs.manage` | `platform_admin` | `superadmin` | — |
|
||
| `platform.maturity_models.manage` | `platform_admin` | `superadmin` | — |
|
||
| `platform.wiki_import.execute` | `platform_admin` | `superadmin` | `wiki_import` |
|
||
| `platform.ai_prompts.manage` | `platform_admin` | `superadmin` | — |
|
||
| `platform.exercise_enrichment.execute` | `platform_admin` | `superadmin` | `ai_calls` |
|
||
| `platform.user_content.moderate` | `platform_admin` | `superadmin` | — |
|
||
| `platform.legal_documents.manage` | `platform_admin` | `superadmin` | — |
|
||
| `platform.media_storage.manage` | `platform_admin` | `superadmin` | — |
|
||
| `platform.club_creation.approve` | `platform_admin` | `superadmin` | — |
|
||
|
||
*Geplant:* `club.creation_request.submit` → `verified_pending_club`; Freigabe über `platform.club_creation.approve`.
|
||
|
||
---
|
||
|
||
## 6. Standard-Zuordnung Vereinsrolle → Capabilities (v1, fest)
|
||
|
||
Diese Tabelle ist die **initiale** Grant-Matrix (`club_role_capability_grants`). Später durch Custom Roles ersetzbar — gleiche Capability-IDs.
|
||
|
||
| Capability-Cluster | `club_admin` | `trainer` | `content_editor` | `division_lead` |
|
||
|--------------------|:------------:|:---------:|:----------------:|:---------------:|
|
||
| `org.structure.manage` | ✓ | — | — | ✓ (eigene Sparte, später) |
|
||
| `org.members.manage` | ✓ | — | — | — |
|
||
| `org.join_request.review` | ✓ | — | — | — |
|
||
| `exercises.read` | ✓ | ✓ | ✓ | ✓ |
|
||
| `exercises.create/update` | ✓ | ✓ | ✓ | ✓ |
|
||
| `exercises.delete` | ✓ | — | — | — |
|
||
| `exercises.ai.*` | ✓ | ✓ | ✓ | ✓ |
|
||
| `media.library.*` | ✓ | ✓ | ✓ | ✓ |
|
||
| `modules.*` / `framework.*` | ✓ | ✓ | ✓ | ✓ |
|
||
| `planning.*` | ✓ | ✓ | — | ✓ |
|
||
| `planning.coach.execute` | ✓ | ✓ | — | ✓ |
|
||
| `governance.content_report.review` | ✓ | — | — | — |
|
||
|
||
---
|
||
|
||
## 7. API-Vertrag (Ziel)
|
||
|
||
### 7.1 Effektive Rechte für Frontend
|
||
|
||
```
|
||
GET /api/me/entitlements?club_id={optional}
|
||
```
|
||
|
||
Antwort (Ausschnitt):
|
||
|
||
```json
|
||
{
|
||
"account_state": "active_member",
|
||
"portal_role": "user",
|
||
"club_id": 12,
|
||
"club_roles": ["trainer"],
|
||
"capabilities": {
|
||
"exercises.read": true,
|
||
"exercises.ai.suggest": true,
|
||
"org.members.manage": false
|
||
},
|
||
"features": {
|
||
"ai_calls": { "allowed": true, "used": 4, "limit": 50, "remaining": 46, "reset_at": "2026-07-01T00:00:00Z" }
|
||
}
|
||
}
|
||
```
|
||
|
||
Frontend: Navigation und Buttons nur aus dieser Antwort — **keine** duplizierten Rollen-Checks in JSX (Ausnahme: rein kosmetische Labels).
|
||
|
||
### 7.2 Backend-Enforcement
|
||
|
||
Zentral (Zielmodul `authorization/capabilities.py` oder Erweiterung `club_tenancy.py`):
|
||
|
||
```python
|
||
assert_capability(tenant, "exercises.ai.suggest", club_id=tenant.effective_club_id)
|
||
assert_club_feature(tenant, "ai_calls", club_id=tenant.effective_club_id) # siehe Club-Membership-Doc
|
||
# + bestehende Governance auf Objekt-Ebene
|
||
```
|
||
|
||
---
|
||
|
||
## 8. Implementierungsreihenfolge (Capabilities)
|
||
|
||
| Phase | Inhalt |
|
||
|-------|--------|
|
||
| C0 | Account-Gates (`unverified`, `verified_pending_club`) — ohne Capability-DB |
|
||
| C1 | `capabilities` + `club_role_capability_grants` seed aus §5–6 |
|
||
| C2 | `GET /api/me/entitlements` + Frontend-Nav |
|
||
| C3 | Enforcement: KI-Endpoints, `exercises.create`, `planning.*` |
|
||
| C4 | Restliche Router schrittweise; Audit in `ACCESS_LAYER_ENDPOINT_AUDIT.md` |
|
||
| C5 | Custom Roles (optional) — gleiche IDs |
|
||
|
||
---
|
||
|
||
## 9. Abgrenzung & Drift-Schutz
|
||
|
||
1. **Neue Nutzerfunktion** → `register_capability()` in `rights_registrations/<modul>.py`, dann Endpoint mit `probe_capability`. Namenskonvention hier dokumentieren — **kein** Bulk-Seed in Migrationen.
|
||
2. **Kontingent** → `register_feature()` im selben Modul; Consume über `consume_club_feature_with_usage`.
|
||
3. **Kein** paralleles `if (user.role === 'trainer')` für Sicherheit — nur UX-Fallback.
|
||
4. Capability ≠ Feature: `exercises.ai.suggest` (darf ich?) vs. `ai_calls` (wie viel übrig?).
|
||
5. Plattform-Admin-Bypass dokumentieren und auditieren (`platform_admin` sieht Mandant, nicht automatisch alle Quotas).
|
||
|
||
Siehe **`docs/working/RIGHTS_AND_FEATURES_REGISTRY.md`** (Registry-first, ersetzt Katalog-first aus 079).
|
||
|
||
---
|
||
|
||
## 10. Referenzen
|
||
|
||
| Dokument | Inhalt |
|
||
|----------|--------|
|
||
| `CLUB_MEMBERSHIP_AND_FEATURES.v1.md` | Vereinsabo, Feature-Registry, Kontingente |
|
||
| `ACCESS_LAYER_AND_GOVERNANCE_PLAN.md` | TenantContext, Governance, Stufe E |
|
||
| `MULTI_TENANCY_RBAC_ARCHITECTURE.md` | §4.6 Vereinsabo-Zielbild |
|
||
| `ACCESS_LAYER_ENDPOINT_AUDIT.md` | Endpoint-Pflege |
|
||
| Mitai `FEATURE_ENFORCEMENT.md` | 4-Phasen-Rollout-Vorbild |
|
||
|
||
---
|
||
|
||
**Changelog**
|
||
|
||
- 2026-06-06: v1 — Initial-Katalog aus Ist-Code (`club_tenancy`, Router-Inventar) + Ziel-Onboarding.
|