Ap03 #4

Merged
Lars merged 6 commits from develop into main 2026-07-04 23:04:11 +02:00
2 changed files with 246 additions and 213 deletions
Showing only changes of commit 39e8084b1a - Show all commits

View File

@ -1,213 +0,0 @@
# AP0.3 Abschlussbericht Capability / Rights Registry & Entitlements Snapshot
**Status:** abgeschlossen
**Stand:** 2026-07-04
**Branch:** `develop`
---
## 1. Umgesetzte Dateien
| Datei | Zweck |
|-------|--------|
| `backend/migrations/004_capabilities_registry.sql` | Tabellen `capabilities`, `role_capability_grants` |
| `backend/rights_registry.py` | In-Memory-Registry, Validierung, DB-Sync, Grant-Lookup |
| `backend/rights_registrations/__init__.py` | Side-Effect-Import aller Modul-Registrierungen |
| `backend/rights_registrations/platform.py` | Platform-Capabilities |
| `backend/rights_registrations/tenant_ops.py` | Tenant-/Actor-Capabilities |
| `backend/capabilities.py` | Auflösung, `check_capability`, `require_capability` |
| `backend/entitlements.py` | Entitlements-Snapshot-Builder |
| `backend/sync_rights_registry.py` | CLI-Sync beim Container-Start |
| `backend/tenant_context.py` | `TenantContext.capabilities` |
| `backend/routers/me.py` | `/entitlements`, `/admin/demo` |
| `backend/entrypoint.sh` | Rights-Sync nach Seeds |
| `backend/version.py` | `0.3.0-ap0.3`, Schema `004` |
| `backend/tests/test_rights_registry.py` | Registry + Sync |
| `backend/tests/test_capabilities.py` | Grants, enforce/probe, Demo-Endpoint |
| `backend/tests/test_entitlements.py` | Snapshot-Form |
| `backend/tests/conftest.py` | Registry-Sync in Test-Session |
| `README.md` | API-Doku AP0.3 |
---
## 2. Neue Migrationen
**`004_capabilities_registry.sql`**
- **`capabilities`** — `capability_key`, `module`, `description`, `is_active`
- **`role_capability_grants`** — `role_scope` (`portal` \| `tenant`), `role_code`, `capability_key`
Kein Feature-/Limit-Schema in AP0.3 (bewusst AP0.4-Vorbereitung).
---
## 3. Registry-Struktur
```
backend/
├── rights_registry.py # register_capability(), sync_rights_registry_to_db()
├── rights_registrations/
│ ├── __init__.py # import platform, tenant_ops
│ ├── platform.py # admin, context, entitlements
│ └── tenant_ops.py # tenant.manage, actor.manage
└── sync_rights_registry.py # Startup nach Migrationen/Seeds
```
**Registrierungsmodell:** `@dataclass(frozen=True) CapabilityRegistration` mit `key`, `module`, `description`, `default_grants: (role_scope, role_code)`.
**Startup:** `entrypoint.sh``python sync_rights_registry.py` (überspringbar via `SKIP_RIGHTS_SYNC=1`).
---
## 4. Endpoints
| Endpoint | Methode | Auth / Gate | Neu/Geändert |
|----------|---------|-------------|--------------|
| `/api/me/context` | GET | Session | **Geändert** — enthält `capabilities[]` |
| `/api/me/entitlements` | GET | Session | **Neu** |
| `/api/me/admin/demo` | GET | Session + `kairo.admin.access` | **Neu** (Beispiel `require_capability`) |
Bestehende Auth-/Me-Endpunkte unverändert in Signatur.
---
## 5. Capability-Auflösungslogik
```
Session (portal_role, active_tenant_id)
→ tenant_membership → tenant_role (optional)
→ load_grants_for_roles(portal_role, tenant_role)
SELECT capability_key FROM role_capability_grants
JOIN capabilities WHERE role_scope/role_code match
→ Union Portal-Grants + Tenant-Grants
→ TenantContext.capabilities (frozenset)
```
**`require_capability(key)`:** prüft `key in ctx.capabilities`.
| Modus | Env | Verhalten |
|-------|-----|-----------|
| probe | `CAPABILITY_ENFORCE=probe` (Default) | Zugriff erlaubt, Audit `capability.denied` |
| enforce | `CAPABILITY_ENFORCE=enforce` | HTTP 403 bei fehlendem Grant |
---
## 6. Initiale Capabilities & Default-Grants
| Capability | Portal admin | Portal user | Tenant owner | Tenant admin | Tenant member |
|------------|:------------:|:-----------:|:------------:|:------------:|:-------------:|
| `kairo.admin.access` | ✓ | | | | |
| `kairo.tenant.manage` | ✓ | | ✓ | ✓ | |
| `kairo.actor.manage` | ✓ | | ✓ | ✓ | |
| `kairo.context.read` | ✓ | ✓ | ✓ | ✓ | ✓ |
| `kairo.entitlements.read` | ✓ | ✓ | ✓ | ✓ | ✓ |
---
## 7. Tests und Testergebnis
```bash
docker compose -f docker-compose.dev-env.yml exec backend pip install -r requirements-dev.txt
docker compose -f docker-compose.dev-env.yml exec backend python -m pytest tests -ra -vv
```
| Testdatei | Abdeckung |
|-----------|-----------|
| `test_rights_registry.py` | 5 Capabilities registriert, Sync idempotent, DB-Zeilen |
| `test_capabilities.py` | Admin erlaubt, Member verweigert (enforce), Owner-Grants, probe-Modus |
| `test_entitlements.py` | Snapshot account/tenant/actor/roles/capabilities/enforcement |
| `test_migrations.py` | Migration 004 erkannt |
*(Lokale Ausführung in dieser Session über CI/Dev-Container nach Push.)*
---
## 8. Übernommene Muster aus Shinkan
| Muster | Kairo-Umsetzung |
|--------|-----------------|
| Registry-first | `rights_registry.py` + `rights_registrations/` |
| `register_capability()` mit Validierung | Pflichtfelder `key`, `module`, `description` |
| Frozen Dataclass-Definitionen | `CapabilityRegistration` |
| Startup-Sync Registry → DB | `sync_rights_registry_to_db()` |
| Modul-Ownership (`module`-Feld) | `platform`, `tenant` |
| Default Grants in Code | `default_grants` pro Capability |
| `require_capability` Dependency | `capabilities.py` |
| `/api/me/entitlements` Snapshot | `entitlements.py` |
| Probe vs. Enforce | `CAPABILITY_ENFORCE` |
**Nicht übernommen:** `club_id`, Vereinsrollen, Übungs-/Trainings-Capabilities, Club-Feature-Kontingente, `club_quota_bypass`.
---
## 9. Übernommene Muster aus Mitai
| Muster | Kairo-Umsetzung |
|--------|-----------------|
| Entitlements als zentrale Auflösungsschicht | `build_entitlements_snapshot()` |
| Probe-vs-Enforce-Denken | Default `probe`, optional `enforce` |
| Feature-Registry-Idee vorbereitet | `features: {}` im Snapshot, Enforcement `probe` |
**Nicht übernommen:** Tier/Subscription, Usage-Zähler, `check_feature_access`-Legacy, Account-Tier-Limits.
---
## 10. Bewusst nicht übernommen
- Shinkan-/Mitai-Domänenbegriffe (`club`, `profile`, Tier)
- Feature-Limits, Billing, Coupons, Usage-Zähler
- Prompt Registry, Vorhaben-/Projektlogik
- MCP, produktive Admin-UI
- Capabilities nur in SQL-Migration pflegen
- Governance/Object-ACL (AP später)
---
## 11. Abweichungen von Designprinzipien
| Thema | Abweichung | Begründung |
|-------|------------|------------|
| Entitlements-Struktur | flache + verschachtelte Blöcke | Kairo Hybrid: Account + Tenant laut Family Model |
| Feature-Registry | leeres Objekt | AP0.4-Scope |
| Admin-Grant-Overrides in DB | Sync fügt nur hinzu (`ON CONFLICT DO NOTHING`) | Sprint-0-Minimal; kein Admin-UI für Overrides |
| `linked_feature_id` | nicht modelliert | Keine Feature-Limits in AP0.3 |
**Eingehalten:** Auth / Capability / Feature getrennt; Prüfung zentral; Portal- vs. Tenant-Rolle getrennt; TenantContext als Auflösungsschicht.
---
## 12. Offene Entscheidungen
1. **Prod `CAPABILITY_ENFORCE`** — Default `probe`; wann auf `enforce` umstellen?
2. **Grant-Overrides** — Admin bearbeitet Grants in DB vs. Re-Sync aus Code
3. **Prod-pytest-Cleanup** für `*@example.com` (aus AP0.2)
4. **Feature-Registry** — Modell und Sync in AP0.4
5. **Frontend** — Entitlements-gestütztes UI-Gating statt Debug-JSON
---
## 13. Empfehlung für AP0.4
Laut Foundation-Dokument **AP0.4 Prompt, Feature, Config Registry**:
- Feature Registry (Metadaten, ohne Limits in Sprint 0)
- PromptTemplate / PromptVersion / Placeholder
- ConfigurationEntry
- Einfaches Prompt-Rendering mit Placeholder-Validation
- `features`-Block in Entitlements mit Registry-Sync (ohne Billing)
Optional vor AP0.4: Prod-Cleanup-Seed für pytest-Artefakte; Frontend zeigt `/api/me/entitlements`.
---
## Referenzen
- `docs/sprints/Jinkendo_Kairo_04_Sprint0_Foundation_v0.3.md` § AP0.3, §9 Entitlements
- `docs/reference/design-principles/shinkan/RIGHTS_REGISTRY_DESIGN_PRINCIPLES.md`
- `docs/reference/design-principles/shinkan/CAPABILITY_ENTITLEMENT_DESIGN_PRINCIPLES.md`
- `docs/reference/design-principles/alignment/FAMILY_ENTITLEMENT_MODEL.md`
- Vorgänger: `docs/sprints/Sprint0_AP0_2_Completion_Report_v0.2.md`
---
*Abgeschlossen im Rahmen Sprint 0 AP0.3.*

