Kairo-Jinkendo/docs/sprints/Sprint0_AP0_2_Completion_Report_v0.2.md

249 lines
9.1 KiB
Markdown
Raw Permalink Normal View History

# AP0.2 – Abschlussbericht Auth, Identity, Tenant & Actor Foundation
**Status:** abgeschlossen
**Stand:** 2026-07-04 (final)
**Branch:** `develop` · Prod-Deploy auf `main` erfolgt und stabil
---
## 1. Scope und Einordnung
AP0.2 liefert die **Auth-, Identity-, Tenant- und Actor-Grundlage** für Kairo. Gegenüber dem ursprünglichen Foundation-Dokument (`Jinkendo_Kairo_04_Sprint0_Foundation_v0.3.md`) wurde der für AP0.3 vorgesehene **Auth-/TenantContext-Teil bereits in AP0.2** umgesetzt.
| Anforderung (AP0.2 / erweitert) | Status |
|----------------------------------|--------|
| Tenant, User, Membership | ✓ |
| Actor (human, agent, working_group, external_system) | ✓ |
| Server-Sessions, Login/Logout | ✓ |
| TenantContext + Tenant-Wechsel | ✓ |
| Portal-Rolle vs. Tenant-Rolle getrennt | ✓ |
| Seed für Admin (Env + Erstregistrierung + Dev-Seed) | ✓ |
| Audit bei Auth-Aktionen | ✓ |
| Frontend Login/Register (minimal) | ✓ |
| Idempotentes Data-Seed-System | ✓ (Erweiterung) |
**Bewusst nicht in AP0.2:** Capabilities/Rights Registry, Rate-Limiting, Tenant-Admin-API, Passwort-Reset.
---
## 2. Umgesetzte Artefakte
### Backend – Schema & Migrationen
| Datei | Zweck |
|-------|--------|
| `backend/migrations/002_auth_identity_tenant_actor.sql` | User, Session, Tenant, Membership, Actor, Audit |
| `backend/migrations/003_data_seeds_tracking.sql` | Tabelle `data_seeds` für Seed-Tracking |
| `backend/run_migrations.py` | Schema-Migrationen (`schema_migrations`) |
| `backend/run_seeds.py` | Data-Seeds (Checksum, Dev-Seeds bei jedem Start) |
| `backend/entrypoint.sh` | Migrationen + Seeds vor Uvicorn-Start |
### Backend – Domäne & Services
| Datei | Zweck |
|-------|--------|
| `backend/auth.py` | bcrypt, Sessions, `require_auth`, `require_portal_admin` |
| `backend/tenant_context.py` | `TenantContext`, `get_tenant_context`, `require_tenant_context` |
| `backend/bootstrap.py` | Env-Bootstrap (`KAIRO_BOOTSTRAP_*`) |
| `backend/services/registration.py` | Erstregistrierung, `provision_system_admin` |
| `backend/services/dev_admin.py` | Dev-Admin sicherstellen (nur Nicht-Prod) |
| `backend/services/actors.py` | Actor-Erzeugung, Human-Lookup |
| `backend/services/audit.py` | Audit-Log |
### Backend – API
| Datei | Zweck |
|-------|--------|
| `backend/routers/auth.py` | Login, Logout, Register, Setup-Status |
| `backend/routers/me.py` | `/api/me`, `/api/me/context`, Tenant-Wechsel |
| `backend/main.py` | Router, Startup (Fallback ohne Entrypoint) |
### Data-Seeds
| Seed | Umgebung | Zweck |
|------|----------|--------|
| `seed_001_cleanup_pytest_artifacts.dev.sql` | Dev | Entfernt `*@example.com`, verwaiste Test-Tenants |
| `seed_002_bootstrap_admin.py` | Dev + Prod | Admin aus `KAIRO_BOOTSTRAP_*` wenn DB leer |
| `seed_003_ensure_dev_admin.dev.py` | Dev | Stellt `lars@stommer.com` als Portal-Admin sicher |
Doku: `docs/MIGRATIONS.md`
### Frontend
| Datei | Zweck |
|-------|--------|
| `frontend/src/App.jsx` | Login/Register-Tabs, Session-Anzeige, Setup-Status |
| `frontend/src/app.css` | Auth-UI, Tabs, Hinweise |
### Tests
| Datei | Abdeckung |
|-------|-----------|
| `test_auth.py` | Login, Logout, Session, `/api/me`, Context, Tenant-Wechsel |
| `test_tenant_actor.py` | Actor-Typen, Portal- vs. Tenant-Rolle |
| `test_registration.py` | Erstregistrierung, Setup-Status |
| `test_seeds.py` | Seed-Runner, Cleanup, Dev-Admin |
| `test_migrations.py` | Migrationen 001–003, Idempotenz |
### Infrastruktur & Doku
| Datei | Zweck |
|-------|--------|
| `docker-compose.dev-env.yml`, `docker-compose.yml` | Postgres pro Stack, Bootstrap/Session-Env, Healthcheck |
| `backend/Dockerfile` | Entrypoint für Startup-Reihenfolge |
| `.gitea/workflows/deploy-dev.yml` | Deploy Dev + Logs bei Fehler |
| `.gitea/workflows/test.yml` | pytest + Seed-Cleanup nach CI |
| `README.md`, `docs/DEPLOYMENT.md` | Local Dev, Auth, DB-Volume-Wechsel |
**Version:** `APP_VERSION = 0.2.0-ap0.2`, `DB_SCHEMA_VERSION = 003`
---
## 3. Datenmodell (Migration 002)
- **`users`** — E-Mail, bcrypt-Hash, `portal_role` (`user` \| `admin`)
- **`sessions`** — opaque Token, `user_id`, `active_tenant_id`, Ablauf
- **`tenants`** — Slug (unique), Name, aktiv
- **`tenant_memberships`** — `tenant_role` (`owner` \| `admin` \| `member`)
- **`actors`** — `human`, `agent`, `working_group`, `external_system`; Human verknüpft mit `user_id`
- **`audit_log`** — Auth-Ereignisse (JSONB-Details)
---
## 4. API-Endpunkte
| Endpoint | Methode | Auth | Beschreibung |
|----------|---------|------|--------------|
| `/api/auth/setup-status` | GET | — | `registration_open`, `has_users`, `user_count` |
| `/api/auth/register` | POST | — | Erster User → Portal-Admin (nur leere DB) |
| `/api/auth/login` | POST | — | E-Mail + Passwort → Session-Token |
| `/api/auth/logout` | POST | `X-Auth-Token` | Session löschen |
| `/api/me` | GET | `X-Auth-Token` | User + Tenant-Liste |
| `/api/me/context` | GET | `X-Auth-Token` | TenantContext (Tenant + Human Actor) |
| `/api/me/context/required` | GET | `X-Auth-Token` | Wie Context, 403 ohne aktiven Tenant |
| `/api/me/tenant` | POST | `X-Auth-Token` | Aktiven Tenant wechseln (nur Memberships) |
OpenAPI (Dev): `/api/docs`
---
## 5. Auth-Fluss
```
POST /api/auth/login { email, password }
→ bcrypt verify
→ INSERT sessions (token, expires_at, active_tenant_id = erste Membership)
→ audit: auth.login
→ Response: { token, expires_at, user }
Request mit Header X-Auth-Token
→ get_session(token) JOIN users
→ require_auth → session (user_id aus DB, nie aus Client-Body)
POST /api/auth/logout → DELETE session → audit: auth.logout
```
**Ersteinrichtung (Priorität):**
1. **Dev:** Seed `seed_003` — `lars@stommer.com` (Portal-Admin, bei jedem Start)
2. **Prod/Dev:** Seed `seed_002` — `KAIRO_BOOTSTRAP_*` wenn DB leer
3. **UI:** `POST /api/auth/register` — nur wenn `user_count == 0`
---
## 6. TenantContext
```
require_auth → session (user_id, active_tenant_id, portal_role)
→ tenant_memberships + tenants (nur aktiv)
→ human actor: actors WHERE tenant_id + user_id + type = human
→ TenantContext(portal_role, tenant_role, tenant, actor)
```
Tenant-Wechsel: `POST /api/me/tenant { tenant_id }` — nur bei gültiger Membership.
---
## 7. Deployment & Betrieb
| | Development | Production |
|---|-------------|------------|
| Verzeichnis | `/home/lars/docker/kairo-dev` | `/home/lars/docker/kairo` |
| Ports | 3097 / 8097 | 3004 / 8004 |
| Postgres | Eigener Container + Volume pro Stack | Eigener Container + Volume |
| Dev-Seeds | Ja (Cleanup + Dev-Admin) | Nein (`.dev.*` übersprungen) |
| Admin-Zugang | `lars@stommer.com` (Seed) | `KAIRO_BOOTSTRAP_*` in `.env` |
**Startup-Reihenfolge:** Entrypoint → Schema-Migrationen → Data-Seeds → Uvicorn.
**DB-Zugangsdaten ändern:** Volume neu anlegen (`docker compose down -v`) — siehe `docs/DEPLOYMENT.md`.
**Verifikation (2026-07-04):** Dev und Prod stabil nach Deploy; Dev-DB-Wechsel mit frischem Volume erfolgreich.
---
## 8. Tests & CI
```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
```
| Bereich | Status |
|---------|--------|
| pytest-backend (Dev/Prod im Container) | ✓ |
| compose-smoke (PR, isolierte Ports) | ✓ |
| k6 Health-Baseline | ✓ |
| Playwright smoke | ✓ |
| Seed-Cleanup nach pytest (Dev) | ✓ |
**Hinweis Betrieb:** pytest gegen deployte Instanz erzeugt `*@example.com`-User. Dev-Seed räumt auf; auf Prod bleiben Test-User bestehen (Cleanup-Seed läuft dort nicht). Prod-DB bei Bedarf manuell prüfen.
---
## 9. Abweichungen von Designprinzipien
| Thema | Kairo AP0.2 | Begründung |
|-------|-------------|------------|
| Mitai `profiles` | `users` + separate `actors` | User ≠ Actor, kein Multi-Profil-Legacy |
| Passwort-Hash | nur bcrypt | Grüne Wiese |
| Query-Token / SSE | nicht implementiert | Später |
| Capabilities in TenantContext | fehlen | AP0.3 |
| Zentrale Postgres-Instanz | je Stack eigener Container | Isolation wie Shinkan/Mitai |
**Eingehalten:** Server-Sessions, `X-Auth-Token`, `Depends(require_auth)`, Portal- vs. Tenant-Rolle, TenantContext-Schicht, nummerierte Migrationen.
---
## 10. Offene Punkte (nach AP0.2)
1. **Rate-Limiting / Passwort-Policy** für Login
2. **Passwort-Reset** + Session-Invalidierung
3. **Tenant-/User-Verwaltung per API** (Admin-Routen)
4. **Prod-pytest-Cleanup** — optional Seed für `*@example.com` auch in Prod
5. **Frontend** — produktive Shell statt Debug-JSON (UX, AP0.3+)
---
## 11. Empfehlung AP0.3
Gemäß Foundation-Dokument:
- **Capability / Rights Registry** (DB + Runtime-Sync)
- **`require_capability()`** als FastAPI-Dependency
- **TenantContext** um `capabilities: list[str]` erweitern
- Keine Feature-Limits / Billing in Sprint 0
---
## 12. Referenzen
- Assignment-Kontext: `docs/sprints/Jinkendo_Kairo_04_Sprint0_Foundation_v0.3.md` § AP0.2
- Vorgänger: `docs/sprints/Sprint0_AP0_1_Completion_Report_v0.1.md`
- Migrationen/Seeds: `docs/MIGRATIONS.md`
- Deployment: `docs/DEPLOYMENT.md`
---
*Abgeschlossen im Rahmen Sprint 0 – AP0.2. Ersetzt `Sprint0_AP0_2_Completion_Report_v0.1.md`.*