# AP0.7 – Abschlussbericht Tenant Hardening, Actor Directory & Data Layer Minimum **Status:** abgeschlossen **Stand:** 2026-07-05 (final) **Branch:** `develop` · Dev-Deploy und Tests grün **Version:** Backend `0.7.0-ap0.7` · Frontend `0.7.0-ap0.7` · Schema `006` (unverändert) **Wesentliche Commits:** `db06af0` (Implementierung), `02b3b17` (Fix Überblick-Widget Overflow) --- ## 1. Scope und Einordnung AP0.7 ist ein **Basis-Härtungsauftrag** — keine neuen großen Fachfeatures. | Teil | Ziel | Status | |------|------|--------| | A | Tenant Hardening | ✓ Invarianten dokumentiert, Endpoints geprüft, Tests ergänzt | | B | Actor Directory | ✓ `GET /api/actors`, ActorSelect mit echter Liste | | C | Data Layer Minimum | ✓ `backend/data_layer/`, Workspace-Endpoints, Widget-Integration | | D | Audit-Härtung | ✓ Bewertung — `actor_id`-Spalte bewusst zurückgestellt | **Keine neue Migration** — Read-Models nutzen Schema `006`. **Produktfrage beantwortet:** Kairo steht vor weiterem Fachausbau auf einer tenant-sicheren Basis mit Actor Directory und zentraler Read-Schicht. --- ## 2. Definition of Done — Prüfmatrix ### 2.1 AP0.7-Auftrag (Abnahmekriterien) | Kriterium | Ergebnis | Nachweis | |-----------|----------|----------| | Tenant-Invarianten dokumentiert | ✓ | `Kairo_Tenant_Invariants_v0.1.md` | | Fachliche Endpoints tenant-geprüft | ✓ | Code-Review Initiatives/Actions/Actors | | Cross-Tenant-Tests | ✓ | `test_ap07.py`, `test_initiatives_actions.py` | | `GET /api/actors` | ✓ | Router + 14 AP0.7-Tests | | ActorSelect echte Liste | ✓ | `useActors()` + `/api/actors` | | Maßnahmen Tenant-Actors zuweisbar | ✓ | Assignment-Tests + UI | | Data Layer Minimum | ✓ | `backend/data_layer/` | | Workspace Summary | ✓ | API + `WorkspaceSummaryWidget` | | Blocked/Active zentral | ✓ | `/api/workspace/actions/*` | | Actor Workload Basic | ✓ | API (kein UI-Widget) | | Frontend nutzt Data Layer | ✓ | Widgets ohne Client-Aggregation | | Keine großen Fachfeatures | ✓ | Read-only Erweiterung | | AP0.6b UX erhalten | ✓ | Look & Feel unverändert | | Tests grün | ✓ | pytest + Vitest 9/9 | | README/Doku | ✓ | README, Tenant-Invarianten, dieser Bericht | ### 2.2 Scope Teil A–D | Teil | Ergebnis | |------|----------| | A — Tenant Hardening | ✓ 10 Invarianten, keine neuen Leaks gefunden | | B — Actor Directory | ✓ List + Detail, `kairo.actor.read` | | C — Data Layer | ✓ 5 Read-Funktionen, 5 Workspace-Endpoints | | D — Audit | ✓ `actor_id`-Spalte zurückgestellt, begründet | ### 2.3 Tests | Test | Ergebnis | Nachweis | |------|----------|----------| | `test_ap07.py` | ✓ 14/14 | Actor, Workspace, Cross-Tenant, Capabilities | | `test_rights_registry.py` | ✓ | 18 Capabilities | | Vitest Frontend | ✓ 9/9 | Registry inkl. `workspace_summary` | | `vite build` | ✓ | Production-Build | | Manueller UI-Smoke | ✓ | User: Überblick-Overflow gemeldet → Fix verifiziert („ok“) | ### 2.4 Post-QA Bugfix | Issue | Fix | Status | |-------|-----|--------| | Überblick-Widget: Kennzahlen ragen über Kartenrand | `02b3b17` — volle Grid-Breite, 2×2/4-Spalten responsive, `minmax(0,1fr)` | ✓ behoben, User bestätigt | --- ## 3. Umgesetzte Dateien ### Backend (neu) | Datei | Zweck | |-------|--------| | `backend/data_layer/` | Read-Models: actions, initiatives, actors, workspace | | `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` | 14 AP0.7-Tests | ### Backend (geändert) | Datei | Änderung | |-------|----------| | `backend/services/actors.py` | `list_actors`, `get_actor` | | `backend/routers/actions.py` | `/me/open` → Data Layer | | `backend/main.py` | Router actors + workspace | | `backend/version.py` | `0.7.0-ap0.7` | ### Frontend (neu/geändert) | Datei | Zweck | |-------|--------| | `frontend/src/api/workspace.js` | Workspace API-Client | | `frontend/src/hooks/useActors.js` | Actor Directory + Fallback | | `frontend/src/widgets/WorkspaceSummaryWidget.jsx` | Überblick-Karte | | Widgets, `ActorSelect`, `ActionForm`, `InitiativeDetailPage` | Data Layer + echte Actors | | `frontend/src/styles/pages.css` | Summary-Metrics (Post-QA-Fix) | ### Doku | Datei | Zweck | |-------|--------| | `docs/architecture/Kairo_Tenant_Invariants_v0.1.md` | Mandanten-Invarianten | | `README.md` | AP0.7 API, Capabilities, Smoke-Test | --- ## 4. Tenant Hardening **Ergebnis:** AP0.5-Services waren bereits tenant-sicher (`tenant_id` aus Context, Queries gefiltert, Cross-Tenant → 404). **AP0.7 ergänzt:** Actor-Directory-Isolation, Workspace-Data-Layer-Tests, verbindliche Invarianten-Doku. **Gefundene Mandantenrisiken:** Keine neuen Lücken. Actor-Zuweisungen weiter über `_actor_in_tenant()`. --- ## 5. Tenant-Invarianten 10 verbindliche Invarianten in `docs/architecture/Kairo_Tenant_Invariants_v0.1.md`: 1. Fachliche Tabellen mit `tenant_id` 2. `tenant_id` aus TenantContext 3. Queries filtern nach `tenant_id` 4. Fremde IDs → 404 5. Assignments tenant-intern 6. User ≠ Actor 7. Actors tenant-scoped 8. Audit mit `tenant_id` 9. Neue Tabellen: Tenant-Entscheidung 10. Router delegieren an Services/Data Layer --- ## 6. Actor Directory | Endpoint | Capability | Verhalten | |----------|------------|-----------| | `GET /api/actors` | `kairo.actor.read` | Aktive Tenant-Actors; Filter `actor_type`, `q`, `include_inactive` | | `GET /api/actors/{id}` | `kairo.actor.read` | Detail; Cross-Tenant → 404 | Response: `{ id, name, actor_type, is_active }` — **ohne** `user_id`. **Grants `kairo.actor.read`:** Portal Admin/User, Tenant Owner/Admin/Member — für Assignment-UI und Workload für alle operativen Mitglieder. --- ## 7. ActorSelect / Assignment UX - `useActors()` lädt `/api/actors` - Mehrfachauswahl, Typ-Labels (Mensch, Agent, …) - Fallback auf Human Actor bei API-Fehler - Loading/Error/Empty States - Agents/Working Groups aus dem Tenant zuweisbar --- ## 8. Data Layer Struktur ```text backend/data_layer/ actions.py — get_my_open_actions, get_my_blocked_actions initiatives.py — get_active_initiatives actors.py — get_actor_workload workspace.py — get_workspace_summary ``` | Schicht | Verantwortung | |---------|---------------| | Router | HTTP, Capability-Gates | | Data Layer | Read-Aggregation, tenant-scoped | | Services | Write/CRUD, Audit | --- ## 9. Workspace Summary `GET /api/workspace/summary`: ```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) - Tenant-weit: aktive/pausierte Vorhaben Frontend: `WorkspaceSummaryWidget` — volle Grid-Breite, responsive 2×2 / 4 Spalten. --- ## 10. Actor Workload Basic `GET /api/workspace/actors/workload` — Counts pro Actor (open, blocked, in_progress). **Nur API** — kein UI-Widget in AP0.7 (bewusst für AP0.8). --- ## 11. Neue/geänderte API-Endpunkte | Endpoint | Methode | Capability | |----------|---------|------------| | `/api/actors` | GET | `kairo.actor.read` | | `/api/actors/{id}` | GET | `kairo.actor.read` | | `/api/workspace/summary` | GET | `kairo.workspace.read` | | `/api/workspace/actions/open` | GET | `kairo.workspace.read` | | `/api/workspace/actions/blocked` | GET | `kairo.workspace.read` | | `/api/workspace/initiatives/active` | GET | `kairo.workspace.read` | | `/api/workspace/actors/workload` | GET | `kairo.workspace.read` | --- ## 12. Capability-Nutzung | Capability | Neu | Grants | |------------|-----|--------| | `kairo.actor.read` | ✓ | Member+ | | `kairo.workspace.read` | ✓ | Member+ | Gesamt: **18 Capabilities** (vorher 16). Kein separates `kairo.workspace.metrics.read`. --- ## 13. Audit-Härtung / actor_id-Bewertung | Frage | Antwort | |-------|---------| | `actor_id` als Spalte jetzt? | **Nein** — Migration 007 + Backfill → AP0.8 | | Reicht `details`? | ✓ für Assignments (`actor_ids`) | | Risiko | Gering für Sprint 0 | --- ## 14. Frontend-Integration | Widget | Datenquelle (nach AP0.7) | |--------|--------------------------| | WorkspaceSummaryWidget | `/api/workspace/summary` | | MyOpenActionsWidget | `/api/workspace/actions/open` | | BlockedActionsWidget | `/api/workspace/actions/blocked` | | InitiativesWidget | `/api/workspace/initiatives/active?limit=5` | | ActorSelect | `/api/actors` | **Keine fachliche KPI-Berechnung in Widgets.** --- ## 15. Übernommene Muster aus Mitai - Zentrale Data-Layer-Schicht - Widgets konsumieren vorbereitete Daten - Trennung Rohdaten / Kennzahlen / UI --- ## 16. Übernommene Muster aus Shinkan - Tenant-sichere Queries - Capability Gates - Cross-Tenant → 404 - Access-Layer-Denken --- ## 17. Bewusst nicht übernommene Muster - Analytics-Plattform, Forecasting, KI - Actor-Admin-UI - `audit_log.actor_id` Migration - Backend-Widget-Registry - Actor Workload UI-Widget --- ## 18. Abweichungen von der Spezifikation | Thema | Abweichung | Begründung | |-------|------------|------------| | Actor Workload | nur API | UI in AP0.8 | | `/api/actions/me/open` | beibehalten | Abwärtskompatibilität | | `done_actions_recent_count` | 7-Tage-Fenster | pragmatisch via `updated_at` | --- ## 19. Offene Entscheidungen 1. `audit_log.actor_id` — Migration AP0.8? 2. Actor Workload Widget — wann sichtbar? 3. Initiative bearbeiten in UI — PATCH existiert 4. Foundation Audit/Admin-UI — backlog --- ## 20. Empfehlung für AP0.8 1. **Audit/Admin minimal** — Audit-Log lesbar, optional `actor_id`-Spalte 2. **Actor Workload Widget** — kleine Karte im Workspace 3. **Initiative bearbeiten in UI** 4. **Kommentare pro Maßnahme** (optional) Danach Sprint-1-Fachscope gemäß Product Spec. --- ## Manueller Smoke-Test (Referenz) 1. Login → Workspace → **Überblick** mit 4 Kennzahlen, kein Overflow 2. Offene / blockierte Maßnahmen in separaten Widgets 3. Vorhaben-Detail → Maßnahme anlegen → **mehrere Actors** in ActorSelect 4. Agent zuweisen → speichern → Assignment sichtbar 5. Status blocked → erscheint nur im Blockiert-Widget 6. API: `curl /api/actors`, `/api/workspace/summary` mit Token --- ## Abnahme-Checkliste AP0.7 (final) | Kriterium | Erfüllt | |-----------|---------| | Tenant-Invarianten | ✓ | | Actor Directory | ✓ | | Data Layer | ✓ | | Workspace Summary | ✓ | | Frontend Integration | ✓ | | Tests grün | ✓ | | AP0.6b UX | ✓ | | Post-QA Überblick-Fix | ✓ |