View File

@ -0,0 +1,246 @@
# AP0.3 Abschlussbericht Capability / Rights Registry & Entitlements Snapshot
**Status:** abgeschlossen
**Stand:** 2026-07-04 (final)
**Branch:** `develop` · Dev-Deploy und Test Suite grün · Prod stabil (Stand Nutzer)
---
## 1. Scope und Einordnung
AP0.3 liefert die **minimale Capability-/Rights-Grundlage** und den **Entitlements-Snapshot** für Sprint 0. Auth, TenantContext und Sessions stammen aus AP0.2; AP0.3 ergänzt Registry, DB-Sync, zentrale Capability-Prüfung und `/api/me/entitlements`.
| Anforderung (AP0.3) | Status |
|---------------------|--------|
| Migration Capabilities + Role-Grants | ✓ |
| Runtime Registry + Modul-Registrierungen | ✓ |
| Startup-Sync Registry → DB | ✓ |
| TenantContext.capabilities | ✓ |
| `require_capability()` Dependency | ✓ |
| `GET /api/me/entitlements` | ✓ |
| Beispiel-Endpoint mit Capability-Gate | ✓ |
| Tests (Registry, Sync, Auflösung, Enforce/Probe) | ✓ |
| Trennung Auth / Capability / Feature | ✓ |
**Bewusst nicht in AP0.3:** Feature-Limits, Billing, Usage-Zähler, Prompt Registry, produktive Admin-UI, Governance/Object-ACL.
---
## 2. Umgesetzte Dateien
| Datei | Zweck |
|-------|--------|
| `backend/migrations/004_capabilities_registry.sql` | Tabellen `capabilities`, `role_capability_grants` |
| `backend/rights_registry.py` | In-Memory-Registry, Validierung, DB-Sync, Grant-Lookup |
| `backend/rights_registrations/__init__.py` | Side-Effect-Import aller Modul-Registrierungen |
| `backend/rights_registrations/platform.py` | Platform-Capabilities |
| `backend/rights_registrations/tenant_ops.py` | Tenant-/Actor-Capabilities |
| `backend/capabilities.py` | Auflösung, `check_capability`, `require_capability` |
| `backend/entitlements.py` | Entitlements-Snapshot-Builder |
| `backend/sync_rights_registry.py` | CLI-Sync beim Container-Start |
| `backend/tenant_context.py` | `TenantContext.capabilities` |
| `backend/routers/me.py` | `/entitlements`, `/admin/demo` |
| `backend/entrypoint.sh` | Rights-Sync nach Seeds |
| `backend/version.py` | `0.3.0-ap0.3`, Schema `004` |
| `backend/tests/test_rights_registry.py` | Registry + Sync |
| `backend/tests/test_capabilities.py` | Grants, enforce/probe, Demo-Endpoint |
| `backend/tests/test_entitlements.py` | Snapshot-Form |
| `backend/tests/conftest.py` | Registry-Sync in Test-Session |
| `frontend/src/App.jsx` | Header AP0.3; `/api/me/context` zeigt Capabilities |
| `README.md` | API-Doku AP0.3 |
**Wesentliche Commits:** `910b1d7` (Implementierung), `eaa0e25` (pytest-Fix), `4069cb0` (GUI-Sprint-Label).
---
## 3. Neue Migrationen
**`004_capabilities_registry.sql`**
- **`capabilities`** — `capability_key`, `module`, `description`, `is_active`
- **`role_capability_grants`** — `role_scope` (`portal` \| `tenant`), `role_code`, `capability_key`
Kein Feature-/Limit-Schema (Vorbereitung AP0.4).
---
## 4. Registry-Struktur
```
backend/
├── rights_registry.py
├── rights_registrations/
│ ├── __init__.py
│ ├── platform.py # admin, context, entitlements
│ └── tenant_ops.py # tenant.manage, actor.manage
└── sync_rights_registry.py
```
**Modell:** `@dataclass(frozen=True) CapabilityRegistration` mit `key`, `module`, `description`, `default_grants`.
**Startup:** `entrypoint.sh``python sync_rights_registry.py` (`SKIP_RIGHTS_SYNC=1` zum Überspringen).
---
## 5. Endpoints
| Endpoint | Methode | Auth / Gate | Status |
|----------|---------|-------------|--------|
| `/api/me/context` | GET | Session | geändert — `capabilities[]` |
| `/api/me/entitlements` | GET | Session | neu |
| `/api/me/admin/demo` | GET | Session + `kairo.admin.access` | neu (Beispiel `require_capability`) |
OpenAPI (Dev): `/api/docs`
---
## 6. Capability-Auflösungslogik
```
Session (portal_role, active_tenant_id)
→ tenant_role aus Membership (optional)
→ load_grants_for_roles(portal_role, tenant_role)
→ Union Portal-Grants + Tenant-Grants
→ TenantContext.capabilities (frozenset)
```
**`require_capability(key)`:** prüft Mitgliedschaft in `ctx.capabilities`.
| Modus | Env | Verhalten |
|-------|-----|-----------|
| probe | `CAPABILITY_ENFORCE=probe` (Default) | Zugriff erlaubt; Verweigerung → Audit `capability.denied` |
| enforce | `CAPABILITY_ENFORCE=enforce` | HTTP 403 ohne Grant |
---
## 7. Initiale Capabilities
| Capability | Portal admin | Portal user | Tenant owner | Tenant admin | Tenant member |
|------------|:------------:|:-----------:|:------------:|:------------:|:-------------:|
| `kairo.admin.access` | ✓ | | | | |
| `kairo.tenant.manage` | ✓ | | ✓ | ✓ | |
| `kairo.actor.manage` | ✓ | | ✓ | ✓ | |
| `kairo.context.read` | ✓ | ✓ | ✓ | ✓ | ✓ |
| `kairo.entitlements.read` | ✓ | ✓ | ✓ | ✓ | ✓ |
---
## 8. Tests und Verifikation
### pytest (CI, Dev-Container)
```bash
docker compose -f docker-compose.dev-env.yml exec backend python -m pytest tests -ra -vv
```
| Testdatei | Abdeckung | Status |
|-----------|-----------|--------|
| `test_rights_registry.py` | 5 Capabilities, Sync idempotent | ✓ |
| `test_capabilities.py` | Admin/Member enforce, Owner-Grants, probe | ✓ |
| `test_entitlements.py` | Snapshot-Struktur | ✓ |
| `test_migrations.py` | Migration 004 | ✓ |
| Gesamt Test Suite (Gitea) | nach Push `develop` | ✓ (Nutzer bestätigt) |
### Manuell (Dev-GUI)
| Prüfung | Ergebnis |
|---------|----------|
| Login `lars@stommer.com` | ✓ |
| `/api/me/context``capabilities` sichtbar | ✓ |
| API Health → `"schema": "004"` | ✓ |
| Header Sprint-Anzeige AP0.3 | ✓ (nach `4069cb0`) |
**Hinweis:** Entitlements und Admin-Demo sind in der GUI noch nicht als eigene Karten — prüfbar über Swagger (`/api/docs`) oder DevTools.
---
## 9. Übernommene Muster aus Shinkan
| Muster | Kairo-Umsetzung |
|--------|-----------------|
| Registry-first | `rights_registry.py` + `rights_registrations/` |
| `register_capability()` mit Validierung | Pflichtfelder `key`, `module`, `description` |
| Frozen Dataclass-Definitionen | `CapabilityRegistration` |
| Startup-Sync Registry → DB | `sync_rights_registry_to_db()` |
| Modul-Ownership | `platform`, `tenant` |
| Default Grants in Code | `default_grants` pro Capability |
| `require_capability` Dependency | `capabilities.py` |
| `/api/me/entitlements` Snapshot | `entitlements.py` |
| Probe vs. Enforce | `CAPABILITY_ENFORCE` |
**Nicht übernommen:** `club_id`, Vereinsrollen, Übungs-/Trainingsrechte, Club-Feature-Kontingente.
---
## 10. Übernommene Muster aus Mitai
| Muster | Kairo-Umsetzung |
|--------|-----------------|
| Entitlements als zentrale Schicht | `build_entitlements_snapshot()` |
| Probe-vs-Enforce-Denken | Default `probe`, optional `enforce` |
| Feature-Registry vorbereitet | `features: {}` im Snapshot |
**Nicht übernommen:** Tier/Subscription, Usage-Zähler, Billing, Legacy `check_feature_access`.
---
## 11. Bewusst nicht übernommen
- Shinkan-/Mitai-Domänenbegriffe (`club`, `profile`, Tier)
- Feature-Limits, Billing, Coupons
- Prompt Registry, Vorhaben-/Projektlogik
- MCP, produktive Admin-UI (nur Debug-JSON + Swagger)
- Capabilities nur in SQL pflegen
- Governance/Object-ACL
---
## 12. Abweichungen von Designprinzipien
| Thema | Abweichung | Begründung |
|-------|------------|------------|
| Entitlements-Struktur | Account- + Tenant-Block | Kairo Hybrid laut Family Entitlement Model |
| Feature-Registry | leeres Objekt | AP0.4 |
| Grant-Overrides | Sync nur additive Grants | Sprint-0-Minimal |
| `linked_feature_id` | nicht modelliert | Keine Limits in AP0.3 |
| Frontend | kein Entitlements-Panel | Minimal-UI; AP0.4/UX optional |
**Eingehalten:** zentrale Capability-Prüfung; Portal- vs. Tenant-Rolle getrennt; TenantContext als Auflösungsschicht.
---
## 13. Offene Entscheidungen
1. **Prod `CAPABILITY_ENFORCE=enforce`** — wann umstellen?
2. **Grant-Overrides in DB** vs. reiner Code-Kanon
3. **Prod-pytest-Cleanup** (`*@example.com`) — aus AP0.2 offen
4. **Frontend:** Entitlements-Karte + Admin-Demo-Button
5. **Feature-Registry** — AP0.4
---
## 14. Empfehlung für AP0.4
Laut Foundation **AP0.4 Prompt, Feature, Config Registry**:
- Feature Registry (Metadaten, ohne Billing-Limits in Sprint 0)
- PromptTemplate / PromptVersion / Placeholder
- ConfigurationEntry
- Prompt-Rendering mit Placeholder-Validation
- `features`-Block in Entitlements mit Registry-Sync
Optional vor AP0.4: Prod-Cleanup-Seed; GUI-Entitlements; `CAPABILITY_ENFORCE=enforce` in Prod nach Kalibrierung.
---
## Referenzen
- `docs/sprints/Jinkendo_Kairo_04_Sprint0_Foundation_v0.3.md` § AP0.3, §9
- `docs/reference/design-principles/shinkan/RIGHTS_REGISTRY_DESIGN_PRINCIPLES.md`
- `docs/reference/design-principles/shinkan/CAPABILITY_ENTITLEMENT_DESIGN_PRINCIPLES.md`
- `docs/reference/design-principles/alignment/FAMILY_ENTITLEMENT_MODEL.md`
- Vorgänger: `docs/sprints/Sprint0_AP0_2_Completion_Report_v0.2.md`
---
*Abgeschlossen im Rahmen Sprint 0 AP0.3. Ersetzt `Sprint0_AP0_3_Completion_Report_v0.1.md`.*