# AP0.7 – Abschlussbericht Tenant Hardening, Actor Directory & Data Layer Minimum **Status:** abgeschlossen **Stand:** 2026-07-05 **Branch:** `develop` **Version:** Backend `0.7.0-ap0.7` · Frontend `0.7.0-ap0.7` · Schema `006` (unverändert) --- ## 1. Scope und Einordnung AP0.7 ist ein **Basis-Härtungsauftrag** — keine neuen großen Fachfeatures. | Teil | Ziel | Status | |------|------|--------| | A | Tenant Hardening | ✓ Invarianten dokumentiert, bestehende Endpoints geprüft, Tests ergänzt | | B | Actor Directory | ✓ `GET /api/actors`, `GET /api/actors/{id}`, ActorSelect mit echter Liste | | C | Data Layer Minimum | ✓ `backend/data_layer/`, Workspace-Endpoints, Widget-Integration | | D | Audit-Härtung | ✓ Bewertung dokumentiert — `actor_id`-Spalte bewusst zurückgestellt | **Keine neue Migration** — Read-Models nutzen bestehendes Schema `006`. --- ## 2. Umgesetzte Dateien ### Backend (neu) | Datei | Zweck | |-------|--------| | `backend/data_layer/__init__.py` | Data-Layer-Paket | | `backend/data_layer/actions.py` | Open/blocked Actions (Read) | | `backend/data_layer/initiatives.py` | Active Initiatives (Read) | | `backend/data_layer/actors.py` | Actor Workload (Read) | | `backend/data_layer/workspace.py` | Workspace Summary | | `backend/routers/actors.py` | Actor Directory API | | `backend/routers/workspace.py` | Workspace Read API | | `backend/rights_registrations/workspace_ops.py` | `kairo.actor.read`, `kairo.workspace.read` | | `backend/tests/test_ap07.py` | AP0.7 Tests (14 Tests) | ### Backend (geändert) | Datei | Änderung | |-------|----------| | `backend/services/actors.py` | `list_actors`, `get_actor` | | `backend/routers/actions.py` | `/me/open` delegiert an Data Layer | | `backend/main.py` | Router actors + workspace | | `backend/version.py` | `0.7.0-ap0.7` | | `backend/tests/test_rights_registry.py` | 18 Capabilities | ### Frontend (neu/geändert) | Datei | Zweck | |-------|--------| | `frontend/src/api/workspace.js` | Workspace API-Client | | `frontend/src/hooks/useActors.js` | Actor Directory Hook + Fallback | | `frontend/src/widgets/WorkspaceSummaryWidget.jsx` | Überblick-Karte | | `frontend/src/api/actors.js` | `listActors`, Fallback beibehalten | | Widgets, `ActorSelect`, `ActionForm`, `InitiativeDetailPage` | Data-Layer-Endpoints, echte Actors | | `frontend/src/registry/widgetRegistry.js` | + `kairo.workspace_summary` | ### Doku | Datei | Zweck | |-------|--------| | `docs/architecture/Kairo_Tenant_Invariants_v0.1.md` | 10 Tenant-Invarianten | | `README.md` | AP0.7 API, Capabilities | --- ## 3. Tenant Hardening **Ergebnis der Code-Prüfung:** Bestehende fachliche Services (AP0.5) waren bereits tenant-sicher aufgebaut. | Prüfpunkt | Ergebnis | |-----------|----------| | `tenant_id` aus Context, nicht Body | ✓ alle Router | | Queries mit `tenant_id`-Filter | ✓ Services + Data Layer | | Cross-Tenant → 404 | ✓ Initiatives, Actions, Actors | | Assignment tenant-sicher | ✓ `_actor_in_tenant()` | | Keine Client-`tenant_id` | ✓ | **Gefundene Mandantenrisiken:** Keine neuen Lücken in AP0.5-Code. AP0.7 schließt die fehlende Actor-Directory-Isolation und Workspace-Aggregations-Tests ab. --- ## 4. Tenant-Invarianten Verbindlich dokumentiert in `docs/architecture/Kairo_Tenant_Invariants_v0.1.md` (10 Invarianten + Anti-Patterns). --- ## 5. Actor Directory ### Endpoints | Endpoint | Capability | Verhalten | |----------|------------|-----------| | `GET /api/actors` | `kairo.actor.read` | Aktive Actors des Tenants; optional `actor_type`, `q`, `include_inactive` | | `GET /api/actors/{id}` | `kairo.actor.read` | Detail; Cross-Tenant → 404 | ### Response-Shape ```json { "id": "...", "name": "...", "actor_type": "human|agent|working_group|external_system", "is_active": true } ``` `user_id` wird **nicht** exponiert (Datenschutz). ### Default Grants `kairo.actor.read` Portal Admin/User, Tenant Owner/Admin/Member — Begründung: Assignment-UI und Workspace-Workload für alle operativen Tenant-Mitglieder. --- ## 6. ActorSelect / Assignment UX - `useActors()` lädt `/api/actors` - `ActorSelect` zeigt Name + Typ (deutsche Labels) - Mehrfachauswahl für Assignments - Fallback auf Human Actor aus Context bei API-Fehler - Loading/Error/Empty States - Maßnahmen können Agents/Working Groups aus dem Tenant zugewiesen werden --- ## 7. Data Layer Struktur ```text backend/data_layer/ actions.py — get_my_open_actions, get_my_blocked_actions, get_all_my_open_actions initiatives.py — get_active_initiatives actors.py — get_actor_workload workspace.py — get_workspace_summary ``` ### Abgrenzung | Schicht | Verantwortung | |---------|---------------| | Router | HTTP, Capability-Gates, Serialisierung | | Data Layer | Read-Aggregation, tenant-scoped Queries, DTOs | | Services | Write/CRUD, Domänenvalidierung, Audit | `/api/actions/me/open` bleibt für Abwärtskompatibilität; delegiert intern an Data Layer. --- ## 8. Workspace Summary `GET /api/workspace/summary` → `kairo.workspace.read` ```json { "open_actions_count": 0, "blocked_actions_count": 0, "active_initiatives_count": 0, "done_actions_recent_count": 0 } ``` - Personal (current actor): open, blocked, done (7 Tage via `updated_at`) - Tenant-weit: `active_initiatives_count` (status active/paused) Frontend: `WorkspaceSummaryWidget` im Workspace. --- ## 9. Actor Workload Basic `GET /api/workspace/actors/workload` — pro aktivem Actor im Tenant: ```json { "actor_id": "...", "display_name": "...", "actor_type": "human", "open_actions": 3, "blocked_actions": 1, "in_progress_actions": 2 } ``` Noch **kein dediziertes UI-Widget** — Endpoint für spätere Dashboards; API + Tests vorhanden. --- ## 10. Neue/geänderte API-Endpunkte Siehe README AP0.7-Abschnitt. Keine Write-Endpoints hinzugefügt. --- ## 11. Capability-Nutzung | Capability | Neu? | Grants | Verwendung | |------------|------|--------|------------| | `kairo.actor.read` | ✓ | Member+ | Actor Directory | | `kairo.workspace.read` | ✓ | Member+ | Workspace Data Layer | | `kairo.actor.manage` | — | unverändert | Actor-Verwaltung (AP0.2) | | `kairo.action.read` | — | unverändert | CRUD-Read, `/me/open` | | `kairo.initiative.read` | — | unverändert | Initiatives | **Entscheidung:** Kein separates `kairo.workspace.metrics.read` — ein Read-Key für alle Workspace-Read-Models. Gesamt: **18 Capabilities** (vorher 16). --- ## 12. Audit-Härtung / actor_id-Bewertung **Ist-Zustand:** `audit_log` hat `user_id`, `tenant_id`, `details` (JSONB). Kein `actor_id`-Spalte. **Bewertung:** | Option | Empfehlung | |--------|------------| | `actor_id` in `details` | ✓ bereits bei Assignments (`actor_ids`) | | `actor_id` als Spalte | **Zurückgestellt** — Migration 007 + Backfill; sinnvoll in AP0.8 (Audit/Admin) | | Risiko ohne Spalte | Gering für Sprint 0 — Actor aus Context + details ausreichend für Nachvollziehbarkeit | Keine Migration in AP0.7 (Basis-Härtung ohne Schema-Change). --- ## 13. Frontend-Integration | Widget/Komponente | Vor AP0.7 | Nach AP0.7 | |-------------------|-----------|------------| | MyOpenActionsWidget | `/api/actions/me/open` + Client-Filter | `/api/workspace/actions/open` | | BlockedActionsWidget | `/me/open` + Filter | `/api/workspace/actions/blocked` | | InitiativesWidget | `/api/initiatives` + Client-Filter | `/api/workspace/initiatives/active?limit=5` | | WorkspaceSummaryWidget | — | `/api/workspace/summary` | | ActorSelect | Context-Fallback only | `/api/actors` + Fallback | **Keine fachliche KPI-Berechnung mehr in Widgets** (Filter/Slice entfernt). AP0.6b Look & Feel unverändert. --- ## 14. Tests und Verifikation ### Backend (`test_ap07.py`) - Actor Directory: List, Filter, Inactive, Detail, Cross-Tenant - Workspace: Summary, Open, Blocked, Initiatives, Workload, Cross-Tenant - Capabilities: Member hat `kairo.actor.read`, `kairo.workspace.read` - Assignment an Tenant-Actor ### Frontend - Vitest: 9/9 grün (Registry inkl. `workspace_summary`) - Build: OK ### CI pytest im Backend-Container (wie bisher) — erwartet grün mit +14 Tests. --- ## 15. Übernommene Muster aus Mitai - Zentrale Data-Layer-Schicht für Read/Aggregation - Widgets konsumieren vorbereitete Daten - Trennung Rohdaten / Kennzahlen / UI **Nicht übernommen:** Mitai Tracking/Gesundheits-KPIs, Tier/Billing. --- ## 16. Übernommene Muster aus Shinkan - Tenant-sichere Queries mit Context-`tenant_id` - Capability Gates pro Endpoint - Cross-Tenant → 404 - Access-Layer-Denken (Data Layer als Read-Access) **Nicht übernommen:** Vereins-/Trainingslogik. --- ## 17. Bewusst nicht übernommene Muster - Analytics-Plattform, Zeitreihen, Forecasting - Actor-Admin-UI, Actor-Erstellung in GUI - `audit_log.actor_id` Migration - Backend-Widget-Registry - Program-Director-Algorithmus --- ## 18. Abweichungen von der Spezifikation | Thema | Abweichung | Begründung | |-------|------------|------------| | Actor Workload UI | nur API, kein Widget | Endpoint für später; kein UI-Scope | | Breakpoint Shell | unverändert 1024px | AP0.6b unverändert | | `/api/actions/me/open` | beibehalten | Abwärtskompatibilität | | `done_actions_recent_count` | 7-Tage-Fenster via `updated_at` | pragmatisch, dokumentiert | --- ## 19. Offene Entscheidungen 1. **`audit_log.actor_id`** — Migration in AP0.8? 2. **Actor Workload Widget** — wann in Workspace anzeigen? 3. **Initiative bearbeiten in UI** — weiter offen aus AP0.6 4. **Foundation AP0.5 Audit/Admin-UI** — backlog --- ## 20. Empfehlung für AP0.8 Kleinster Nutzwert (Priorität): 1. **Audit/Admin minimal** — Audit-Log lesbar, optional `actor_id`-Spalte 2. **Initiative bearbeiten in UI** — PATCH existiert 3. **Actor Workload Widget** — kleine Karte im Workspace 4. **Kommentare pro Maßnahme** — Kollaboration ohne Domänen-Explosion Danach Sprint-1-Fachscope gemäß Product Spec. --- ## Abnahme-Checkliste AP0.7 | Kriterium | Erfüllt | |-----------|---------| | Tenant-Invarianten dokumentiert | ✓ | | Fachliche Endpoints tenant-geprüft | ✓ | | Cross-Tenant-Tests | ✓ | | `GET /api/actors` | ✓ | | ActorSelect echte Liste | ✓ | | Tenant-Actor-Zuweisung | ✓ | | Data Layer Minimum | ✓ | | Workspace Summary | ✓ | | Blocked/Active zentral | ✓ | | Actor Workload Basic | ✓ (API) | | Frontend nutzt Data Layer | ✓ | | Keine großen Fachfeatures | ✓ | | AP0.6b UX erhalten | ✓ |