diff --git a/docs/MIGRATIONS.md b/docs/MIGRATIONS.md index 414c588..ca5c7b3 100644 --- a/docs/MIGRATIONS.md +++ b/docs/MIGRATIONS.md @@ -11,6 +11,19 @@ Kairo trennt **Schema-Migrationen** (einmalig) von **Data-Seeds** (idempotent, b | **Ausführung** | Beim Backend-Start (`run_migrations.py`), überspringbar via `SKIP_DB_MIGRATE=1` | | **Regel** | Jede Datei wird **genau einmal** angewendet. Änderungen → neue nummerierte Datei. | +### Aktuelle Schema-Migrationen + +| Nr. | Datei | AP | Inhalt | +|-----|-------|-----|--------| +| 001 | `001_init_core.sql` | AP0.1 | `kairo_app_meta` | +| 002 | `002_auth_identity_tenant_actor.sql` | AP0.2 | User, Tenant, Actor, Session, `audit_log` | +| 003 | `003_data_seeds_tracking.sql` | AP0.2+ | `data_seeds` | +| 004 | `004_capabilities_registry.sql` | AP0.3 | `capabilities`, `role_capability_grants` | +| 005 | `005_prompt_feature_config_registry.sql` | AP0.4 | Feature/Prompt/Placeholder/Config | +| 006 | `006_initiatives_actions.sql` | AP0.5 | `initiatives`, `actions`, `action_assignments` | + +Aktuelle Schema-Version: **`006`** (`backend/version.py` → `DB_SCHEMA_VERSION`). + ## Data-Seeds | | | @@ -35,7 +48,7 @@ docker compose -f docker-compose.dev-env.yml exec backend python run_seeds.py -- | Seed | Typ | Zweck | |------|-----|--------| -| `seed_001_cleanup_pytest_artifacts` | SQL (dev) | Entfernt pytest/CI-User (`*@example.com`) und verwaiste Test-Tenants | +| `seed_001_cleanup_pytest_artifacts` | SQL (dev) | Entfernt pytest/CI-User (`*@example.com`), verwaiste Test-Tenants; löscht zuerst Initiatives (AP0.5 FK) | | `seed_002_bootstrap_admin` | Python | Legt Systemadmin aus `KAIRO_BOOTSTRAP_*` an, wenn noch kein User existiert | | `seed_003_ensure_dev_admin` | Python (dev) | Entfernt fremde Dev-User, stellt `lars@stommer.com` als Portal-Admin sicher (jeder Start) | diff --git a/docs/architecture/ADP_AP0_5_Sprint0_Scope_Shift_v0.1.md b/docs/architecture/ADP_AP0_5_Sprint0_Scope_Shift_v0.1.md new file mode 100644 index 0000000..c37e062 --- /dev/null +++ b/docs/architecture/ADP_AP0_5_Sprint0_Scope_Shift_v0.1.md @@ -0,0 +1,88 @@ +# Architecture Decision Proposal — AP0.5 Scope-Verschiebung Sprint 0 + +**Status:** angenommen (Umsetzung abgeschlossen) +**Stand:** 2026-07-05 +**Autor:** Sprint-0-Umsetzung (Cursor/Claude) +**Commits:** `afa6815`, `a34a614` + +--- + +## Problem + +In `Jinkendo_Kairo_04_Sprint0_Foundation_v0.3.md` ist **AP0.5** als *Audit und minimale Admin-Prüfbarkeit* definiert. Gleichzeitig verbietet §13 *Vorhaben/Projektlogik in Sprint 0 vorziehen*; Sprint 1 sieht Vorhaben und Maßnahmen vor. + +Für den ersten **fachlich nutzbaren Kairo-Slice** wurde AP0.5 bewusst neu beauftragt als *Minimaler Vorhaben- und Maßnahmen-Slice* (Migration 006, CRUD, Assignments, Capability-Gates, Tests). + +Ohne dokumentierte Entscheidung entsteht ein **Nummerierungs- und Scope-Konflikt** zwischen Foundation-Dokument und Implementierung. + +--- + +## Betroffene Regel + +| Dokument | Regel | +|----------|--------| +| `Jinkendo_Kairo_04_Sprint0_Foundation_v0.3.md` § AP0.5 | Audit + Admin-Prüfbarkeit | +| `Jinkendo_Kairo_04_Sprint0_Foundation_v0.3.md` §13 | Keine Vorhaben/Projektlogik in Sprint 0 vorziehen | +| `Jinkendo_Kairo_04_Sprint0_Foundation_v0.3.md` §14 | Vorhaben/Maßnahmen in Sprint 1 | +| `Kairo_Sprint0_Principle_Gate_v0.1.md` G-01–G-12 | Architekturprinzipien (weiterhin verbindlich) | + +--- + +## Optionen + +| Option | Kurzbeschreibung | Pro | Contra | +|--------|------------------|-----|--------| +| A | Foundation-AP0.5 zuerst (Audit/Admin), Vorhaben in Sprint 1 | Entspricht Foundation 1:1 | Kein fachlicher End-to-End-Slice; Audit ohne Domäne schwer demonstrierbar | +| B | **AP0.5 = Vorhaben/Maßnahmen-Slice; Foundation-AP0.5 → AP0.6 umbenennen** | Erster nutzbarer Slice; Principle Gate eingehalten (Tenant, Actor, Capability, Audit) | Scope-Verschiebung; Foundation-Dokument veraltet bis Update | +| C | Vorhaben ohne AP-Nummer (Sprint-1-Vorgriff) | Schnell | Undokumentiert; verwirrt Sprint-Tracking | + +--- + +## Empfehlung + +**Option B** — angenommen und umgesetzt. + +Begründung: + +1. Der Slice ist **minimal** (keine Projects, Milestones, Programs, Reviews, KI). +2. **Principle Gate** bleibt eingehalten: Tenant-first, Actor-first, TenantContext, Capability Registry, nummerierte Migration, Audit. +3. Der ursprüngliche Foundation-AP0.5-Inhalt (granulares Audit, Admin-Routen) wird als **AP0.6** eingeplant — kein Verlust, nur Verschiebung. + +--- + +## Risiko + +| Risiko | Mitigation | +|--------|------------| +| Foundation-Dokument und Code divergieren | Dieses ADP + Abschlussbericht AP0.5 v0.2; Foundation-Update in separatem Doc-Pass | +| Sprint-1-Doppelarbeit | AP0.5 bewusst minimal; Meilensteine/Programme/Backlog bleiben Sprint 1 | +| Audit-Schema ohne `actor_id` | Bekannte Lücke seit AP0.2; AP0.6 kann Schema erweitern | + +--- + +## Rückbaubarkeit + +- Tabellen `initiatives`, `actions`, `action_assignments` sind additiv (Migration 006). +- Rückbau: neue Migration mit `DROP TABLE` — keine Änderung an AP0.1–0.4-Tabellen. +- Capabilities in `initiative_ops.py` können deaktiviert werden, ohne andere Module zu brechen. + +--- + +## Auswirkung auf Sprint 0 + +| Thema | Auswirkung | +|-------|------------| +| Sprint-0-Fundament (AP0.1–0.4) | unverändert | +| AP0.5 (neu) | fachlicher Minimal-Slice Vorhaben/Maßnahmen | +| Foundation-AP0.5 (Audit/Admin) | **→ AP0.6** (empfohlen) | +| Sprint-0 DoD §12 | Vorhaben-Teil formal Sprint 1 — durch ADP begründete Ausnahme | +| Prod/Dev | Schema `006`; pytest 55/55 grün nach Cleanup-Seed-Fix | + +--- + +## Nächste Schritte (Dokumentation) + +1. ~~ADP (dieses Dokument)~~ +2. ~~`docs/MIGRATIONS.md` um 006 ergänzen~~ +3. ~~`Sprint0_AP0_5_Completion_Report_v0.2.md`~~ +4. Foundation v0.4 (optional): AP-Nummern und §13/§14 angleichen diff --git a/docs/sprints/Sprint0_AP0_5_Completion_Report_v0.2.md b/docs/sprints/Sprint0_AP0_5_Completion_Report_v0.2.md new file mode 100644 index 0000000..5f41a9b --- /dev/null +++ b/docs/sprints/Sprint0_AP0_5_Completion_Report_v0.2.md @@ -0,0 +1,316 @@ +# 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`