317 lines
11 KiB
Markdown
317 lines
11 KiB
Markdown
|
|
# AP0.5 – Abschlussbericht Minimaler Vorhaben- und Maßnahmen-Slice
|
|||
|
|
|
|||
|
|
**Status:** abgeschlossen
|
|||
|
|
**Stand:** 2026-07-05 (final)
|
|||
|
|
**Branch:** `develop` · Dev-Deploy und Test Suite grün · Schema `006`
|
|||
|
|
**Version:** `0.5.0-ap0.5`
|
|||
|
|
|
|||
|
|
**Scope-Entscheidung:** [ADP_AP0_5_Sprint0_Scope_Shift_v0.1.md](../architecture/ADP_AP0_5_Sprint0_Scope_Shift_v0.1.md) — Foundation-AP0.5 (Audit/Admin) → **AP0.6** verschoben.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. Scope und Einordnung
|
|||
|
|
|
|||
|
|
AP0.5 liefert den **ersten fachlich nutzbaren Kairo-Slice**: Ein angemeldeter Actor kann innerhalb eines Tenants Vorhaben und Maßnahmen verwalten, Actors zuweisen und offene Maßnahmen abrufen.
|
|||
|
|
|
|||
|
|
| Anforderung (AP0.5) | Status |
|
|||
|
|
|---------------------|--------|
|
|||
|
|
| Migration `006` (initiatives, actions, action_assignments) | ✓ |
|
|||
|
|
| Tenant-Bezug für alle Objekte | ✓ |
|
|||
|
|
| Owner Actor für Initiative | ✓ |
|
|||
|
|
| Action gehört zu Initiative | ✓ |
|
|||
|
|
| Action → ein oder mehrere Actors (Assignments) | ✓ |
|
|||
|
|
| CRUD-Minimum Initiatives | ✓ |
|
|||
|
|
| CRUD-Minimum Actions | ✓ |
|
|||
|
|
| Endpoint „Meine offenen Maßnahmen“ | ✓ |
|
|||
|
|
| Statusmodell minimal | ✓ |
|
|||
|
|
| Priority minimal | ✓ |
|
|||
|
|
| Capability-Gates (4 neue Capabilities) | ✓ |
|
|||
|
|
| Audit bei Create/Update/Statuswechsel | ✓ |
|
|||
|
|
| Tests (Isolation, CRUD, Assignment, Status) | ✓ |
|
|||
|
|
| README/API-Doku | ✓ |
|
|||
|
|
| CI pytest grün | ✓ (55/55 nach Seed-Fix) |
|
|||
|
|
|
|||
|
|
**Bewusst nicht in AP0.5:** Projects, Milestones, Programs, Reviews, Evidence, Blocker, KI/Prompt-Erweiterung, MCP, automatische Priorisierung, komplexe UI, Workflow Engine, Foundation-AP0.5 (Audit/Admin-UI).
|
|||
|
|
|
|||
|
|
**Wesentliche Commits:** `afa6815` (Implementierung), `a34a614` (Cleanup-Seed FK-Fix).
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. Definition of Done — Prüfmatrix
|
|||
|
|
|
|||
|
|
### 2.1 AP0.5-Auftrag (fachlich)
|
|||
|
|
|
|||
|
|
| Kriterium | Ergebnis | Nachweis |
|
|||
|
|
|-----------|----------|----------|
|
|||
|
|
| Vorhaben anlegen | ✓ | `POST /api/initiatives`, `test_initiative_crud` |
|
|||
|
|
| Maßnahmen erfassen | ✓ | `POST /api/initiatives/{id}/actions` |
|
|||
|
|
| Actors zuweisen | ✓ | `PUT /api/actions/{id}/assignments`, `test_action_assignments` |
|
|||
|
|
| Status ändern | ✓ | `PATCH`, `test_action_crud_and_status_change` |
|
|||
|
|
| Offene Maßnahmen abrufen | ✓ | `GET /api/actions/me/open`, `test_my_open_actions` |
|
|||
|
|
| Tenant-Isolation | ✓ | 3 Isolation-Tests |
|
|||
|
|
| Tests grün | ✓ | CI Job `pytest-backend` |
|
|||
|
|
|
|||
|
|
### 2.2 Principle Gate (G-01–G-12)
|
|||
|
|
|
|||
|
|
| ID | Prinzip | AP0.5 |
|
|||
|
|
|----|---------|-------|
|
|||
|
|
| G-01 | Tenant-first | ✓ `tenant_id` serverseitig |
|
|||
|
|
| G-02 | Actor-first | ✓ Assignments an Actors |
|
|||
|
|
| G-03 | TenantContext | ✓ `require_capability` |
|
|||
|
|
| G-04 | Auth/Capability/Feature getrennt | ✓ |
|
|||
|
|
| G-05 | Rights Registry | ✓ `initiative_ops.py` |
|
|||
|
|
| G-10 | Audit | ✓ 9 Audit-Actions |
|
|||
|
|
| G-11 | Migration Standard | ✓ `006_*` nummeriert |
|
|||
|
|
| G-12 | Fail-Fast Startup | ✓ Migration beim Start |
|
|||
|
|
|
|||
|
|
### 2.3 Sprint-0 DoD (Foundation §12) — mit ADP
|
|||
|
|
|
|||
|
|
| Kriterium | Status | Anmerkung |
|
|||
|
|
|-----------|--------|-----------|
|
|||
|
|
| Migrationen funktionieren | ✓ | 001–006 |
|
|||
|
|
| Tenant/User/Actor/Membership | ✓ | AP0.2 |
|
|||
|
|
| TenantContext, Capability, Prompt, Audit | ✓ | AP0.2–0.4 |
|
|||
|
|
| Tests Kernmodelle | ✓ | inkl. AP0.5 |
|
|||
|
|
| README aktuell | ✓ | AP0.5-Abschnitt |
|
|||
|
|
| Keine hardcodierten Rechte | ✓ | |
|
|||
|
|
| Vorhaben nicht in Sprint 0 | ⚠ | **ADP begründet** — minimaler Slice |
|
|||
|
|
| Foundation-AP0.5 Audit/Admin | ✗ | → AP0.6 |
|
|||
|
|
|
|||
|
|
### 2.4 User Story S0-07 (Audit)
|
|||
|
|
|
|||
|
|
| Feld (Foundation) | AP0.5 |
|
|||
|
|
|-------------------|-------|
|
|||
|
|
| Tenant | ✓ `tenant_id` |
|
|||
|
|
| Aktion | ✓ `action` |
|
|||
|
|
| Zeitpunkt | ✓ `created_at` |
|
|||
|
|
| Entity | ✓ in `details` (JSON) |
|
|||
|
|
| Actor | ✗ nur `user_id` (bekannt seit AP0.2) |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. Umgesetzte Dateien
|
|||
|
|
|
|||
|
|
### 3.1 Migration & Schema
|
|||
|
|
|
|||
|
|
| Datei | Zweck |
|
|||
|
|
|-------|--------|
|
|||
|
|
| `backend/migrations/006_initiatives_actions.sql` | initiatives, actions, action_assignments |
|
|||
|
|
|
|||
|
|
### 3.2 Services
|
|||
|
|
|
|||
|
|
| Datei | Zweck |
|
|||
|
|
|-------|--------|
|
|||
|
|
| `backend/services/initiatives.py` | Vorhaben-CRUD, Validierung, Audit |
|
|||
|
|
| `backend/services/actions.py` | Maßnahmen-CRUD, Assignments, offene Maßnahmen |
|
|||
|
|
|
|||
|
|
### 3.3 API & Capabilities
|
|||
|
|
|
|||
|
|
| Datei | Zweck |
|
|||
|
|
|-------|--------|
|
|||
|
|
| `backend/routers/initiatives.py` | Initiative-Endpoints + nested Actions |
|
|||
|
|
| `backend/routers/actions.py` | Action-Endpoints + `/me/open` |
|
|||
|
|
| `backend/rights_registrations/initiative_ops.py` | 4 Capabilities |
|
|||
|
|
| `backend/main.py` | Router-Mount |
|
|||
|
|
| `backend/version.py` | `0.5.0-ap0.5`, Schema `006` |
|
|||
|
|
|
|||
|
|
### 3.4 Tests, Seeds, Doku
|
|||
|
|
|
|||
|
|
| Datei | Zweck |
|
|||
|
|
|-------|--------|
|
|||
|
|
| `backend/tests/test_initiatives_actions.py` | 11 Tests AP0.5 |
|
|||
|
|
| `backend/tests/test_migrations.py` | Migration 006 |
|
|||
|
|
| `backend/tests/test_rights_registry.py` | 16 Capabilities |
|
|||
|
|
| `backend/seeds/seed_001_cleanup_pytest_artifacts.dev.sql` | Initiatives vor Actor-Löschung (FK-Fix) |
|
|||
|
|
| `README.md` | API-Doku AP0.5 |
|
|||
|
|
| `docs/MIGRATIONS.md` | Migrationstabelle 001–006 |
|
|||
|
|
| `docs/architecture/ADP_AP0_5_Sprint0_Scope_Shift_v0.1.md` | Scope-Entscheidung |
|
|||
|
|
| `frontend/src/App.jsx` | Header AP0.5 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. Neue Migrationen
|
|||
|
|
|
|||
|
|
**`006_initiatives_actions.sql`**
|
|||
|
|
|
|||
|
|
| Tabelle | Spalten (Kern) |
|
|||
|
|
|---------|----------------|
|
|||
|
|
| `initiatives` | `tenant_id`, `title`, `goal`, `status`, `priority`, `owner_actor_id` |
|
|||
|
|
| `actions` | `tenant_id`, `initiative_id`, `title`, `description`, `status`, `priority` |
|
|||
|
|
| `action_assignments` | `tenant_id`, `action_id`, `actor_id` — UNIQUE `(action_id, actor_id)` |
|
|||
|
|
|
|||
|
|
CHECK-Constraints für Status und Priority. `owner_actor_id` → `actors` ON DELETE **RESTRICT**.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. Datenmodell
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
tenants
|
|||
|
|
└── initiatives
|
|||
|
|
id, tenant_id, title, goal, status, priority
|
|||
|
|
owner_actor_id → actors
|
|||
|
|
created_at, updated_at
|
|||
|
|
└── actions [ON DELETE CASCADE]
|
|||
|
|
id, tenant_id, initiative_id, title, description
|
|||
|
|
status, priority
|
|||
|
|
└── action_assignments [ON DELETE CASCADE von action]
|
|||
|
|
id, tenant_id, action_id, actor_id
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. Endpoints
|
|||
|
|
|
|||
|
|
| Endpoint | Methode | Capability |
|
|||
|
|
|----------|---------|------------|
|
|||
|
|
| `/api/initiatives` | GET | `kairo.initiative.read` |
|
|||
|
|
| `/api/initiatives` | POST | `kairo.initiative.manage` |
|
|||
|
|
| `/api/initiatives/{id}` | GET/PATCH/DELETE | read / manage |
|
|||
|
|
| `/api/initiatives/{id}/actions` | GET/POST | `kairo.action.read` / manage |
|
|||
|
|
| `/api/actions/{id}` | GET/PATCH/DELETE | action.read / manage |
|
|||
|
|
| `/api/actions/{id}/assignments` | PUT | `kairo.action.manage` |
|
|||
|
|
| `/api/actions/me/open` | GET | `kairo.action.read` |
|
|||
|
|
|
|||
|
|
`tenant_id` ausschließlich aus `TenantContext` — nie aus Client-Body.
|
|||
|
|
|
|||
|
|
Details und curl-Beispiele: `README.md`.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. Statusmodell
|
|||
|
|
|
|||
|
|
**Initiative:** `active` · `paused` · `completed` · `archived`
|
|||
|
|
|
|||
|
|
**Action:** `open` · `in_progress` · `blocked` · `done` · `discarded`
|
|||
|
|
|
|||
|
|
**Priorität:** `low` · `normal` · `high`
|
|||
|
|
|
|||
|
|
**Offen** (`/api/actions/me/open`): Status ∈ `{open, in_progress, blocked}` und zugewiesen an `ctx.actor_id`. Sortierung: Priority high→low, dann `updated_at DESC`.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8. Assignment-Modell
|
|||
|
|
|
|||
|
|
- n:m über `action_assignments`
|
|||
|
|
- `PUT /api/actions/{id}/assignments` ersetzt die komplette Liste
|
|||
|
|
- Beim Create optional `assigned_actor_ids`
|
|||
|
|
- Assignee-Actors müssen im gleichen Tenant und aktiv sein
|
|||
|
|
- Cross-Tenant-Zuweisung → HTTP 400
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 9. Capability-Nutzung
|
|||
|
|
|
|||
|
|
| Capability | Default-Grants |
|
|||
|
|
|------------|----------------|
|
|||
|
|
| `kairo.initiative.read` | portal user/admin, tenant owner/admin/member |
|
|||
|
|
| `kairo.initiative.manage` | portal admin, tenant owner/admin/member |
|
|||
|
|
| `kairo.action.read` | portal user/admin, tenant owner/admin/member |
|
|||
|
|
| `kairo.action.manage` | portal admin, tenant owner/admin/member |
|
|||
|
|
|
|||
|
|
Enforcement: `require_capability()` → `require_tenant_context` → Probe/Enforce via `CAPABILITY_ENFORCE`.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 10. Tenant-Isolation
|
|||
|
|
|
|||
|
|
- Alle Queries: `WHERE tenant_id = %s` aus `ctx.tenant_id`
|
|||
|
|
- Fremde IDs → **404** (kein Leak)
|
|||
|
|
- Cross-Tenant-Actor → **400**
|
|||
|
|
- Tests: `test_tenant_isolation_initiatives`, `test_tenant_isolation_actions`, `test_cross_tenant_actor_assignment_rejected`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 11. Audit
|
|||
|
|
|
|||
|
|
| Audit-Action | Trigger |
|
|||
|
|
|--------------|---------|
|
|||
|
|
| `initiative.created` | POST Initiative |
|
|||
|
|
| `initiative.updated` | PATCH Initiative |
|
|||
|
|
| `initiative.status_changed` | PATCH mit Statusänderung |
|
|||
|
|
| `initiative.deleted` | DELETE Initiative |
|
|||
|
|
| `action.created` | POST Action |
|
|||
|
|
| `action.updated` | PATCH Action |
|
|||
|
|
| `action.status_changed` | PATCH mit Statusänderung |
|
|||
|
|
| `action.assigned` | PUT Assignments |
|
|||
|
|
| `action.deleted` | DELETE Action |
|
|||
|
|
|
|||
|
|
Nachweis: `test_audit_on_create_and_status_change`.
|
|||
|
|
|
|||
|
|
**Lücke (S0-07):** kein `actor_id`-Feld in `audit_log` — nur `user_id`. Offen für AP0.6.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 12. Tests & CI
|
|||
|
|
|
|||
|
|
### 12.1 Testabdeckung AP0.5
|
|||
|
|
|
|||
|
|
| Test | Abdeckung |
|
|||
|
|
|------|-----------|
|
|||
|
|
| `test_initiative_crud` | Create, List, Get, Update, Delete |
|
|||
|
|
| `test_action_crud_and_status_change` | Lifecycle + Status |
|
|||
|
|
| `test_action_assignments` | Multi-Actor |
|
|||
|
|
| `test_my_open_actions` | Filter offen/erledigt/nicht zugewiesen |
|
|||
|
|
| `test_tenant_isolation_*` | Cross-Tenant 404 |
|
|||
|
|
| `test_cross_tenant_actor_assignment_rejected` | FK-Logik |
|
|||
|
|
| `test_audit_on_create_and_status_change` | Audit-Log |
|
|||
|
|
| `test_member_has_initiative_capabilities` | Grants |
|
|||
|
|
| `test_unauthenticated_rejected` | Auth-Gate |
|
|||
|
|
| `test_invalid_status_rejected` | Pydantic |
|
|||
|
|
|
|||
|
|
### 12.2 CI-Nachweis
|
|||
|
|
|
|||
|
|
| Lauf | Ergebnis |
|
|||
|
|
|------|----------|
|
|||
|
|
| Erster Push `afa6815` | 53 passed, **2 failed** (Cleanup-Seed FK) |
|
|||
|
|
| Fix `a34a614` | **55 passed**, 0 failed |
|
|||
|
|
|
|||
|
|
Fehlerursache: `initiatives.owner_actor_id` RESTRICT verhinderte Actor-Löschung im pytest-Cleanup. Fix: Initiatives vor Actors in `seed_001_cleanup_pytest_artifacts.dev.sql` löschen.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 13. Abweichungen von Foundation / Designprinzipien
|
|||
|
|
|
|||
|
|
| Thema | Abweichung | Begründung / ADP |
|
|||
|
|
|-------|------------|------------------|
|
|||
|
|
| AP-Nummerierung | AP0.5 ≠ Foundation-AP0.5 | ADP Scope-Verschiebung |
|
|||
|
|
| Vorhaben in Sprint 0 | minimaler Slice | ADP Option B |
|
|||
|
|
| Audit Actor-Feld | nur `user_id` | AP0.2-Schema, AP0.6 |
|
|||
|
|
| GUI | keine Vorhaben-UI | bewusst minimal |
|
|||
|
|
| Feature Registry | keine initiative-Features | Capabilities reichen |
|
|||
|
|
|
|||
|
|
**Eingehalten:** Tenant/Actor/Capability-Trennung; keine hardcodierten Rechte; nummerierte Migration; kein Mitai/Shinkan-Domänencode.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 14. Bewusst nicht übernommen
|
|||
|
|
|
|||
|
|
- Projects, Milestones, Programs, Reviews, Evidence, Blocker
|
|||
|
|
- KI/Prompt-Erweiterung, MCP, Workflow Engine
|
|||
|
|
- Automatische Priorisierung
|
|||
|
|
- Foundation-AP0.5: Admin-Routen, Admin-Seite, granulares Registry-Audit
|
|||
|
|
- GUI für Vorhaben/Maßnahmen (Swagger/API)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 15. Empfehlung AP0.6
|
|||
|
|
|
|||
|
|
**Foundation-AP0.5 nachziehen (Audit & Admin):**
|
|||
|
|
|
|||
|
|
- Granulares Audit (optional `actor_id` in `audit_log`)
|
|||
|
|
- Minimale Admin-Routen oder Admin-Seite
|
|||
|
|
- Entitlements-/Registry-Prüfbarkeit in GUI
|
|||
|
|
|
|||
|
|
**Alternativ fachlich:** Kommentare pro Maßnahme (`action_comments`) — siehe v0.1 §11.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Referenzen
|
|||
|
|
|
|||
|
|
- Auftrag: AP0.5 Minimaler Vorhaben- und Maßnahmen-Slice (Cursor)
|
|||
|
|
- ADP: `docs/architecture/ADP_AP0_5_Sprint0_Scope_Shift_v0.1.md`
|
|||
|
|
- Foundation: `docs/sprints/Jinkendo_Kairo_04_Sprint0_Foundation_v0.3.md` § AP0.5, §12, §13
|
|||
|
|
- Principle Gate: `docs/architecture/Kairo_Sprint0_Principle_Gate_v0.1.md`
|
|||
|
|
- Vorgänger: `docs/sprints/Sprint0_AP0_4_Completion_Report_v0.2.md`
|
|||
|
|
- v0.1: `docs/sprints/Sprint0_AP0_5_Completion_Report_v0.1.md`
|