Kanonisches Home für FastAPI-Struktur, Router-Schnitt und API-Vertrag. Mitai-Referenz: `.claude/rules/ARCHITECTURE.md` §1, `backend/main.py`, `backend/routers/`.
## 1. Prinzipien
Herkunft: Mitai-Architekturregeln, als Rahmen übernommen.
### 1.1 Ein Modul = ein Router
Jedes fachliche Modul besitzt genau eine Router-Datei unter `backend/routers/`. Endpoints liegen nicht in `main.py` außer Health/Status.
Neue Module = neue Datei, Registrierung via `app.include_router(..., prefix="/api")`.
Rahmen-Module (erste erwartbare Dateien, keine vollständige Liste):
Domänenrouter für Mitai-Tracking werden nicht angelegt.
### 1.2 API-First
Jede vom UI benötigte Funktion ist zuerst ein Endpoint. Das Frontend spricht ausschließlich diese API (Mitai: `utils/api.js`). Keine fachliche Berechnung, kein Context-Building und kein Privacy-Demasking im Browser.
Keine parallelen Formate (`error`, `success: false`). Herkunft: Mitai.
### 1.4 Auth an der Grenze
Geschützte Routen nutzen `Depends(require_auth)` bzw. `require_admin`. Ressourcenfilter immer über Session-`profile_id`. Siehe `auth_identity_and_roles.md`.
## 2. Schichten im Backend
Bevorzugte innere Trennung, analog Mitai plus Kanshō-spezifische Gateway-Schicht:
**Status: bevorzugte Richtung** für Ordnernamen. Kein Zwang, Mitai-Dateibaum 1:1 zu klonen, wenn die Trennlinie Router / Gateway / Persistenz klar bleibt.
Privacy Gateway darf nicht umgangen werden, indem ein Router den Provider direkt aufruft. KI-Ausführung nur über die Prompt-Engine (`platform_extensibility.md`), Callback = Gateway.
## 3. Versionierung
Mitai führt `backend/version.py` mit `APP_VERSION` und `MODULE_VERSIONS`.
- Generate: `POST /days/{id}/generate` nur explizit; optionale `conversation_ids`; `include_existing` nur nach ausdrücklicher UI-Auswahl; ohne Auswahl kein stilles Mergen; optionaler `generation_policy`-Snapshot und `remember_generation_policy`
- Generation Policy: `GET /generation-settings` — profilbezogene Defaults der vier Journal-Ausgabeeinstellungen, nicht Writing Profile. Die Anweisungstexte kommen aus `generation_instruction_fragments`, nicht aus dem Nutzerregler.
- **Additiv 2026-08-27:** Generate sendet `generation_selection` (`transformation_id`, `detail_id`, `voice_id`, `narrative_id`) und `remember_generation_selection` (Default false). `GET /generation-settings` liefert `selection`, aktive `options` ohne Promptanweisung und System-`defaults`. Unbekannte oder nicht aktive IDs: 400 `invalid_generation_selection`. Der gespeicherte Entwurf enthält `generation_snapshot` und `generation_summary`.
- **Additiv 2026-08-29:** Voice-Ausprägungen tragen `style_context` (`include_core`, `include_facet`, `include_traits`, `include_style_examples`). `GET /generation-settings` liefert diese Flags an den Journal-Tag, ohne Promptanweisung. Admin `PUT/POST` versioniert Anweisung und Stilkontext gemeinsam. Kein zusätzlicher Generate-Parameter.
- **Additiv 2026-08-29:** Snapshot und Trace führen `cloned_from` der Voice-Ausprägung. Legacy-Vergleichs-IDs sind normale aktive Optionen, nicht Default.
-`POST /api/admin/generation-instructions/{purpose}/preview` — lokal, kein Provider, keine persönlichen Quellen
**Additiv 2026-08-27 (benannte Ausprägungen):** Der numerische Katalog-PUT entfällt. Übersicht ohne Promptkörper. Detail, Klon, Draft-Update, Veröffentlichen, Archivieren, Standard und Löschen nur für unverwendete Drafts:
-`GET /api/admin/generation-instructions/{purpose}` — Kartenfelder, keine Anweisungstexte
-`PUT /api/admin/generation-instructions/{purpose}/{id}` — nur Draft
-`POST .../{id}/clone|publish|archive|default`
-`DELETE .../{id}` — nur ungenutzter Draft
-`POST .../reset` — neue Seed-Drafts, keine Überschreibung historischer Varianten
-`POST .../preview` — lokal gerenderter Prompt, Dummy-Kontext, kein Provider
UI: `/admin/generation` mit getrennten Dimensionen, Karten und einem Editor nach „Öffnen“. Source Modes eigener Abschnitt. Keine Seed-Dateipfade in der normalen Adminbeschreibung.
**Additiv 2026-08-27 (kein Source Mode):** Preview und Admin-UI verwalten nur die vier Gestaltungsdimensionen. `source_mode` ist kein Request-Feld mehr. Ein Custom-Prompt mit veraltetem Platzhalter: 409 `prompt_contract_incompatible`, kein Provideraufruf, kein Draft.
- Entries: `POST /entries`, `GET /entries/{id}`, Versionen, Versions-Restore, Soft-Delete, `POST /entries/{id}/undelete`, `POST /entries/{id}/purge`. Speichern aus einem Entwurf mit `entry_id` + `origin=accepted_draft` legt eine neue Version desselben Entry an.
- Writing Profile: `GET /writing-profile`, Import (optional `occurred_at`, `context_hint`), Korpus `GET/POST /writing-profile/corpus`, Rebuild, `PATCH` Governance, Facet-Edit/Lock, Trait-Edit `PATCH /writing-profile/traits/{slug}`, Vorschläge annehmen/verwerfen. Brief ist eine abgeleitete Sicht aus Traits und zeitgestempelten Quellen. Media-Token werden vor dem Brief entfernt. JSON-Export/Restore: `GET /writing-profile/export`, `POST /writing-profile/restore`. Review: `GET /writing-profile/review`, `POST /writing-profile/review/paste`, `POST /writing-profile/review/api`, `POST /writing-profile/review/import`, `POST /writing-profile/review/accept`, `POST /writing-profile/review/reject`. Initial Build: `POST /writing-profile/initial-build/paste`, `POST /writing-profile/initial-build/api`. API und Copy/Paste nutzen denselben Vertrag `kansho.profile_analysis_package` / `kansho.profile_analysis_result` (`mode` `initial_build`\|`review`, `corpus`, `existing_before_new`, `expected_result`). Legacy-`kind` `kansho.profile_review_*` bleibt lesbar. Import erzeugt ein Proposal, kein Current Profile; Übernahme erst nach Accept. Der Current Brief ist kein Import-/Exportformat. **Additiv 2026-08-29:** Fehler von Review/Initial-Build-API tragen `cost_report` und den Providergrund (`code`, `message`, optional `http_status` / `provider_message`); die generische Client-Meldung „Anfrage fehlgeschlagen“ ist nicht mehr der einzige sichtbare Text.
- Interaction Profile: `GET /interaction-profile`, `PATCH` Governance und Präferenzen, Vorschläge annehmen/verwerfen. Keine Ableitung aus Nicht-Widersprechen. Der Slot liegt unter `/api/journal` nur als Settings-Nachbar, nicht als Journal-Artefakt. JSON-Export/Restore: `GET /interaction-profile/export`, `POST /interaction-profile/restore`.
- Beide Profile: `GET /profiles/export`, `POST /profiles/restore` (`kind: kansho.profiles`). Journal-Backup ist `local_backup.py`, nicht dieser Profil-Export.
`/api/dialogue/*` bleibt Low-Level-Source und Admin-Diagnose, nicht die Produkt-IA. Context Builder und Retrieval liegen nicht im Frontend.
## 5.2 Implementierungsstand (Provider-Admin)
**Status: Code vorhanden.** `GET /api/admin/providers`, `PUT /api/admin/providers/{generate|detect}`. Session-Admin. Body darf einen write-only `key` enthalten; die Antwort enthält ihn nicht. Persistenz: URL/Modell/Flags in `provider_settings`, Key in `backend/.env`.
**Additiv 2026-09-08:** `llm_profiles`. `POST /api/admin/providers/{role}/activate`, CRUD unter `/api/admin/llm-profiles`. Keys weiterhin nicht in der DB.
UI: `/admin/debug` (Baum). Im Dialog bei angeschalteter Persistenz: Gesprächs-JSON. Am Journal-Entwurf: sichtbare Testspur und Entwurf-JSON. Kein Gateway-Bypass. Mapping-Labels nicht in der Payload. Keine Live-Testspur unter der Konversation.