Zum Inhalt

Kora Platform Roadmap

Diese Roadmap beschreibt die Implementierung der kora-Plattform v1.0.0. Sie ist ein Plan, kein Vertrag — Scope und Reihenfolge werden bei Bedarf angepasst, Änderungen werden im Abschnitt Änderungen an dieser Roadmap dokumentiert.

Stand: 11. Mai 2026 (Plan-Phase abgeschlossen)

Aktuelle Phase: Plan-Phase final mit Konsolidierungs-Roadmap ✅ (methodik/konsolidierungs-roadmap.md) — Drei-Track-Synthese (Customer-Handbuch + SaaS-Foundation + Operational), Karten-Sequenz für nächste 3–6 Monate dokumentiert, Tudidi-Format-Konvention etabliert, Backlog-Triage-Hochstufungen vorbereitet. Saga-Lehre 13 zum 10. Mal validiert. Plan-Phase-Bilanz: 7 Karten / ~13h Wall-Clock — Karte B Backlog ✅, Block-19 Tag-7 ✅, Doc-Upload-Saga ✅ (Pre-Flight + A1 + A2), Karte C Customer-Handbuch ✅, Karte D Konsolidierungs-Roadmap ✅ Abgeschlossen: Block 1–8 ✅, Block 11 ✅, Block 8.5 Pfad C ✅ (Doc-Upload Backend + UI), v1.3.0-Welle ✅, Defense-in-Depth-Saga ✅, Pre-Existing-Drift-CleanupTags: v1.0.0 (2026-04-29), v1.1.0 (2026-04-30), v1.2.0 (2026-05-01), v1.3.0 (2026-05-02), pentest-suite-v1.0 (2026-05-08) Nächste Karte: C-1 Endnutzer-Section befüllen (~12–20h, 🔴 höchste Customer-Sichtbarkeit). Drei-Track-Sequenz: ~25 Karten / ~180–300h bis v1.0.0-Launch (siehe Konsolidierungs-Roadmap). Version: platform/v1.0.0 (Plan-Phase abgeschlossen, Umsetzungs-Phase beginnt)

Fortschritt v1.0.0

Erledigt: Block 1 (28h real) + Block 2 (20h real) + Block 3 (~7h real; 12h geplant) + Block 4 (~32h real) + Block 5 (~28h real inkl. 7a-Scaffolding + TODO-4c) + Block 6 (~10h real; 10-12h geplant) + Block 7.1a (~6h real) + Block 7.1b (~9h real) + Block 7.2 (~4h real) + Block 7.3 (~4h real; Modules-Registry + Per-Tenant-Toggle Frontend-only) + Block 7.4 (~6h real; Audit-Reader + Bulk-Ops Backend & Frontend + Connectors-Stub) + Block 8 (~30.5h real; 50-64h refined, 60 % Quote) + Block 11 (~5-6h real; 14h refined, 40 % Quote — TODO-Platform-15 + TODO-Block-7-4-04-Anteil mitbedient) + v1.3.0-Welle (~13h real; 42.5–44.5h refined, ~30 % Quote — D2 + D1 + E) = ~203h von ~427h (~48 %). v1.3.0 getaggt am 2026-05-02 — siehe Release-Notes und Akzeptanz-Matrix. Phase A (Fundament) ist mit Block-5-Merge (2a3e5b0) am 2026-04-24 abgeschlossen; Block 7 ist mit dem 7.4-Merge vollständig abgeschlossen (vier Sub-Commits: 7.1a Backend, 7.1b Frontend-Scaffolding + Tenants-UI, 7.2 Templates-UI, 7.3 Modules-Registry + Paket-Editor, 7.4 Audit-UI + Bulk-Ops + Connectors-Stub). Nach der Roadmap-Umnummerierung vom 2026-04-23 ist der hier als "Block 6" geführte Plattform-Module-Eintrag identisch mit dem historisch als "Block 5" dokumentierten Merge (c858402).

Der Gesamt-Aufwand ist durch die v5.2-Quality-Einschübe (§6a, §13.3a) von ~384h auf ~449h gestiegen (+65h: Block 18 ~18h, Block 19 ~25h, Block 20 ~13h, Block 13 +9h für Merkle-Sync). Die prozentuale Abnahme von ~25 % auf ~22 % war rechnerische Konsequenz der Nenner-Erweiterung — keine Regression der erledigten Arbeit.

Das v1.0.0-Budget ist durch die v5.3.1-MediaWiki-Verschiebung (Konnektor-Roadmap §2.3, Konzept §13.6) von ~449h auf ~425h reduziert; per v5.3.3-Block-11-Refinement (TODO-Konzept-01-Auflösung, 2026-05-01) auf ~427h justiert (+2h Block 11 von 12h auf 14h Refined). Die prozentuale Zunahme (~22 % → ~23 % → ~29 %) setzt sich aus der Nenner-Reduktion und dem Block-5-Gewinn zusammen.

Phase-A-Restaufwand: 0h — Phase A komplett. Block P1 (Speculative Decoding) läuft als Performance-Track parallel zu Phase B, nicht blocking.

Kernfunde aus Block 2+3 sind in offene-todos.md dokumentiert. Nach Cleanup-02 ist nur noch TODO-B2-03 (Keycloak-Service-Account statt Master-Password) offen — Rest abgearbeitet.

Zwischenstand-Aufräumen

Zwischen Block 3 und dem Start von Block 4 liefen drei Aufräum-Runden, um aufgestaute Deferred-Items aus den Code-Reviews der vorherigen Blöcke zu bereinigen. Jede Runde ist ein eigener Merge auf platform/v1.0.0:

  • Pre-Block-4-Cleanup (Merge da461d6, 21.04.) — 7 TODOs + L-B3-01: Correlation-ID-Middleware, Redis-Pool in app.state, TENANT_ROLES- Gate, ContextVar-Reset im Vendor-Pfad, Realm-JSON-Mapper, refreshTokenMaxReuse für Tenants-Realm, Makefile-Health-Loop.
  • mkdocs-Hygiene (Merge 6e43f71, 21.04.) — Config-Layout und Bind-Mount-Problem: mkdocs-kora.yml nach docs-kora/mkdocs.yml, Content nach docs-kora/docs/, Single-File-Bind-Mount eliminiert. /todo/-URL auf /offene-todos/ umgestellt. Deployment-Ergonomie: docker restart reicht jetzt statt --force-recreate.
  • Cleanup-02 (Merge 610f459, 21.04.) — 5 weitere TODOs: vendor_access_log.action VARCHAR(64) → TEXT (Alembic 0004), Audit-Poller-Pagination mit MAX_PAGES=50, Redis-Cursor-Key avs:kora: (idempotente Startup-Migration), URL-Settings als AnyHttpUrl, /metrics IP-Allowlist via FastAPI-Dependency.
  • Block-4-+-Block-6-Merges (Merges f21c030, 90e96f8, c858402, 22.–23.04.) — Block 4 (Qdrant Collection-per-Chatbot + Shared, ~32h real) mit QdrantManager, Fan-Out-Retrieval, Soft-Delete-Lifecycle und Cross-Tenant-Isolation-Tests (200×/0- Stress-Test). Phase-D.1-Nachzug (90e96f8): uses_shared_docs-Gate auf Chatbot-Ebene laut Fundament §6.2. Block 6 (Plattform-Module & einstufige Freischaltung, ~10h real; vor der Umnummerierung vom 23.04. als "Block 5" geführt) mit ModuleService plus platform_modules/tenant_modules-Schema (Alembic 0006). Struktur-Sync-Merge 97ae387 (23.04.) richtete danach die Block-Nummerierung 1:1 auf Konzept §17.2 aus.

Architektur-Grundsatz: v1.0.0 ist ein Monolith mit embedded Vue-Komponenten — ein Container-Image liefert FastAPI + Jinja2 + Vue-Bundles. Details siehe Fundament §9.3.

Methodik

  • Zielversion: v1.0.0 — das produktive Multi-Tenancy-Fundament.
  • Phasen: A (Fundament), B (UIs & Automation), C (Konnektoren & Templates), D (Deployment, Migration & Go-Live), E (Post-Launch). Jede Phase ist in Blöcke aufgeteilt. Phase E startet nach dem v1.0.0-Release (v1.0.1 / v1.1.0).
  • Blöcke: ein Block = 1–5 Commits auf platform/v1.0.0. Größere Blöcke werden in Teilblöcke (1.1, 1.2, …) zerlegt.
  • Eintrags-Struktur: jeder Block hat Warum (Motivation), Ansatz (Architektur-Entscheidungen), Komponenten (konkrete Artefakte), optional Offene Fragen und Verweise. Phase-B/C/D-Themen nutzen Scope statt Komponenten.
  • Status-Pflege: nach jedem abgeschlossenen Block wird diese Datei im selben Commit aktualisiert — Status-Emoji + Commit-Hash. Plan und Implementierung bleiben so im Gleichschritt.
  • Verhältnis zur AVS-Roadmap: Die AVS-Roadmap dokumentiert die Demo-Evolution (v0.x-Reihe des avs-chatbot-Repos). Diese Roadmap dokumentiert die Plattform-Evolution (v1.0+). Die Grenze liegt beim v1.0.0-Release — ab dann läuft die Plattform produktiv bei AVS, die Demo wird 7 Tage beobachtet und dann abgeschaltet.

Status-Legende

Emoji Bedeutung
Erledigt — committed, getestet, merged
🚧 In Arbeit — aktiv bearbeitet
Geplant — nächste Schritte, konkreter Scope
📋 Scoping — Phase definiert, Blöcke noch nicht im Detail geplant
🔒 Blockiert — wartet auf externe Voraussetzung
💭 Backlog — perspektivisch, kein Zeitplan

Defense-in-Depth-Saga ✅

Status: abgeschlossen 2026-05-08, ~52h Wall-Clock, 13 Karten, 13 Saga-Lehren. Aus dem ursprünglichen v1.0.0-Scope herausgelöst und –64 % unter Schätzung umgesetzt. Detail-Bilanz mit Karten-Tabelle und Pen-Test-Bilanz im Audit-Trail; Architektur in architektur/sicherheit/defense-in-depth.md; Methodik in methodik/saga-lehren.md.


Phase A — Fundament

Das technische Rückgrat der Plattform: Datenmodell, API-Skelett, SSO-Integration, Qdrant-Mandanten-Isolation. Ohne dass Phase A abgeschlossen ist, kann weder Operator-UI (B) noch Konnektor-Arbeit (C) sinnvoll beginnen. Parallel dazu läuft der Performance-Track (Block P1, Speculative Decoding), der nicht am Multi-Tenancy-Stack hängt.

Block 1 — Tenant-Datenmodell ✅ Erledigt

Zielversion: v1.0.0 Aufwand: ~28h geschätzt (Konzept §17.2), deutlich darunter tatsächlich Abhängigkeiten: keine (Fundament)

Warum

Dreischichtiger Schutz ist DSGVO-kritisch: der Application-Layer kann Bugs enthalten, Trigger schützen beim Schreiben, RLS schützt beim Lesen. Ohne diese Redundanz kann ein einziger Middleware-Bug dazu führen, dass Tenant A Daten von Tenant B sieht. Die Aufgabe beim AVV zwischen luki und AVS ist explizit, die Tenant-Grenze technisch hart zu machen — nicht nur als "wir haben da Code, der das prüft".

Das Datenmodell ist das Fundament, auf dem alles andere (API, UI, Konnektoren) aufbaut. Wenn hier Schemata später geändert werden müssen, sind alle abhängigen Schichten betroffen — also lieber jetzt ein paar Wochen in das Schema stecken als später in Panik migrieren. Der Audit-Trail (vendor_access_log + platform_audit_log) ist außerdem AVV-Pflicht.

Ansatz

Fünf Teilblöcke mit klarer Trennung: erst SQL-Draft gegen eine echte Platform-Postgres laufen lassen (1.1), dann Alembic drumherum bauen (1.2), dann die Models ableiten (1.3), dann DB-Seite-Sicherheit (1.4+1.5). So ist jeder Schritt einzeln verifizierbar, statt ein großes "hoffentlich funktioniert's"-Paket zu committen.

Alembic bekommt einen eigenen Branch (alembic.ini.platform, alembic/platform/), isoliert vom Demo-Alembic. Drei PostgreSQL-Rollen: Migrator (BYPASSRLS für DDL), App (RLS-enforced für Laufzeit), Vendor (BYPASSRLS für Support, mit App-Level-Audit). Auf allen RLS-Policies WITH CHECK, nicht nur USING — sonst lässt RLS Cross-Tenant-INSERTs durch (das hat ein Test im Block 1.5 explizit gezeigt).

Komponenten

  • alembic/platform/ mit eigenständigem env.py und drei Revisionen: 0001_initial_schema, 0002_triggers, 0003_rls
  • src/kora_platform/db/ — neuer Python-Package-Tree mit Base, SessionLocal, 18 Models (aufgeteilt in 5 Domain-Dateien: tenant, chatbot, connector, operational, audit)
  • PostgreSQL-Trigger: 3 für updated_at-Automatik (trigger_set_updated_at) und 7 für tenant_id-Konsistenz (trigger_check_tenant_id_via_chatbot/_via_source)
  • RLS-Policies auf 13 Tabellen mit USING + WITH CHECK gegen current_setting('app.current_tenant_id', true)::uuid
  • Makefile-Targets für Platform-Alembic: migrate-platform, -down, -status, -new, -history
  • .env.platform.example um die drei neuen Rollen-Passwörter erweitert, mit Placeholder-Validation in der 0003-Migration

Verweise


Block 2 — Keycloak Dual-Realm + FastAPI-Skelett ✅ Erledigt

Zielversion: v1.0.0 Aufwand: ~20h (16h Keycloak + 4h FastAPI-Skelett aus Block 3 vorgezogen) Abhängigkeiten: Block 1

Warum

JWT-basierte Authentifizierung ist Voraussetzung für Tenant-Resolution (Block 3). Ohne Keycloak-Realms kann die App nicht wissen, zu welchem Tenant ein Request gehört. Konzept §2 definiert die Drei-Schichten-Rollen (Vendor/Operator/Tenant) — diese müssen in Keycloak als Realm-Rollen existieren, damit JWTs sie tragen können.

Parallel dazu braucht der Audit-Poller (Konzept §15.4) eine FastAPI-Lifespan, und die Bootstrap-CLI braucht Settings- und DB-Zugang. Statt einen separaten Docker-Service nur für den Poller aufzusetzen, wurde das minimale FastAPI-Skelett aus Block 3 vorgezogen. Block 3 wird dafür um 4h entlastet.

Ansatz

Zwei Realms in kora-platform-keycloak: kora-platform für Vendor-/Operator-Rollen, kora-tenants für Tenant-User. Separate Realms, weil die Rollen-Hierarchien unterschiedlich sind und die Token-Signatur-Domains sauber getrennt bleiben sollen. Drei Clients im Platform-Realm (kora-api, kora-api-vendor-breakglass, kora-api-vendor-tunnel — letzte beide mit 2h Client-Session-Max). First-Broker-Login-Flow "Create User If Unique" als REQUIRED-Step im Tenants-Realm — verhindert Cross-Tenant-Account-Linking bei späterer IdP-Föderation (Block 17).

FastAPI-Skelett minimal: /health/live + /health/ready, Audit-Poller als Lifespan-Background-Task, structlog-JSON-Logging, async SQLAlchemy-Engine. Keine Business-Endpoints, keine Scope-Middleware — das kommt in Block 3.

MailHog als Dev-SMTP im kora-platform-net (SMTP intern, Web-UI auf 8239; Port 8237 ist für kora-platform-mkdocs belegt).

Komponenten

  • infra/keycloak/realms/kora-platform-realm.json — 6 Realm-Rollen, 3 Clients, 3 disabled Vendor-Users, smtpServer-Block auf MailHog
  • infra/keycloak/realms/kora-tenants-realm.json — 3 Realm-Rollen, 1 Client, First-Broker-Login-Flow "kora-tenants first broker login", Default-Rolle tenant-viewer via Composite
  • infra/keycloak/patch-dev-redirects.sh — fügt Localhost-Redirects für Dev-Work ein, ohne die Produktions-Config anzufassen
  • src/kora_platform/main.py — FastAPI-Lifespan + Exception-Handler
  • src/kora_platform/config.py — Pydantic-Settings mit KORA_ Prefix
  • src/kora_platform/logging_setup.py — structlog JSON
  • src/kora_platform/db/async_session.py — AsyncEngine + get_session
  • src/kora_platform/api/health.py/health/live, /health/ready
  • src/kora_platform/cli/bootstrap.py — CLI-Kommando kora-platform bootstrap-operator-admin --email <mail>
  • src/kora_platform/services/audit_poller.pyIdpAuditPoller (60s-Polling, Redis-Cursor)
  • docker-compose.platform.yml — Services api (Port 8280) + mailhog, Keycloak-ENV-Migration auf KC_BOOTSTRAP_ADMIN_* und KC_DB_*
  • infra/docker/Dockerfile.platform — Multi-Stage Build
  • scripts/smoke-block2.sh — 30 Smoke-Tests (alle grün)
  • docs-kora/deployment/npmplus-auth-subdomain.md — Runbook auth.kora.luki-net.org

Verweise


Block 3 — API Scope-Middleware ✅ Erledigt

Zielversion: v1.0.0 Aufwand geplant: ~12h (reduziert von 16h Konzept §17.2: −4h für das in Block 2 vorgezogene FastAPI-Skelett) Aufwand real: ~7h. Die 5h Unterlauf kamen aus dem klaren Design der vorangegangenen Blöcke (Keycloak-Realms, Audience/Issuer/ Group-Claim-Format fest definiert) und der Wiederverwendung der kora_platform_vendor-Rolle aus Block 1.5 (keine neue Alembic- Migration nötig). Commit: d18a1fcMerge: f558a38 Benchmark-Vorbereitung: 4eb764f (Session-Pool-Benchmark, Scenario A bestätigt: Shared Pool + SET LOCAL, 25× Throughput gegenüber Fresh- Engine-per-Request bei C=100) — Merge: 8439210 Nachbereitung: Pre-Block-4-Cleanup (da461d6) + Cleanup-02 (610f459) haben die Block-3-Review-Findings systematisch abgearbeitet — Details im Abschnitt Zwischenstand-Aufräumen. Abhängigkeiten: Block 2 ✅

Warum

Das ist das Herzstück der Multi-Tenant-Absicherung. Jeder API-Request muss den Tenant aus dem JWT ableiten, den Postgres-Session-Context via SET LOCAL app.current_tenant_id setzen, und danach darauf vertrauen, dass RLS den Rest erledigt. Ohne diese Middleware ist die gesamte Block-1-Arbeit nutzlos — RLS würde zwar greifen, aber mangels app.current_tenant_id alle Rows ausfiltern (Hard-Fail-Closed, aber nicht nutzbar).

Ansatz

FastAPI-Dependency, die aus dem JWT-Header den tenant_id-Claim zieht (RS256-Signatur gegen Keycloak-Public-Key validiert). Python-ContextVar speichert den Tenant für die Request-Dauer. Die DB-Session-Factory ruft SET LOCAL app.current_tenant_id = :tenant_id vor dem ersten Statement — pro Request, nicht pro Session, wegen Connection-Pool.

Fail-Safe-Verhalten: kein JWT → HTTP 401, kein Tenant-Claim → HTTP 403, Tenant existiert nicht → HTTP 404. Keine Fallbacks, keine Defaults — lieber restriktiv als permissiv.

src/kora_platform/db/session.py wechselt endgültig von Superuser auf kora_platform_app-Rolle. Der bewusste Zwischenzustand aus Block 1.5 wird damit aufgelöst. Ab Block 4 greift RLS zur Laufzeit.

Vendor-Rollen umgehen die Middleware nicht automatisch — auch sie brauchen den Tenant-Context für tenant-scopierte Endpoints. Ein bypass_rls-Claim im JWT (signiert von Keycloak) oder eine separate Keycloak-Client-Rolle schaltet die alternative Vendor-DB-Rolle frei. Zweites ist sauberer.

Komponenten

  • src/kora_platform/api/dependencies/auth.py — JWT-Validation + Claim-Extraktion, Keycloak-Public-Key-Caching
  • src/kora_platform/api/dependencies/tenant_context.py — ContextVar + Session-Scoping
  • src/kora_platform/db/session.py — Update auf kora_platform_app-Rolle
  • SET-LOCAL-Mechanismus vor jedem Statement
  • Unit-Tests: JWT-Validierung (gültig/abgelaufen/falsche Signatur)
  • Smoke-Tests: kein JWT → 401, JWT mit fremdem Tenant → 404, JWT mit richtigem Tenant → 200 mit gefilterten Daten
  • Integrations-Test: zwei Tenants parallel schreiben und lesen, keine Cross-Contamination

Offene Fragen

  • Vendor-Breakglass-Erkennung: Claim im JWT vs. separate Keycloak-Rolle mit eigener DB-Rolle. Aktuelles Standing: separate Rolle (cleaner Audit).
  • Connection-Pool vs. Connection-per-Request: Pool mit SET LOCAL ist Standard, aber braucht Care dass SET LOCAL wirklich per Transaction gilt und nicht leakt. Performance-Impact zu messen, falls Alternative ohne Pool nötig wird.

Block 4 — Qdrant Collection-per-Chatbot + Shared ✅ Erledigt

Zielversion: v1.0.0 Aufwand geplant: ~32h (Konzept §17.2 nennt 28h; Real-Implementation inkl. Phase-D.1-Nachzug bei ~32h) Aufwand real: ~32h Merge: f21c030 (Block 4 Qdrant Collection-per-Chatbot + Shared) Phase-D.1 uses_shared_docs-Gate: 90e96f8 — schloss die Kategorie-C-Lücke aus dem Roadmap-Check vom 22.04. (Chatbot-Level-Gate laut Konzept §6.2). Das Template-Level-Gate ist als TODO-Block-4c deferred auf Block 5 (Chatbot-Templates & CRUD). Abhängigkeiten: Block 3 ✅

Warum

DSGVO-Anforderung aus §6 des Fundament-Konzepts. PostgreSQL-RLS schützt relationale Daten, aber die Vektor-Embeddings liegen in Qdrant. Wenn alle Tenants in einer einzigen Collection liegen und der Retriever nur über Metadaten-Filter scopt, ist eine Metadaten-Bug-Klasse gefährlich (ein falsches Filter-Object → Cross-Tenant-Leak). Eine Collection pro Chatbot ist architektonisch narrensicher — es gibt keinen gemeinsamen Datensatz mehr, aus dem versehentlich zu viel zurückkommt.

Ansatz

Naming-Konvention aus §6.1: chatbot_<uuid> für Chatbot-spezifische Collections, shared_<template>_<topic> für AVS-gepflegte Shared- Handbücher (auf die Tenants gemäß chatbots.uses_shared_docs zugreifen können).

Automatische Collection-Erstellung beim Chatbot-Provisioning (§14.2), atomar mit der DB-Transaktion oder mit Cleanup-Handler bei Fehlschlag. Lifecycle-Hook beim Tenant-Soft-Delete: Collection wird pausiert (kein Write), aber erst nach der 30-Tage-Grace-Frist aus §14.4 gelöscht.

Fan-Out-Retrieval für Chatbots mit uses_shared_docs=true: Query läuft parallel gegen die chatbot-eigene Collection plus alle Template-Shared-Collections, Ergebnisse werden zusammengeführt und re-ranked. Das ist teurer als Single-Collection-Query, aber notwendig für das AVS-Shared-Handbuch-Modell.

Backup-Strategie Hybrid (§6.5): Qdrant-Snapshots für Full-Restore + asynchrone Replik in separates Volume für Point-in-Time-Recovery.

Komponenten

  • src/kora_platform/services/qdrant_manager.py — Collection-CRUD mit Idempotenz, Naming-Konvention-Enforcement, Lifecycle-Hooks
  • src/kora_platform/services/retrieval.py — Fan-Out-Logik mit Re-Ranking
  • Unit-Tests: Collection-Erstellung (idempotent), Collection-Löschung (nach Grace), Fan-Out mit zwei Collections
  • Integrations-Test: Tenant A legt Chatbot an, lädt Dokument hoch, findet es wieder; Tenant B findet dasselbe Dokument nicht (Isolation gegen Qdrant-Collection-Ebene bestätigt)
  • Runbook: deployment/qdrant-collections.md — Collection-CRUD, Backup, Restore

Offene Fragen

  • Skalierung bis 50 Tenants: Qdrant-Collection-Overhead ist bei sehr hoher Anzahl nicht null. Ab ~50–100 Tenants wird laut §6.4 ein Hybrid-Modell (Shared Collection + Metadaten-Filter zusätzlich zu Per-Chatbot-Collection) nötig. Für v1.0.0 nicht relevant.
  • Performance-Impact von Qdrant-Snapshots auf der laufenden Produktiv-Instanz: messen, ob Snapshot-Zeiten akzeptabel sind oder ein Secondary-Node für Backup-Offloading gebraucht wird.

Block 5 — Chatbot-Templates & CRUD ✅ Erledigt

Zielversion: v1.0.0 Aufwand geplant: ~28h (16h Block-5-Content + ~12h vorgezogenes 7a UI-Framework-Scaffolding aus Block 7, Konzept §17.2 v5.3) Aufwand real: ~28–30h über vier Sub-Commits + TODO-4c-Auflösung Merge: 2a3e5b0 auf platform/v1.0.0 Sub-Commits:

  • 7753067 — Sub-Commit 1: 7a UI-Framework-Scaffolding (Vue 3 + Vite + Auth-PKCE + BaseLayout + Dockerfile Multi-Stage + Keycloak-tenant-ui-Public-Client)
  • f09b8ef — Sub-Commit 2: Backend (Alembic 0007, ChatbotTemplateService mit Option-B-Versioning, 5 REST-Routes, Keycloak-Seed-Script, 14 Unit-Tests)
  • 85203db — Sub-Commit 3: UI-Content (ChatbotDetailPage, TemplateUpdateBanner, TemplateUpdateDialog), Template-Apply-POST-Endpoint (Option Y, atomar), Template-Seed-Script, 8 Vitest-Component-Tests, Playwright-Scaffold
  • c898d85 — Sub-Commit 4: TODO-Block-4c-Auflösung (PlatformRetrieval Zwei-Stufen-Gate nach §6.2, 3 neue Unit-Tests, Integration-Test-Fixture-Anpassung) Liefert als Nebeneffekt: 7a UI-Framework-Scaffolding (Vue-3-Build-System, Auth-Middleware-Integration, Base-Layout) für Block 7 + 8 (siehe Konzept §9.3 v5.3 und §17.2 v5.3). Abhängigkeiten: Block 1 (chatbot_templates-Tabelle im Datenmodell) ✅

Warum

AVS kuratiert die Plattform-Templates (Meldeschein, Kurverwaltung, weitere Kundenkategorien). Ohne CRUD-UI müssten Templates per SQL gepflegt werden — fehleranfällig, nicht revisionsfähig, und der Chatbot-Wizard aus §14.2 (Umsetzung in Block 8) lässt sich ohne pflegbare Templates nicht sinnvoll bauen.

Snapshot-Versionierung (§5.2) ist kein Nice-to-have: ein Tenant darf nicht überraschend einen geänderten System-Prompt bekommen, nur weil AVS das Template weiterentwickelt hat. Der Snapshot-Marker template_version_at_creation auf chatbots ist der Schutzschirm.

Ansatz

CRUD auf chatbot_templates mit sichtbarem version-Feld (Semver). Beim Chatbot-Create wird der aktuelle Template-Snapshot eingefroren (template_version_at_creation). Ein "Template-Update verfügbar"- Hinweis im Tenant-UI (Umsetzung in Block 8) macht die Drift sichtbar; Bulk-Migration auf eine neuere Template-Version ist ein explizites Tenant-Admin-Kommando.

Evaluation-Questions werden auf Template-Ebene gepflegt (§5.4) — 20+ DE-Fragen pro Template, die als Regression-Set nach jedem System-Prompt-Update durchlaufen werden können.

Komponenten

  • src/kora_platform/services/template_service.py — CRUD-Service mit Semver-Versionierung
  • REST-API GET/POST/PATCH/DELETE /api/v1/platform/templates (Operator-Scope); Tenant-Endpoint GET /api/v1/tenants/{id}/templates (read-only)
  • Alembic-Migration, falls Schema-Ergänzungen (z.B. template_version_at_creation-Spalte auf chatbots) nötig
  • Unit-Tests für Snapshot-Logik und Version-Bump-Regeln

Zusätzlich (7a UI-Framework-Scaffolding, ~12h):

  • Vue-3-Build-System-Setup (infra/docker/Dockerfile.platform Node-Stage, Vite-Build-Pipeline, Bundle-Assets)
  • Auth-Middleware-Integration ins Frontend (JWT-Context aus Keycloak, Route-Guards)
  • Base-Layout und Router-Skelett für Tenant-UI (wird von Block 8 ausgebaut, von Block 7 via Operator-UI-Branch wiederverwendet)

Siehe Konzept §9.3 (Container-Strategie) und §17.2 v5.3 (Block-5- Erweiterung um 7a-Scope als Block-7-Split-Konsequenz).

Verweise


Block 6 — Plattform-Module & einstufige Freischaltung ✅ Erledigt

Zielversion: v1.0.0 Aufwand: ~10h real (10-12h geplant) Abhängigkeiten: Block 1 (tenants, platform_audit_log), Block 3 (TenantContext, app/vendor-Engines) Commits: 1eacd12 (Schema), 58c20a2 (Service+Tests), 9dcc05b (Routes+Audit+Smoke), 6831d3a (RLS-Tests)

Zusammenfassung

Einstufiges Modul-Freischaltungs-Modell nach Fundament §8 (Konzept v5.1). Kein globaler Enable-Schritt, keine UI (Block 6), kein Lizenz-Gating (v5 §7). Datenebene + Service + Routes + Audit.

Schema (Alembic 0006):

  • platform_modules: id VARCHAR(64) PK (Slug), name, version, config_schema (nullable JSONB), scope, is_always_on. CHECK core_is_always_on + Scope-Enum. Kein RLS (plattformweit).
  • tenant_modules: Composite-PK (tenant_id, module_id), is_enabled, enabled_at, enabled_by (nullable). RLS FORCE + Policy tenant_isolation_tenant_modules auf kora_platform_app.

Service (services/module_service.py):

  • 6 Methoden: register_platform_module, list_platform_modules, list_tenant_modules, assign_to_tenant, revoke_from_tenant, is_module_enabled.
  • is_module_enabled als zentrale Gate-Funktion — eine SQL-Query mit EXISTS-JOIN über platform_modules × tenant_modules.
  • ModuleNotAssignable (core/internal_only), ModuleNotFound.
  • Idempotenter Assign (re-assign aktualisiert enabled_by), idempotenter Revoke (kein Fehler bei nicht-existierender Row).

API-Routen:

  • GET /api/v1/platform/modules — Operator sieht 3 (ohne internal_only), Vendor sieht 4.
  • GET /api/v1/tenants/{id}/modules — Operator/Vendor alle, Tenant nur eigener.
  • POST /api/v1/tenants/{id}/modules — Operator zuweist, 201 bei Erfolg, 400 bei core/internal_only, 404 bei Typo.
  • DELETE /api/v1/tenants/{id}/modules/{module_id} — Operator entzieht, 204.
  • Inline-Scope-Checks (kein separater Dependency-Refactor).

Audit (routes/_module_audit.py): mapped auf existierendes platform_audit_log-Schema (action, actor_keycloak_id, actor_role, actor_user, entity_type, entity_id, tenant_id, details JSONB). actor_keycloak_id toleriert non-UUID-Subjects (Service-Accounts → NULL). Audit-Fail = HTTP 503 mit Rollback (Block-3-Pattern).

Datenmodell-Abweichung: Konzept §8.1 spezifiziert tenant_packages.enabled_modules JSONB-Array. Block 5 implementiert relational mit eigener tenant_modules-Tabelle — Vorteile: Per-Row-Audit, enabled_by/enabled_at-Granularität, RLS-Policies. Dokumentiert in deployment/platform-modules.md.

Acceptance

  • Smoke scripts/smoke-block5.sh: 7/7 ✓ (Operator-List, Vendor-List, Assign-201, Tenant-Sicht, Cross-Tenant-403, internal_only-400, Audit-Event)
  • Unit-Tests tests/unit/test_module_service.py: 17/17 ✓
  • Integration-Tests RLS tests/integration/test_tenant_modules_isolation.py: 3/3 ✓ (Visibility, Cross-Tenant-Write-Block, BYPASSRLS)

Offen (nach Block 5)

  • internal_only-Assignment-Route (Vendor-Scope mit force=true) — Block 6 oder später, aktuell nicht zuweisbar
  • In-Memory-Cache für is_module_enabled — verschoben auf Block 6 / Performance-Tuning (erst profilieren, dann cachen)
  • Konsolidierung der Dependencies (require_*, AuditLogger-Service) — eigener Cleanup-Block, nicht Block 5

Block P1 — Speculative Decoding (POC + Produktiv-Integration) ⏳ Geplant

Zielversion: v0.9.0 (Demo-Optimierung) + v1.0.0 (Platform, falls bis Go-Live fertig) Aufwand: ~30h (inkl. 8h POC) Abhängigkeiten: keine — läuft parallel zu Blöcken 2-5

Warum

Das Latenz-Profil zeigt 97 % der Query-Zeit in der LLM-Generation. Jede Sekunde, die in RAG-Komponenten-Optimierung investiert wird, adressiert nur 3 % des Problems. Speculative Decoding (SD) adressiert den 97 %-Anteil direkt: mathematisch identische Ausgabe, aber 1.8–2.5 × schneller durch Memory-Bandwidth-Optimierung.

Der Effekt entsteht daher, dass autoregressive Token-Generation memory-bandwidth-gebunden ist: das große Modell muss für jeden Token den kompletten Forward-Pass fahren, wobei das Laden der Gewichte aus dem VRAM dominiert. SD lässt ein kleines Draft-Modell mehrere Tokens vorausraten, das große Target-Modell verifiziert sie in einem einzigen Forward-Pass. Akzeptierte Tokens werden übernommen, abgelehnte Tokens werden vom Target-Modell neu generiert.

Ansatz

Draft-Target-Variante, kein EAGLE — weil für Qwen3-14B-AWQ keine EAGLE-Checkpoints existieren und wir keinen eigenen trainieren wollen.

Topologie: Draft-Modell (Qwen3-1.7B-AWQ-INT4) auf RTX 4090 (luki-ai), Target-Modell (Qwen3-14B-AWQ) auf RTX 5090 (luki-ai-2). Nginx vllm-lb bleibt unverändert — SD ist vLLM-intern, die Draft-Target-Kommunikation läuft zwischen den vLLM-Prozessen, nicht über den Load Balancer.

Thinking-Mode auch im Draft-Modell deaktivieren (alle drei Code-Pfade: stream, non-stream, query-rewrite) — Draft soll fokussiert Tokens raten, nicht reasoning aufbauen.

Prometheus-Histogram pro Stage bleibt bestehen, zusätzliche Metrik avs_spec_decode_acceptance_rate für Tuning.

POC vor Commitment (8h): Qwen3-1.7B + Qwen3-14B-AWQ in Test-Container starten, Acceptance-Rate auf Evaluation-Questions (20 DE) + echten Session-Queries (20) messen. Go/No-Go-Gate: >65 % Acceptance-Rate → weitermachen, <65 % → Qwen3-4B als Draft probieren oder Track aufgeben.

Komponenten

  • vllm-target-Config mit --speculative-config Parameter
  • Neuer vllm-draft-Service in docker-compose.yml (Demo) und docker-compose.platform.yml (Platform)
  • k6-Lasttest mit und ohne SD, Grafana-Panels für Acceptance-Rate + Latency-Delta (p50, p90, p99)
  • Runbook-Ergänzung: Tuning-Prozess, Rollback auf Non-SD-Modus
  • POC-Report als Markdown in docs/entwicklung/ (Demo) bzw. docs-kora/ (Platform)

Offene Fragen

  • Qwen3-1.7B vs. Qwen3-4B als Draft-Modell: welche Balance aus Draft-Geschwindigkeit und Acceptance-Rate? Messung im POC.
  • VRAM-Budget auf der 4090: Draft-Modell + KV-Cache + bestehende Services. Qwen3-1.7B-AWQ-INT4 bei ~1 GB wahrscheinlich unkritisch, aber zu verifizieren.
  • AWQ + SD-Kompatibilität: vLLM unterstützt die Kombination seit v0.6.x, aber Kernel-Backend-Kompatibilität (Marlin vs. GPTQ-Kernel) muss im POC bestätigt werden.
  • Bei v1.0.0 Multi-Tenancy bleibt Draft global (shared) und Target global. Per-Tenant-Target ist v1.3.0+-Thema (Custom-LoRA-Adapter-Modul im Backlog).

Verweise

  • NVIDIA DGX-Spark-Playbook nvidia/speculative-decoding/README.md
  • vLLM-Dokumentation: --speculative-config-Parameter
  • Latenz-Baseline-Metrik: avs_rag_stage_duration_seconds{stage="llm_generation"}
Technische Hinweise (aus NVIDIA-Playbook-Recherche)
  • Topologie: Draft-Target passt zum existing Zwei-Node-Setup — Qwen3-1.7B-Draft auf luki-ai (4090), Qwen3-14B-Target auf 5090-Node. Draft-Last ist gering, 4090-Reserve-Kapazität reicht.
  • Erwartung: 1.8–2.5× Speedup bei Generation-Latenz → aktuelle ~2567 ms Generation-Latenz → ~1100–1400 ms Ziel.
  • vLLM-Flag: --speculative-config (NICHT TensorRT-LLM-Pfad nehmen, obwohl NVIDIA-Playbook das nutzt — vLLM-Native ist seit v0.6.x stabil).
  • Konkrete Config-Felder: decoding_type: Eagle, max_draft_len: 5, free_gpu_memory_fraction: 0.9.
  • POC-Gate-Akzeptanz: >65 % Acceptance-Rate auf DE/EN-Test-Queries bevor ~30h Integration-Investment.

Phase B — UIs & Automation

Phase B baut die drei UIs (Operator, Tenant, Vendor) auf derselben Vue-3-Basis (Composition API ohne Pinia, Fundament §9.1) plus System-Prompt-Automatismus, das Multi-Tenant-Widget und die Provisioning-Automatisierung. Ohne Phase B ist die Plattform technisch funktional, aber ohne bedienbare Oberfläche.

Block 7 — Operator-UI (AVS-Ebene, Content = 7b) ✅ Erledigt

Zielversion: v1.0.0 Aufwand geplant: ~20h (Content-only; 7a UI-Framework-Scaffolding ~12h in Block 5 vorgezogen, Konzept §17.2 v5.3) Aufwand real: ~29h (7.1a 6h + 7.1b 9h + 7.2 4h + 7.3 4h + 7.4 6h) Merge: 0b93d60 (4 Sub-Commits: 287a292 7.1a, 911930c 7.1b, e46b61e 7.2, 529dc66 7.3, 0b93d60 7.4) Abhängigkeiten: Phase A komplett, insbesondere Block 5 (liefert UI-Framework-Scaffolding + Template-UI), Block 6 (Modul-Katalog)

Warum

Ohne Operator-UI müsste AVS alle Tenant-, Template- und Modul- Aktionen per SQL oder API-Call durchführen — fehleranfällig, eskalationsfreudig, und ein Blocker für den Operator-Alltag. Die Audit-Log-Einsicht ist AVV-Pflicht (vgl. Block 9 Vendor-UI) — der Operator-Pfad ist die AVS-seitige Hälfte derselben Datenquelle.

Hinweis: UI-Framework-Scaffolding (Vue-3-Setup, Build-Pipeline, Base-Layout) wurde als 7a in Block 5 vorgezogen (siehe dort und Konzept §17.2 v5.3). Block 7 konzentriert sich auf Content- Implementation auf dem bestehenden Scaffolding.

Scope

Im Scope:

  • Route-Gruppe /admin/operator/* (§9.2): tenants/*, templates/*, modules/*, connectors/*, vendor-access/*
  • Tenants-CRUD mit Paket-Editor (aktiviert Module laut Block 6)
  • Template-CRUD nutzt Backend aus Block 5
  • Modul-Katalog als Read-Only-Registry-View plus Pro-Tenant-Aktivierung
  • Vendor-Audit-Log Read-Only + CSV-Export (ersetzt den alten "Vendor-Audit-Log-UI"-Scoping-Eintrag aus der vor-v5.1-Roadmap)
  • Bulk-Operationen (mehrere Tenants gleichzeitig Modul zuweisen)

Nicht im Scope:

  • Kein Self-Service-Tenant-Signup (nur AVS legt an; siehe Block 12)
  • Keine Billing-Integration
  • Keine Tenant-Impersonation (der "Im Auftrag"-Pfad ist Block-17-Thema)

Verweise


Block 8 — Tenant-UI mit Chatbot-Management ✅ Erledigt 2026-04-30

Gesamt-Status: In Arbeit (8.0 ✅, 8.1 ✅). Real-Aufwand bisher: ~4h (8.0 + 8.1). Refined-Schätzung Rest: ~46–60h (Discovery-basiert, siehe Sub-Blocks). Konzept-Versprechen §17.2: 44h. Drift-Hinweis: Discovery zeigt Chatbots-Wizard (8.4) ist größerer Brocken als Konzept-Punkt-Schätzung suggerierte; Sources (8.5) hat hard-dependency auf Block 13. Drift wird in §17.2-Reconciliation aufgenommen, nicht hier korrigiert. Letzte Konkretisierung: 2026-04-30 (Discovery-First nach 8.0/8.1- Hand-off). Abhängigkeiten: Block 7 (UI-Grundgerüst), Block 4 (Chatbot-Provisioning-Hook), Block 5 (Template-Snapshot), Block 13 (Konnektor-Subsystem) als hard-dep für 8.5.

Warum

Kurverwaltungen brauchen einen Klick-Pfad für Chatbot-Erstellung, Quellen-Management, Branding, Prompt-Editor und Feedback-Review. Ohne dieses UI ist die Plattform für Tenants unbedienbar — es bliebe nur der Breakglass-Weg über AVS-Operator oder luki-Support.

Sub-Block-Status (Discovery-First-Refinement, 2026-04-30)

Sub-Block Inhalt Status Aufwand
8.0 Foundation: Module-Auto-Seed + Tenant-UI-Core-Routes ✅ Erledigt (Merge a6081d8) 3.5h real
8.1 UX-03 Tenant-Edit-UI ✅ Erledigt-by-prior-block (7.1b/7.4), Verifikation Merge fd7e5be 0.5h Verifikation
8.2 Multi-Language-Templates-Convenience (Clone-Workflow) ✅ Erledigt 2026-04-30 4h real
8.3 Provisioning-Self-Service Tenant-Module-Toggle ✅ Erledigt 2026-04-30 4h real
8.4 Chatbots-CRUD + Wizard ✅ Erledigt 2026-04-30 9h real
8.5 Sources-Management 📋 Blockiert von Block 13 ~10–12h (nach Block 13)
8.6 Branding-Editor (Tenant + Chatbot + Operator-Override mit custom_css) ✅ Erledigt 2026-04-30 5h real
8.7 Feedback-View (Merge 7280d33) ✅ Erledigt 2026-04-30 ~3h real

Block-8-Schluss: Mit 8.7 sind alle Block-8-Sub-Blöcke abgeschlossen außer 8.5 (von Block 13 blockiert). v1.1.0 wurde am 2026-04-30 getaggt — siehe Release-Notes und Akzeptanz-Matrix.

Block-8-Real-Aufwand: ~30.5h vs. Refined-Schätzung 50–64h (60 % Quote). Pattern-Reife wurde ab 8.4 sichtbar — 8.6 (5h) und 8.7 (3h) profitierten direkt vom Sub-Route-Pattern aus 8.6 plus Audit-Helper aus TODO-14.

Strategie-Pause nach v1.2.0

Pfad A (Block 11) erledigt mit v1.2.0-Tag (2026-05-01). Vier Pfade stehen für die nächste Achse:

Pfad A — Block 11 Widget-Integration ✅ Erledigt 2026-05-01 (v1.2.0)

Branding-Schreib-Pfade aus 8.6 als Foundation eingelöst. Block 11 brachte:

  • GET /api/v1/widget/config/{chatbot_id} (public, Origin-checked) mit Field-by-Field Chatbot→Tenant-Branding-Resolve
  • POST /api/v1/feedback (public, Origin-checked, anonymous-actor Audit) — Alembic 0009 macht feedback.session_id/message_id nullable, damit Widget-Feedback ohne Platform-Chat-Infrastruktur landet
  • Origin-Check inline (Option A — exact + Sub-Wildcard, kein Discovery-Oracle); 13 pytest-Integration-Tests grün
  • Widget-API-Client um chatbotId-Mode erweitert (Hybrid-Variante: AVS-Demo bleibt, Platform parallel)
  • EmbedCodeSnippet-Komponente in beiden UIs (Tenant-UI auf ChatbotDetailPage integriert)
  • TODO-Platform-15 Phase 4 erledigt: 7 neue Playwright-Specs (chatbot-sub-routes, widget-public-api, tenant-branding-sub-route)
  • TODO-Block-7-4-04 Anteil bedient (chatbot_feedback.created in KNOWN_ACTIONS)

Aufwand-Datapoint: ~14h Refined geplant → ~5–6h real (Pattern-Quote ~40 % — besser als Block-8-Schnitt 60 %; Branding- Foundation aus 8.6 plus Audit-Helper aus TODO-14 zahlten direkt ein).

Pfad B — Block 13 Konnektor-Framework (~57h Refined)

Größter Tech-Hub, blockt 8.5. BaseConnector + Modul-Registry + Credential-Store + Sync-Scheduler. Foundation für 8.5 (Sources- Management) und für Phase C (Confluence, MediaWiki, MS-System-Connector).

Erwartete Real-Quote: höher als 60 % (neue Achse, kein direktes Pattern-Reuse aus Block 8/11). Risiko: 57h-Single-Block ohne Zwischen-Tag — Pattern wäre, in ~3–4 Sub-Blöcke zu zerlegen analog Block 8 (Discovery-First-Refinement).

Pfad C — Block 8.5 Stub-Variante (~6h Refined)

Fixer Upload-Konnektor ohne BaseConnector-Framework. Brücke zwischen v1.2.0 und Block 13. Risiko: Sunk-Cost-Falle, falls Block 13 dann anders strukturiert. Lohnt nur, wenn Source-Upload demnächst customer-relevant ist.

Pfad D — Cleanup-Welle (~22h Real) ✅ Konkretisiert in v1.3.0-Welle

Discovery-Mini-Run am 2026-05-01 abgeschlossen (cleanup-welle-discovery-2026-05-01.md): 42 aktive TODOs in 9 Familien, ~37h Refined / ~22h Real mit 60 %-Pattern-Quote. Aufgeteilt in zwei Sub-Branches D1 Frontend Polish (~9h Real) und D2 Backend Polish (~13h Real) wegen Review-Friction bei Mega-Cleanup. Konkretisiert als v1.3.0-D1 + v1.3.0-D2 — siehe v1.3.0-Welle-Sektion unten.

Pfad E — Operator-UI Per-Chatbot-Page (~4–5h Real) ✅ Konkretisiert in v1.3.0-Welle

Customer-Wert-Datapoint aus Block-11-Discovery: Operator-UI hat keinen Per-Chatbot-Detail-View. EmbedCodeSnippet-Komponente steht standalone bereit (frontend/operator-ui/src/components/ EmbedCodeSnippet.vue) — Integration auf einer künftigen OperatorChatbotDetailPage ist eine Zeile.

Pattern-Reife: Tenant-UI ChatbotDetailPage als direkte Vorlage. Real-Quote vermutlich ähnlich Block 11 (~40 %), wenn Cross-Tenant- Backend-Endpoints schon existieren. Konkretisiert als v1.3.0-E — siehe v1.3.0-Welle-Sektion unten.

Pfad B — Block 13 Konnektor-Framework (~57h Refined) 🔵 Offen

🔵 Offen — nach v1.3.0-Tag. v1.3.0-Welle räumt Wartungsschuld auf, damit Block 13 sauber starten kann (Audit-Pattern und Scope-Guards vor neuer Achse konsolidiert).

Pfad C — Block 8.5 Stub-Variante (~6h Refined) 🔵 Offen

🔵 Offen — Bewertung nach v1.3.0-Tag. Sunk-Cost-Risiko bleibt; lohnt nur, wenn Source-Upload customer-relevant wird, bevor Block 13 fertig ist.

v1.3.0-Welle — Cleanup + Customer-Wert ✅ Abgeschlossen 2026-05-01

Total: ~42.5–44.5h Refined / ~13h Real (≈ 30 %-Quote — deutlich besser als die 60 %-Discovery-Erwartung; Audit-/Service-Pattern aus Block 4/5/8/11 trugen über alle drei Sub-Blöcke). Charakter: kombinierte Welle aus Wartungsschuld-Reduktion (Pfad D) und Customer-Wert (Pfad E) Reihenfolge umgesetzt: D2 (Backend-Foundation) → D1 (Frontend nutzt D2-Endpoints + flattenError) → E (Customer-Wert auf D1+D2-Foundation). Lutz-Entscheidung 2026-05-01 (Audit-Empfehlung mit Foundation-Argument) bestätigt durch Real-Aufwände.

Sub-Blocks

v1.3.0-D2 — Backend Polish ✅ Erledigt 2026-05-01

  • Aufwand: ~5h real vs. 22h Refined (≈ 23 % Quote — deutlich besser als die 60 %-Erwartung der Discovery; Audit-/Service-Pattern aus Block 8/11 voll wiederverwendbar, viele TODOs Single-File-Touch). Datapoint für D1- und E-Erwartung.
  • Geschlossen: 17 TODO-IDs in 4 Familien (7.1a, 5e/5f/5g, 7.3-Backend-Anteil, 7.4-Backend-Anteil) — Liste im changelog.md Unreleased-Sektion und im offene-todos.md Archiv.
  • Foundation-Lieferung: Zentraler Scope-Guard-Helper (api/dependencies/scope_guards.py), Alembic 0010 mit set_updated_at()-PG-Trigger auf tenants + tenant_modules + platform_modules, Bulk-Cap (MAX_BULK_ITEMS=500) + Multi-Row- Refactor in beiden Bulk-Endpoints, neue Modul-Detail- und Aggregate-Endpoints, neue Doku-Page operations/audit-conventions.md.
  • Test-Stand: 160/160 grün (vorher 155/155, +5 neue D2-Tests).
  • Quelle: cleanup-welle-discovery-2026-05-01.md Cluster D2

v1.3.0-D1 — Frontend Polish ✅ Erledigt 2026-05-01

  • Aufwand: ~14.5h Refined / ~4.5h Real (~30 %-Quote, näher am Plan als D2 mit 23 %, weil Frontend-Refactors typischerweise mehr Vue-/ Test-spezifische Reibung tragen — guter Datapunkt für E).
  • Branch: platform/v1.3.0-d1-frontend-polish
  • Inhalt: 16 TODOs aus 3 Familien (7.1b, 7.2, 7.3) + 2 D2- Frontend-Last-Mile-Items (useModule, useTenantModules auf neue D2- Endpoints migriert).
  • Lieferung:
    • Foundation-Helpers: formHelpers.ts (trimEqual, listsEqual), flattenError in useApi.ts — TenantsEdit, TemplatesEdit, TenantsList Bulk und TenantModulesSection adoptieren die Helpers konsistent.
    • Component-Patterns: ListInput a11y (Live-Region, Alt+↑/↓ Reorder, Move-Buttons), useConfirm FIFO-Queue.
    • Backend-induziert + Last-Mile: useModule auf /platform/modules/{id} umgestellt, useTenantModules auf Aggregate /platform/tenant-modules?tenant_id=…. TenantModulesSection bekommt Optimistic-Updates, full-UUID-Tooltip auf enabled_by, flattenError-Toast-Detail. TemplatesCreate lässt Empty-Lists weg.
    • Composable-Caching: useTenants SWR-Cache (30s TTL, Mutation-Invalidation).
    • Hygiene: E2E-Seed hinter VITE_E2E_MODE-Build-Gate (mit Dockerfile/compose-Default true für luki-ai), mintTokens async, PORTING.md nach docs-kora/docs/blocks/.
    • Cosmetic: stale „Block 7.x"-Strings in TenantsCreatePage und TenantsDetailPage entfernt.
  • Test-Stand: 161/161 grün (vorher 130 baseline; +6 ListInput reorder/a11y, +5 useApi flattenError, +8 formHelpers, +3 TenantModulesSection aggregate/optimistic/UUID-tooltip, +4 useTenants SWR, +1 useConfirm queue, +1 ModulesDetailPage detail- endpoint; +3 useConfirm-Tests umgeschrieben).
  • Quelle: cleanup-welle-discovery-2026-05-01.md Cluster D1

v1.3.0-E — Operator-Per-Chatbot-Page ✅ Erledigt 2026-05-01

  • Aufwand: ~3.5h Real vs. 6–8h Refined (≈ 50 %-Quote — höher als D2/D1 weil ein neuer Top-Level-View entsteht statt nur In-Place- Refactor; Sub-Route, vier Sektionen, drei Composables, vier Routes brauchten echtes Skelett. Trotzdem deutlich unter 100 %, weil Service-Layer komplett wiederverwendet, Pattern voll gespiegelt aus operator_branding_router und Tenant-UI ChatbotDetailPage).
  • Branch: platform/v1.3.0-e-operator-chatbot-page
  • Lieferung:
    • Backend (4 Endpoints, alle pure Auth-Wrapper): GET /operator/tenants/{tid}/chatbots/{cid} (Stammdaten), GET .../branding (Override-Read), GET .../feedback (Liste mit Filtern), GET .../feedback/stats (Aggregat). Alle BYPASSRLS + require_operator_or_vendor, Service-Layer (ChatbotService/BrandingService/FeedbackService) ohne Änderung wiederverwendet.
    • Frontend (vier Read-Sektionen, single page): TenantChatbotDetailPage mit Sub-Route /tenants/:tenantId/chatbots/:chatbotId. Vier vertikal gestapelte Sektionen: ChatbotOverviewSection (Stammdaten + collapsible System-Prompt), ChatbotBrandingReadSection (Inheritance-Hint, Empty-Override-Hint, Color-Swatch), ChatbotFeedbackReadSection (4 Stat-Cards, Rating-/Kategorie- Filter, paginierte Tabelle), EmbedCodeSnippet aus Block 11 direkt eingehängt. Diagnostischer Banner: „Bearbeiten/Override- Edit/Löschen aus Tenant-Kontext".
    • Composables: useOperatorChatbot, useOperatorChatbotBranding, useOperatorChatbotFeedback — alle nutzen flattenError aus D1.
    • TenantsDetailPage: neuer „Chatbots"-Tab (lazy-loaded) mit Tabelle + „Ansehen"-Button pro Row → Sub-Route.
  • Foundation-Reuse-Bilanz:
    • D1: flattenError für Toast-Detail-Extraction
    • D2: BYPASSRLS-Helper + require_operator_or_vendor
    • Block 8.6/8.7: BrandingService/FeedbackService unverändert
    • Block 11: EmbedCodeSnippet-Komponente direkt
    • Block 8.4: ChatbotService.get_for_tenant unverändert
  • Test-Stand: 178/178 Frontend grün (vorher 161, +17 neue: 4 Overview, 5 Branding, 5 Feedback, 3 DetailPage). Backend 9/9 neue Integration-Tests (Pattern aus test_feedback_api.py).
  • Customer-Wert: Operator kann ohne Tenant-Wechsel Chatbots inspizieren — schließt Block-11-Hand-off-Datapoint (AVS-Operator-Pain).
  • Quelle: Drift-Status-Audit + Block-11-Hand-off-Datapoint

Was ist NICHT in v1.3.0-Welle

Aus Cleanup-Welle-Discovery als „strategisch verschoben" (Cluster D3) markiert:

Item Verschoben nach Begründung
4b Qdrant-Backup eigener Block (~8–12h) Operations-Block, kein Cleanup
TODO-Block-7-3-01 Pakete/Tier/Limits Block 12 Tenant-Provisioning-Bezug, Limits-Enforcement
TODO-Platform-11 Pytest-Env-Bootstrap Block 14 (CI) CI-Foundation
TODO-Platform-12 Pytest-Profil-Trennung Block 14 (CI) CI-Foundation
TODO-Block-7-NN-05 pydantic[email] Supply-Chain-Review Vor v1.0.0-GA-Audit, eigene Decision
TODO-Block-7-4-04 KNOWN_ACTIONS-Drift Block 13/14 Wird mit neuen Actions natürlich erweitert
TODO-Block-7-4-05 Playwright workers:1 Trigger > 50 Specs Heute 8 Specs, kein Pain
TODO-Auth-NEU JWT-sub optional in v1.3.0-D2 ankoppelbar Monitored seit v1.0.0, low priority (~1.5h)

Nach v1.3.0-Welle: Strategie-Pause B vs. C

v1.3.0-Welle (Pfad D + E) erledigt; v1.3.0-Tag am 2026-05-02. Nach v1.3.0 stehen:

Pfad B — Block 13 Konnektor-Framework (~57h Refined)

  • Größter Tech-Hub, blockt 8.5
  • BaseConnector + Modul-Registry + Credential-Store + Sync-Scheduler
  • Erwartete Real-Quote: 50–70 % (neue Achse, Foundation-erweiternd)
  • Real-Erwartung: ~28–40h
  • Foundation aus v1.3.0: zentraler scope_guards.py-Helper, Audit- Pattern konsolidiert, Bulk-Cap-Hardening — Block 13 startet auf etablierten Patterns.

Pfad C — Block 8.5 Stub-Variante (~6h Refined)

  • Fixer Upload-Konnektor ohne BaseConnector-Framework
  • Brücke vor Block 13
  • Risiko: Sunk-Cost wenn Block 13 anders strukturiert
  • Real-Erwartung mit ~30 %-Cleanup-Welle-Quote: ~2h

Mini-Run pending: TODO-Konzept-02

§17.2-Reconciliation mit Pattern-Reife-Quote-Trendlinie pro Block-Typ. Drei v1.3.0-Datapoints (D2 23 %, D1 31 %, E ~50 %) plus existing aus Block 8/11 erlauben kalibrierte Quote-Erwartung. ~30–45 min, eigener Run nach v1.3.0-Tag — analog zur TODO-Konzept-01-Auflösung aus dem v1.2.0-Lauf.

Pause-Entscheidung: Lutz wählt nach v1.3.0-Tag.

Pattern-Reife-Quote-Anwendung in v1.3.0-Welle

Sub-Block Foundation-Reuse Erwartete Quote Tatsächliche Quote
D2 Backend Polish hoch (Audit-Helper TODO-14, Service-Patterns Block 4/5) 60 % ~23 %
D1 Frontend Polish hoch (Component-Library, Composables Block 7.1b) 60 % ~31 %
E Operator-Per-Chatbot-Page sehr hoch (Tenant-UI-Pattern Block 8.4 als Vorlage) 40–60 % ~50 %
Welle gesamt ~60 % ~30 %

Alle drei Sub-Blöcke deutlich unter Erwartung. Datapoint für Block-13-Schätzung: bei hoher Foundation-Reuse rechnet sich konsistent ~30 % Quote, nicht 60 %. E lag oben in seiner Bandbreite, weil ein neuer Top-Level-View entstand (vier Sektionen + Sub-Route + drei Composables); D1/D2 waren In-Place-Refactors. Bei künftigen „neuer-View"-Blöcken ~50 % als Daumenregel ansetzen.

Block 8.0 — Foundation ✅ (Merge a6081d8, 2026-04-30)

Tenant-UI Core-Routes (Templates/Module/Profile read-only), Sidebar-Restruktur (4 Groups), Module-Auto-Seed im Lifespan-Hook (TODO-Platform-13 erledigt). Backend-Endpoint GET /api/v1/tenants/me/modules mit LEFT-JOIN-Variante.

Block 8.1 — UX-03 Tenant-Edit-UI ✅ Erledigt-by-prior-block (Merge fd7e5be, 2026-04-30)

Discovery zeigte: Tenant-Edit-UI war bereits seit Block 7.1b/7.4 vollständig. PATCH-Endpoint, TenantUpdate-Schema, TenantsEditPage (Slug-immutable, Dirty-State, Inline-Errors), Audit-Action tenant.updated mit details.before/after-Diff. Verifikations-only Block — kein neuer Code. Re-Diagnose-Lesson: Status-Annahmen via find/grep verifizieren vor Block-Moves.

Block 8.2 — Multi-Language-Templates-Convenience 📋

Existing (aus Discovery):

  • chatbot_templates.language (VARCHAR(5), Default 'de') seit Block 5
  • ChatbotTemplateBase/Create/Update-Pydantic-Schemas mit language
  • TemplatesCreatePage hat language-Feld (default 'de')
  • TemplatesEditPage erlaubt language-Änderung
  • TemplatesListPage hat Sprach-Filter (UX-04 Merge 1110a21)
  • Service propagiert template.language → chatbot.language bei Provisioning

Offen — Convenience-Workflow:

  • Clone-in-Other-Language-Action: „DE-Template → neues EN-Template (mit Suffix -en)". Single-Click in TemplatesDetailPage, Backend- Service-Methode clone_template_to_language(id, target_language), audit-action template.cloned.
  • Optional (kann verschoben werden): Template-Familien-Gruppierung (mehrere Sprachversionen einer Template-Idee verknüpfen). Aktuell unverbunden via separate IDs.

Akzeptanz-Kriterien:

  • TemplatesDetailPage zeigt „In andere Sprache klonen"-Button
  • Backend-Endpoint POST /api/v1/operator/templates/{id}/clone mit target_language-Body
  • Tenant-Liste zeigt klonierte Templates korrekt nach Filter
  • Audit-Log-Eintrag mit Source/Target-Template-IDs

Aufwand: ~4–6h (Backend ~2h + Frontend ~2h + Tests ~1h).

Block 8.3 — Provisioning-Self-Service: Tenant-Module-Toggle 📋

Existing (aus Discovery):

  • GET /api/v1/tenants/me/modules (read-only, Block 8.0)
  • POST /api/v1/tenants/{tenant_id}/modules mit _require_operator_or_vendor
  • DELETE /api/v1/tenants/{tenant_id}/modules/{module_id} analog operator-only
  • Service hat assign_to_tenant, revoke_from_tenant mit is_always_on- Validierung (ModuleNotAssignable-Exception bei core-Scope-Versuchen)
  • Tenant-UI ModulesPage ist read-only (Block 8.0)

Offen:

  • Tenant-self Toggle-Endpoints: POST /api/v1/tenants/me/modules + DELETE /api/v1/tenants/me/modules/{module_id} mit tenant_scope_required-Gate, Re-Use der Service-Layer-Methoden
  • Frontend: ModulesPage Toggle-Switch mit Confirm-Dialog
  • Validierung: is_always_on=true (core-Scope) → 403, internal_only-Scope → 404 für Tenants
  • Audit-Action tenant.module.self_activated/tenant.module.self_deactivated

Akzeptanz-Kriterien:

  • Tenant kann external_eligible-Module selbst aktivieren/deaktivieren
  • core-Module kann Tenant nicht ändern (Server- + UI-Gate)
  • Audit-Log-Spur ist eindeutig zwischen operator-getriebenem und tenant-self-getriebenem Toggle
  • Vitest + Playwright deckt Toggle-Flow ab

Aufwand: ~6–8h.

Block 8.4 — Chatbots-CRUD + Wizard 📋 (größter Sub-Block)

Existing (aus Discovery):

  • chatbots-Schema vollständig: tenant_id, slug, display_name, description, template_id, system_prompt, suggestions, language, uses_shared_docs, qdrant_collection, template_version_at_creation, status, deleted_at
  • 218 chatbot-Rows in DB (Demo-Daten)
  • GET /api/v1/tenants/{tenant_id}/chatbots (Liste) existiert
  • Tenant-UI ChatbotDetailPage.vue (Detail-View für Template-Update-Flow)
  • TemplateUpdateBanner + TemplateUpdateDialog im Tenant-UI
  • Endpoint apply_chatbot_template_update für Template-Update-Apply

Offen — Wizard + List + Edit:

  • ChatbotsListPage (Tenant-UI) — analog Operator-TenantsListPage
  • Chatbot-Wizard (/chatbots/new): Multi-Step-Form mit Template-Auswahl, System-Prompt-Customization, uses_shared_docs-Toggle (§5.3), Suggestions-Editor
  • ChatbotEditPage (Stammdaten-Edit, NICHT System-Prompt — der hat Template-Update-Flow)
  • Backend: POST /api/v1/tenants/me/chatbots, PATCH .../{id}, DELETE .../{id} (soft-delete) mit Qdrant-Collection-Provisioning- Hook (§4.2 — eigene Collection pro Chatbot)
  • Audit-Actions chatbot.created/chatbot.updated/chatbot.deleted

Akzeptanz-Kriterien:

  • Tenant erstellt Chatbot via Wizard → Qdrant-Collection wird angelegt
  • Chatbot in Liste sichtbar, Detail-Page zeigt aktuellen Template-Stand
  • Edit ändert Stammdaten, kein Template-Update-Hook
  • Soft-Delete entfernt Chatbot aus aktiver Liste, Qdrant-Collection bleibt erhalten (Hard-Delete = Operator-Aktion)

Aufwand: ~12–16h (Block-7.1b-Pattern als Granularität-Maßstab, plus Wizard-Komplexität).

Block 8.5 — Sources-Management 📋 Blockiert von Block 13

Existing (aus Discovery):

  • chatbot_sources-Schema vollständig: chatbot_id, tenant_id, connector_id, connector_version_at_creation, display_name, config, credential_id, sync_schedule, sync_status, last_synced_at, last_error
  • 0 Rows
  • ❌ Keine Source-Routes (api/routes/chatbot_sources.py existiert nicht)
  • ❌ Keine Konnektor-API (api/routes/connectors.py existiert nicht)
  • Operator-UI ConnectorsPage.vue ist Stub mit Hinweis „Verfügbar in Block 13"
  • ❌ Keine Source-UI

Hard-Dependency: Sources brauchen das Konnektor-Framework aus Block 13 (§13). Ohne Konnektor-Registry, Credential-Storage, Sync-Engine ist Source-Management nicht implementierbar — Block 13 ist 57h-Block (siehe Konzept-Roadmap).

Empfehlung: Block 8.5 wird nach Block 13 ausgeführt. Das verschiebt Block 8 thematisch in Phase C (Quality + Konnektoren), nicht Phase B (UI-Polish). Alternative: Stub-Source-UI mit fixem Upload- Konnektor (~6h), Volumen kommt mit Block 13 nach. Lutz-Entscheidung offen.

Aufwand: ~10–12h (nach Block 13). Falls Stub: ~6h.

Block 8.6 — Branding-Editor 📋

Existing (aus Discovery):

  • tenant_branding-Schema: tenant_id (PK), primary_color, logo_url, widget_title, widget_subtitle, welcome_message, footer_text, allowed_origins, custom_css
  • Plus chatbot_branding-Schema (separate per-Chatbot-Override-Tabelle)
  • 0 Rows
  • ❌ Keine Branding-Routes
  • ❌ Keine Branding-UI

Offen — Backend + UI:

  • Backend-CRUD für tenant_branding (operator + tenant-self) und chatbot_branding (tenant-only)
  • Branding-Editor-UI (Tenant-UI, route /branding):
  • Color-Picker für primary_color
  • Logo-URL-Input mit Preview
  • Welcome-Message + Footer-Text-Editor
  • Allowed-Origins-Liste (für CORS bei Embedded-Widget)
  • Custom-CSS-Textarea (advanced, mit Hinweis)
  • Fallback-Tree-Logic: Chatbot-Branding → Tenant-Branding → Default (§4.5 Konzept)

Akzeptanz-Kriterien:

  • Tenant editiert Branding, sieht Live-Preview
  • Embedded-Widget-Generator (Block 11) zieht Branding korrekt
  • Audit-Log-Eintrag pro Branding-Update

Aufwand: ~8–10h.

Block 8.7 — Feedback-View ✅ (2026-04-30)

Read-Only-Feedback-Übersicht pro Chatbot. Sub-Route /chatbots/:id/feedback (Pattern aus 8.6 wiederverwendet, keine Tabs in ChatbotDetailPage). Stat-Cards plus filterbare Tabelle in Konzept-A-Color-Tokens. Categories und DE-Labels aus AVS-Demo-Pattern (wrong_answer/incomplete/wrong_source/not_helpful/too_slow/other).

Discovery (verkürzt 6–8h-Schätzung auf ~3h real):

  • Platform-Feedback-Schema existierte bereits seit Block 1 mit RLS-Policy → Phase 1a (Schema-Migration) entfiel komplett.
  • Schreib-Pfad ist nur in der AVS-Demo (src/avs_chatbot/api/routes/feedback.py) vorhanden, nicht in der Platform. Block 11 (Widget-Integration) stellt das Widget um. Bis dahin zeigt 8.7 leere Tabellen oder Mock-Daten — pragmatischer Empty-State im UI dokumentiert das.
  • Tab-Pattern aus 8.6: keine Tabs etabliert, Sub-Routes vom ChatbotDetailPage (/chatbots/:id/branding). 8.7 spiegelt das.

Erledigt (Backend, 3 Files):

  • src/kora_platform/models/feedback.py — Pydantic-DTOs mit Literal-Categories.
  • src/kora_platform/services/feedback_service.pylist_feedback_for_chatbot
  • get_stats-Aggregation (rating/category-Whitelist gegen Drift).
  • src/kora_platform/api/routes/feedback.py — 2 GET-Endpoints (/feedback + /feedback/stats) mit tenant_scope_required, Regex-validierten Query-Params, Route zwischen chatbots_router und tenants_router registriert.

Erledigt (Frontend Tenant-UI, 3 Files + 2 Edits):

  • types/feedback.ts mit FEEDBACK_CATEGORY_LABELS_DE-Map.
  • composables/useFeedback.ts (Read-only).
  • pages/ChatbotFeedbackPage.vue mit 4 Stat-Cards (Total/Positiv/Negativ/Top-Kategorie), Rating-Toggle + bedingtes Category-Dropdown, Tabelle mit gekürzter Frage/Antwort, Empty-State, Pagination-Button.
  • router/index.ts und pages/ChatbotDetailPage.vue (Action-Bar mit Feedback-/Branding-Buttons).

Tests:

  • tests/integration/test_feedback_api.py — 9 Pytest-Cases (List, Filter, Pagination, Stats, Empty-Stats, Cross-Tenant-404, Operator-403, Chatbot-Not-Found-404). Cleanup über chatbots-DELETE (FK-CASCADE wipes sessions/messages/feedback) vor tenants-DELETE — chat_sessions.tenant_id hat keinen ondelete=CASCADE. → 9/9 grün im Container.
  • Vitest: useFeedback.spec.ts (4) + ChatbotFeedbackPage.spec.ts (5) → Suite gesamt 31/31 in 6 Files.
  • Live-Smoke: 10 Mock-Rows auf bench-chatbot-000 direkt per SQL geseedet. OpenAPI-Probe zeigt beide Routes registriert.

Stop-Trigger-Anwendung:

  • TODO-Platform-11 (Pytest-Env-Bootstrap): Tests laufen via docker cp + docker exec pytest, weil das Image /app/tests/ nicht enthält. Workaround unverändert seit 8.4/8.6.
  • Playwright: kein E2E geschrieben — 8.6 hatte ebenfalls keinen Playwright-Sweep für Sub-Routes; Vitest + Live-Smoke reichen.

Aufwand: ~3h real (vs. 6–8h Schätzung — Discovery sparte Schema-Migration komplett, Pattern aus 8.6 sparte UI-Architektur).

Lessons aus Block 8 Roadmap-Refinement (2026-04-30)

  • Discovery-First für Roadmap-Konkretisierung: Vor Sub-Block-Move muss find/grep zeigen, was existiert. UX-03 wurde im UX-04-Block in Block-8-Scope verschoben, ohne dass die Edit-UI verifiziert wurde — sie existierte seit 7.1b/7.4. Discovery in Block 8.1 sparte 6–10h Doppelarbeit.
  • Aufwand-Schätzung nach Pattern-Erfahrung: Block 7.1b (~12h) ist Granularitäts-Maßstab. 8.0 lief in 3.5h, 8.1 in 0.5h. Refined- Schätzungen für 8.2–8.7 nutzen Block-7.1b-Pattern + Discovery-Ist- Stand-Korrektur.
  • Schema vorhanden ≠ Feature implementiert: chatbot_sources, tenant_branding, feedback haben vollständige Schemas, aber 0 Routes und 0 UI. Block-1-Datenmodell-Vorarbeit war gut, aber Block-8-Scope ist trotzdem voll Frontend + Backend.
  • Hard-Dependencies sichtbar machen: Block 8.5 (Sources) hängt von Block 13 (Konnektor-Subsystem). Ohne explizite Doku läuft Block-8- Implementation in einen toten Block 13-Stub-Page. Roadmap muss Dependencies vor Aufwand-Summen kommunizieren.
  • Konzept-Drift ist normal: Block 8 wurde im Konzept v3/v4 mit 44h geschätzt. Discovery-Refined ergibt 50–64h. Drift kommt aus zu optimistischer Wizard-Schätzung (8.4) und übersehener Block-13- Dependency (8.5). Konzept-Update kann nachziehen, Roadmap dokumentiert Realität.
  • Audit-Spur > Plan-Theater: Erledigte Sub-Blocks mit Merge-Hash dokumentieren ist wertvoller als „voraussichtlich-fertig"-Marker. Block 8.0 + 8.1 sind mit konkreten Hashes (a6081d8, fd7e5be) archiviert.

Verweise


Block 9 — Vendor-UI (luki-Ebene) 📋 Scoping

Zielversion: v1.0.0 Aufwand: ~12h (Konzept §17.2) Abhängigkeiten: Block 7 (UI-Framework), Block 2 (Keycloak-Rollen vendor-breakglass, vendor-tunnel)

Warum

Die luki-Vendor-Rollen brauchen einen klaren UI-Pfad mit E-Mail-Alert, Session-Banner und Tunnel-Toggle. Der AVV verlangt, dass vendor-seitige Aktionen genauso transparent sind wie die operator-seitige Audit-Einsicht — derselbe Datensatz, andere Scope-Filter.

Scope

Im Scope:

  • Route-Gruppe /admin/vendor/* (§9.2): audit-log, tenant-overview, tunnel-control, sync-health
  • Break-Glass-Login mit sofortigem E-Mail-Alert an AVS-Contact
  • Session-Banner ("Vendor-Session aktiv") permanent sichtbar, Timer bis Session-Ablauf
  • Audit-Log-View (gleiche Datenquelle wie Operator-UI in Block 7, andere Scope-Filter)
  • Tunnel-Toggle — Aktivierung erfordert Operator-Freischaltung als Voraussetzung (§15.4)

Nicht im Scope:

  • Keine Modul-Registry-Stufe-1-UI (entfällt laut §17.1, −4h)
  • Kein luki-seitiges Billing oder Reporting

Verweise


Block 10 — System-Prompt-Automatismus 📋 Scoping

Zielversion: v1.0.0 Aufwand: ~24h (Konzept §17.2) Abhängigkeiten: Block 8 (Prompt-Editor-UI als Trigger-Oberfläche), Block 4 (Chatbot-Kontext für Dokumenten-Sampling)

Warum

Tenant-Admins sollen Prompts nicht von Hand schreiben müssen. Ein automatisiert generierter Draft-Prompt auf Basis der eingespielten Dokumente ist ein klarer UX-Sprung gegenüber dem heutigen Demo-Stand — und er senkt die Einstiegshürde für Kurverwaltungen, die kein Prompt-Engineering-Know-how haben.

Scope

Im Scope:

  • Multi-Step-Pipeline mit Qwen3-14B (Default-LLM): Dokument-Sampling, Source-Type-bewusste Zusammenfassung (Confluence anders als DOCX), Prompt-Template-Auswahl, Entwurfs-Rendering
  • Explizit Button-getriggert im Prompt-Editor (Block 8) — kein Auto-Trigger beim Upload
  • Source-Type-Handling: unterschiedliche Zusammenfassungs-Prompts für Upload, Confluence, MediaWiki
  • Pipeline-Stage-Metrics (Prometheus-Histogramm pro Stage)
  • UI-Integration: "Draft aus Dokumenten generieren"-Button im Prompt-Editor, Preview mit Diff gegen aktuellen Prompt

Nicht im Scope:

  • Kein vollautomatisches Prompt-Update (Admin muss Draft explizit übernehmen)
  • Keine Evaluation gegen evaluation_questions (separate Arbeit)

Verweise


Block 11 — Widget Multi-Tenant + Multi-Chatbot ✅ Erledigt 2026-05-01

Zielversion: v1.0.0 Aufwand: ~14h Refined geplant → ~5–6h real (Pattern-Reife-Quote ~40 %, besser als Block-8-Schnitt 60 %). Konzept-Patch §17.2 v5.3.3 (TODO-Konzept-01-Auflösung) hat den Mid-Point der vormals 12h-§17.2- vs. 16h-Roadmap-Diskrepanz auf 14h festgelegt — siehe §17.2a Überlapp-Quelle Nr. 6. Abhängigkeiten: Block 3 (API-Middleware), Block 7 (Operator-UI für allowed_origins-Pflege), Block 8.6 (Branding-Schreib-Pfade als Read-Foundation eingelöst)

Warum

Das Widget ist das User-Facing-Artefakt: Tenants und Chatbots müssen sich visuell unterscheiden lassen (Farben, Logo, Welcome-Message), und die Einbettung muss per data-tenant+data-chatbot-Attribute parametrisierbar sein. Branding-Resolution folgt dem Fallback-Tree aus §4.5 (Chatbot-Branding → Tenant-Branding → System-Default). Authentifizierung läuft origin-basiert statt per Token (§12.4).

Scope

Im Scope:

  • GET /widget/config?chatbot_id=... liefert gerendertes ChatbotBranding mit Fallback auf TenantBranding und System-Default
  • <kora-chat-widget tenant-id="..." chatbot-id="..."> — Web-Component akzeptiert beide Attribute, lädt Config, applied sie auf CSS-Variablen
  • Widget-CSS auf CSS-Variables umgestellt (Farben zur Laufzeit änderbar)
  • allowed_origins-Enforcement pro Chatbot (Origin-Middleware, §12.4)
  • 6-Monats-Deprecation-Policy für Widget-Breaking-Changes dokumentiert (§12.2)

Nicht im Scope:

  • Kein Widget-Theming-Editor-UI in v1.0.0 (Custom-CSS bleibt Tenant-Branding-only)
  • Keine Custom-CSS-Injection im Chatbot-Level

Verweise


Block 12 — Provisioning-Automatisierung 📋 Scoping

Zielversion: v1.0.0 Aufwand: ~14h (Konzept §17.2; ersetzt den alten "Tenant-Provisioning-Flow"-Scoping-Eintrag aus der vor-v5.1-Roadmap) Abhängigkeiten: Block 2 (Keycloak-Admin-API), Block 4 (Qdrant-Collection-Provisioning), Block 7 (Operator-Wizard-UI als Trigger)

Warum

Ein halber Tenant (PG-Eintrag ohne Keycloak-Group oder umgekehrt) ist schlimmer als gar keiner. Atomizität ist Pflicht, nicht optional — sonst entsteht ein Ghost-Account, der nirgends einloggen kann, aber Credentials verbrennt, oder ein Tenant ohne User, der nie genutzt werden kann.

Scope

Im Scope:

  • Server-seitige Transaktion über PG + Keycloak mit Kompensations-Logik bei Teilerfolg (§14.1)
  • Operator-Alert statt automatischem Retry bei Keycloak-Rollback- Failure (manueller Eingriff bevorzugt)
  • Keycloak-eigener execute-actions-email-Flow für den Initial-Admin-Link (kein Custom-Token-Generator)
  • Qdrant-Collection-Provisioning-Hook beim Chatbot-Create (§14.2)
  • Soft-Delete mit 30-Tage-Grace (§14.4): tenants.deleted_at gesetzt, Cleanup-Job nach Grace-Period

Nicht im Scope:

  • Kein Self-Service-Tenant-Signup (nur AVS legt an)
  • Keine Bulk-Provisioning-CSV (Einzel-Anlage reicht)
  • Kein Hard-Delete-Pfad über UI (nur Soft-Delete, Hard-Delete via Runbook)

Verweise


Phase C — Konnektoren, Quality & Templates-Content

Phase C umfasst die Ingestion- und Retrieval-Qualität (Docling-Normalisierung, BGE-M3 Hybrid-Retrieval, AST-Chunking), das Konnektor-Subsystem (Framework + Upload + Credentials + Merkle-Sync) sowie den Confluence-Konnektor und die Template-Inhalte durch AVS. Die Quality-Blöcke stehen bewusst vor dem Konnektor-Subsystem, weil sie die Pipeline-Basis liefern, auf der alle Konnektor-Arbeit aufbaut: Docling für Document-Normalisierung, BGE-M3 als finales Embedding-Modell (re-index-sparend nur einmal), AST-Chunking als Chunker-Erweiterung.

Nicht mehr in v1.0.0: Der MediaWiki-Konnektor wurde per Entscheidung 2026-04-24 auf v1.1.0 verschoben (AVS-Realität unbestätigt, Confluence hat Priorität). Siehe Konnektor-Roadmap §2.3 und Konzept §13.6 (v5.3.1).

Block 18 — Docling Ingestion-Normalisierung ✅ Erledigt

Zielversion: v1.0.0 ✅ in platform/v1.0.0 (Merge-SHA 814f981) Aufwand: ~21h Refined (18h ursprünglich + 3h Phase 2.5 Page-Tracking-Scope-Erweiterung) Real-Aufwand Total: ~17-18h (Phase 0-7 Code: ~8h, Real-Eval + Real-Stack-Drifts: ~9-10h) Pattern-Reife-Quote real: ~50-60 % (Code-Phasen ~38 % High-Foundation-Reuse, Real-Eval-Phase moderat wegen PDF-Konventions-Drifts) Branch: platform/block-18-docling-ingestion → merged in platform/v1.0.0 Production-Switch: avs_handbuecher Collection enthält jetzt 242 chunks aus DoclingPDFConverter (DocLayNet + TableFormer). Backup: backups/qdrant/avs_handbuecher_pre_block18.snapshot (8.2 MB, 356 points).

Implementations-Stand (2026-05-02 final)

  • ✅ Phase 0 Discovery (Docling-API, Pipeline-Wiring, Chunker-Refactor-Fläche, Payload, Re-Indexing, Eval, Grafana-Datasource)
  • ✅ Phase 1 DoclingPDFConverter (Lazy-Import, MARKDOWN-Mode, Fail-Loud, has_tables-Detection)
  • ✅ Phase 2 SemanticChunker preserve_tables=True (Sentinel-Pattern, atomare Tabellen, chunk_type-Klassifikation)
  • ✅ Phase 2.5 Page-Tracking via page_break_placeholder + numbered Sentinels (TODO-Block-18-Followup-02 erledigt)
  • ✅ Phase 3 Qdrant-Payload-Schema additiv (chunk_type, docling_version, has_tables — keine Migration nötig)
  • ✅ Phase 4 scripts/reindex_with_docling.py (--dry-run, --collection, idempotent, fail-isolation)
  • ✅ Phase 5 Eval-Set-Erweiterung um 5 Tabellen-Queries
  • ✅ Phase 6 Grafana-Panel "Chunk-Type-Verteilung (Block 18)" + Prometheus-Counter
  • ✅ Phase 7 Doku/CHANGELOG/TODO-Followup-01
  • ✅ Phase 8 Real-Eval + Real-Stack-Drift-Fixes (heading-trailing-dot, word-count-hard-cap)
  • ✅ Production-Switch via Snapshot-Restore (avs_handbuecher ← Block 18 collection)
  • ✅ Merge nach platform/v1.0.0 mit dokumentierter Stop-Trigger-4-Ausnahme

Real-Eval-Resultat: R@5 92 % gesamt (q001-q020 90 %, q021-q025 100 %), MRR 0.77 (+0.057 vs Baseline). Stop-Trigger 4 (R@5 ≥ 0.95) verfehlt um -1 Frage (q004 Gold-Label-Edge-Case) — dokumentierte Ausnahme mit Net-Wins (Tabellen-Recall, MRR, Page-Tracking). Detail siehe Changelog Block 18.

Original-Scope-Beschreibung

Zielversion: v1.0.0 Aufwand: ~18h (neu in Konzept v5.2 §17.2) Abhängigkeiten: keine (parallel zu Phase A/B möglich; produktive Nutzung durch Block 13 und die Konnektoren)

Warum

Der Haystack-Default-Converter linearisiert strukturierte Inhalte: Tabellen-Spalten verschmelzen, Zeilen-Zusammenhänge gehen verloren, Layout-Hinweise werden zerschlagen. Für AVS-Dokumente heißt das konkret: Meldeschein-Feldkataloge, Paragraphen-Listen in Bundesländer-Verordnungen, Gebühren-Tabellen (Kurtaxe × Altersgruppe × Saison) und Fehler-Code-Referenzen werden im Retrieval als Fließtext-Fragmente zurückgegeben, nicht als Tabellen-Zellen mit erhaltenem Spalten-Kontext. Das degradiert die Antwortqualität bei genau den Query-Typen, die in der AVS-Praxis häufig sind.

Ansatz

IBM Docling (MIT-Lizenz, Linux Foundation AI & Data, v2.72.0 Februar 2026) als vorgelagerter Document-Converter. Docling kombiniert DocLayNet (Layout-Analyse, trainiert auf 81k gelabelten Seiten) mit TableFormer (strukturierte Tabellen-Rekonstruktion) und erreicht dokumentiert 97,9 % Tabellen-Extraktions-Genauigkeit. Integration via haystack-integrations/docling, Pipeline-Position vor dem Semantic Chunker. Der Chunker bekommt eine zusätzliche Regel preserve_tables=True — Tabellen-Chunks sind atomar und werden nie geteilt, auch nicht wenn sie max_chunk_chars überschreiten.

Granite-Docling-258M-VLM ist in v1.0.0 nicht Default, sondern Backlog-Kandidat gemeinsam mit VLM Multimodal.

Komponenten

  • Docling-Converter-Einbindung in die Haystack-Pipeline
  • Semantic-Chunker-Erweiterung: preserve_tables=True-Regel, atomare Tabellen-Chunks
  • Qdrant-Payload-Metadaten: chunk_type ("table" | "text" | "figure_caption" | "heading"), docling_version, has_tables
  • Re-Indexing-Job über bestehendes document_versions-Pattern (kein User-Input nötig)
  • Eval-Set-Erweiterung um 5–10 Tabellen-Queries (Gebühren-Tabelle, Meldeschein-Feldkatalog)
  • Grafana-Panel für Chunk-Type-Verteilung

Verweise


Block 19 — BGE-M3 + Hybrid Retrieval 📋 Scoping

Zielversion: v1.0.0 Aufwand: ~25h (neu in Konzept v5.2 §17.2) Abhängigkeiten: Block 18 (soft — BGE-M3 profitiert von Doclings 8192-Token-Kontext, um größere strukturierte Chunks ohne Mittelungs-Verlust abzubilden)

Warum

Das bisherige Embedding-Modell multilingual-e5-large (Mitte 2023) ist technologisch überholt und hat zwei konkrete Retrieval-Lücken: (1) rein semantische Suche ist schwach bei exakten Token-Matches ohne semantisches Signal — Paragraphen-Nummern (§ 23 Abs. 4), Error-Codes (E-1042), Eigennamen/Formular-IDs (ELMA-Kennzeichen); (2) die 512-Token-Kontext-Länge zwingt zu kleinteiligen Chunks, was mit den atomaren Tabellen-Chunks aus Block 18 kollidiert.

Ansatz

BGE-M3 (BAAI, MIT-Lizenz) liefert in einem Modell simultan Dense- (1024d), Sparse- (SPLADE-ähnlich) und Multi-Vector-Embeddings (ColBERT-Style-Late-Interaction). Das ersetzt den ursprünglich separat diskutierten SPLADE-Einschub und den Grep-Search-Fallback durch eine einzige Modell-Komponente. Hybrid-Retrieval über zwei Retriever auf derselben Qdrant-Collection (Dense + Sparse), Fusion via Reciprocal Rank Fusion mit Startgewichten Dense:Sparse = 0.7:0.3 (empirisch via Eval-Suite tunbar). 8192-Token-Kontext (vs. 512 bei e5-large) eröffnet größere, sinnvollere Chunks.

Der bestehende Cross-Encoder-Ranker (mmarco-mMiniLMv2-L12-H384-v1) bleibt final — optional Upgrade auf bge-reranker-v2-m3 für konsistenten Stack (+2h Aufwand).

Komponenten

  • Qdrant-Collection-Schema: Dense + Sparse Vectors in derselben Collection (VectorParams + SparseVectorParams)
  • Embedder-Umstellung auf BGE-M3
  • Dual-Retriever + RRF-Fusion in der Query-Pipeline
  • Re-Indexing-Job über document_versions-Pattern (kein User-Input)
  • Feature-Flag USE_HYBRID_RETRIEVAL (global in v1.0.0, pro Tenant erst ab v1.1.0 via tenant_packages)
  • Eval-Set-Erweiterung um 10 Edge-Case-Queries (Paragraphen, Akronyme, Error-Codes)
  • A/B-Vergleich Dense-only vs. Hybrid auf bestehendem Eval-Set

Verweise


Block 19.5 — Reranker-Upgrade auf bge-reranker-v2-m3 📋 Geplant

Konzept-Anker: §6a.Y — Reranker-Rolle Zielversion: v1.0.0 Aufwand: 6-8h Priorität: Mittel Abhängigkeit: Block 19 abgeschlossen (Production-Cutover live, 2026-05-03)

Was es ist

Wechsel des Cross-Encoder-Rerankers von mmarco-mMiniLMv2-L12-H384-v1 auf BAAI/bge-reranker-v2-m3. Konsistenter BGE-Stack (BGE-M3-Embedder + BGE-Reranker-v2-m3), erwartete Mitigation für Block-19-Phase-3.5 H4-Erkenntnis (Reranker-Bias bei duplizierten Inhalten, q006-MRR-Drift).

Warum jetzt

Block-19-Phase-3.5-Diagnose hat empirisch belegt: der Cross-Encoder- Reranker ist die dominante Komponente für Final-Top-K-Quality (siehe §6a.Y). RRF-Weight-Tuning hat keinen Effekt, weil der Reranker die Top-20-Liste neu sortiert. Reranker-Wechsel ist daher der Hebel mit größtem Quality-Impact, nicht eine inkrementelle Verbesserung.

Akzeptanzkriterien

  • bge-reranker-v2-m3 als Component im Pipeline-Code
  • Phase-3-Style A/B-Eval gegen Block-19-Baseline (R@5=0.96, MRR=0.74)
  • Akzeptanz: MRR ≥ 0.77 (Block-18-Niveau wieder erreicht), R@5 ≥ 0.94
  • q006 spezifisch: RR ≥ 0.5 (Hit auf Top-2 zurück, von aktuellem Top-4)
  • Latenz-Akzeptanz: avg ≤ 200 ms (BGE-Reranker-v2-m3 ist größer als mmarco, +50-100 ms erwartet)

Nicht-Ziel in dieser Karte

  • Embedder-Wechsel — BGE-M3 bleibt
  • Pipeline-Architektur — bleibt unverändert
  • Evaluation-Tooling-Refactor (separate Karte falls nötig)

Stop-Trigger

Wenn A/B-Eval zeigt MRR < 0.74 (Block-19-Niveau) → bge-reranker-v2-m3 wird nicht aktiviert. Mmarco-Reranker bleibt Default. Diagnose-Followup für andere Mitigations.


Block 20 — AST-Aware Chunking 📋 Scoping

Zielversion: v1.0.0 Aufwand: ~13h (neu in Konzept v5.2 §17.2) Abhängigkeiten: Block 18 (Docling liefert die Markdown-Code-Fences, AST-Chunking zerlegt sie semantisch)

Warum

Der Semantic Chunker (Kapitel-Grenzen-Erkennung, Recall@5 = 100 %, MRR = 1.000 auf aktuellem Eval-Set) ist für Prosa-Dokumentation optimal, aber suboptimal für Code-Snippets (Funktionen werden zerschnitten) und strukturierte Inhalte wie JSON/YAML-Schemas oder API-Referenzen.

Aktuell nicht per Eval-Set messbar, weil AVS-Handbücher primär Prosa sind. Block 20 ist Enabler-Feature für Zukunfts-Use-Cases: technische Integrations-Dokumentation bei Multi-Tenant-Kunden, Ticket-Eskalation mit Code-Antworten (Knowledge-Hub-Modul v2.0.0), AVS-eigene Konnektor-Entwickler-Dokumentation (Konzept §13.10).

Ansatz

Tree-sitter-basierter AST-Parser als optionale Strategy via chunk_strategy: "text" | "ast"-Parameter. Default bleibt der Prosa-Chunker für ~99 % der AVS-Inhalte. Auto-Detection pro Chunk-Kandidat: Code-Fences in Markdown werden extrahiert und sprach-spezifisch zerlegt, auch wenn die Source-Datei nicht primär als Code markiert ist.

Unterstützte Sprachen gestaffelt: v1.0.0 Python, JSON, YAML (JSON/YAML für AVS-Schema-Doku und Template-Configs, Python für Integrations-Beispiele). v1.1.0+ TypeScript, SQL je nach Kundenbedarf. Nie C#/Java/Rust/Go (AVS' Tech-Stack umfasst diese nicht).

Komponenten

  • tree-sitter-Dependencies (Python/JSON/YAML in v1.0.0)
  • _ast_chunk()-Utility mit Language-Router
  • Chunk-Grenzen pro Sprache: Python def/class/Top-Level; JSON Top-Level-Objekte; YAML Document-Marker (---) oder Top-Level-Keys. Docstrings werden mit der Funktion gebundelt.
  • Qdrant-Payload-Metadaten: chunk_strategy, ast_node_type, ast_node_name, language
  • Unit-Tests pro Sprache
  • Regression-Test auf bestehendem Prosa-Eval-Set: 100 %-Recall muss erhalten bleiben

Verweise

  • Konzept v5.2 §6a.3 (AST-Aware Chunking, neu in v5.2), Konzept v5.2 §6a.1 (komplementär: Docling liefert Code-Fences, AST-Chunking zerlegt sie)

Block 13 — Konnektor-Subsystem (Framework + Upload + Credentials + Merkle-Sync) 📋 Scoping

Zielversion: v1.0.0 Aufwand: ~57h (Konzept §17.2 v5.2: 48h Basis aus v5.1 + 9h für §13.3a Merkle-Tree-Snapshot-Sync in v5.2) Scope-Erweiterung in v5.2: Dieser Block ist jetzt konzept-konform (§17.2) und bündelt die bisher separat geführten Funktionalitäten (Framework-Stub, Upload-Konnektor, Credentials-Verwaltung, Sync-Scheduler) zu einem Eintrag. Der bisherige separate Upload-Konnektor-Eintrag in Phase C wurde in diesen Block absorbiert. Abhängigkeiten: Block 1 (Connectors-/Credentials-/Sources-Tabellen), Block 4 (Qdrant-Write-Hook), Block 18 (Docling als Normalisierungs-Schicht für Upload und alle konkreten Konnektoren)

Warum

Alle konkreten Konnektoren (Upload, Confluence, MediaWiki) bauen auf demselben BaseConnector-Interface auf. Ohne dieses Skelett würden drei Konnektoren parallel mit dreifachen Ad-hoc-Lösungen gebaut — nicht wartbar und kaum testbar. Das Framework ist außerdem der interne Contract, auf dem die SDK-Stufe 2 (AVS als designierter Zweit-Entwickler, §13.10) aufsetzt.

Ohne den §13.3a-Merkle-Sync würde ein typischer AVS-Tenant mit 5.000 Confluence-Seiten und stündlichem Sync täglich ~120.000 redundante Embedding-Calls produzieren (realistisch ändern sich ~10 Seiten/Tag). Merkle-Tree-Snapshots senken das auf ~250 Calls/Tag (~99,8 % Einsparung auf Embedding- und Qdrant-Write-Last, ~96 % auf Upstream-API-Calls).

Scope — fünf Unterpunkte

  1. Framework-Stub (~8h)BaseConnector-Abstract-Class (§13.2) mit fetch, extract, incremental_sync, on_delete; ConnectorRegistry; Pipeline-Hook; Modul-Registry-Integration (Block 6, Konnektoren registrieren config_schema + credential_schema als Pydantic-Modelle).
  2. Upload-Konnektor (~8h, §13.6, Konnektor-Roadmap §2.1) — Refactoring des bestehenden Demo-Direct-Upload-Flows in ein BaseConnector-konformes Modul; Multi-Tenant-Aware-Umbau; Integration in den Scheduler (trivial, weil manual-triggered). Extraktions-Backends (PDF/DOCX/TXT) bleiben unverändert; sie laufen ab v1.0.0 aber durch Docling (Block 18) statt Haystack-Default.
  3. Credentials-Verwaltung (~20h, §13.7) — AES-GCM-Verschlüsselung mit Master-Key aus Environment, CRUD-Endpunkte auf credentials-Tabelle, strikte Tenant-Isolation, Audit-Logging jeder Änderung. Nur tenant-admin darf CRUDen.
  4. Sync-Scheduler (~12h, §13.3) — Credential-basierter Rate-Limit-Scheduler mit Bucket-Management pro credential_id, Parameter aus connectors.config_schema.rate_limits. Bei 50 parallelen Tenants mit derselben Credential serielle Ausführung statt parallel — verhindert 429-Responses.
  5. §13.3a Merkle-Tree-Snapshot-Sync (~9h, neu in v5.2) — neue Tabelle connector_sync_snapshots (chatbot_source_id, root_hash, document_hashes JSONB, created_at) mit Retention keep_last=3; services/merkle_sync.py mit compute_merkle_root und diff_manifests; Erweiterung von BaseConnector um abstrakte fetch_manifest(source) und content_hash(document); 7-stufiger Sync-Ablauf (Manifest fetchen → letzten Snapshot laden → Root-Hash-Vergleich mit Early-Exit → Diff → nur added ∪ modified re-embedden → removed aus Qdrant löschen → Snapshot persistieren); Unit-Tests; Grafana-Panel avs_connector_sync_changed_docs_total{connector_type}.

Nicht im Scope:

  • Kein öffentliches SDK (SDK-Stufe 3 bleibt Backlog)
  • Keine Reverse-Sync-Mechanik (Antworten zurück in Quelle)
  • Kein Permission-Enforcement zur Laufzeit (Permissions werden in v1.0.0 nur gesammelt, ab v1.1.0 aktiv gefiltert, §13.5)
  • Kein Bulk-Import-UI für Upload (Einzeldatei-Upload reicht für v1.0.0)

Komponenten

  • src/kora_platform/connectors/base.pyBaseConnector + ConnectorRegistry, abstrakte fetch_manifest + content_hash
  • src/kora_platform/connectors/scheduler.pySyncScheduler mit Rate-Limit-Buckets
  • src/kora_platform/connectors/credentials.pyCredentialStore mit AES-GCM
  • src/kora_platform/connectors/upload.py — Upload-Konnektor als erste konkrete Implementierung (Docling via Block 18)
  • src/kora_platform/services/merkle_sync.py — Hash-Map-Diff, Root-Hash-Computation
  • Pydantic-Schemas für config_schema und credential_schema
  • Alembic-Migration: sync_jobs-Tabelle (falls nicht aus Block 1), connector_sync_snapshots-Tabelle
  • Grafana-Dashboards für Sync-Health und Merkle-Diff-Statistiken

Verweise


Block 13b — Confluence-Konnektor 📋 Scoping

Zielversion: v1.0.0 Aufwand: ~40h (aus Konnektor-Roadmap §2.2) Abhängigkeiten: Block 13 (Konnektor-Subsystem-Framework, Upload-Konnektor als Framework-Test)

Warum

AVS hat Confluence-Nutzung bestätigt — das ist kein hypothetischer Bedarf, sondern ein direkter AVS-Workflow. Confluence ist der Erst- Konnektor, mit dem das Konnektor-Subsystem produktiv validiert wird.

Scope

Im Scope:

  • REST-API-Client für Atlassian Cloud + Server/DC
  • Incremental-Sync via CQL lastmodified > "<since>"
  • HTML→Markdown-Konvertierung via BeautifulSoup
  • Permission-Extraktion in permissions.read_groups (in v1.0.0 gesammelt, ab v1.1.0 aktiv gefiltert laut Konnektor-Roadmap §6)
  • Attachment-Handling (50 MB Default)
  • Rate-Limit-Handler (200 req/min Cloud, konfigurierbar)

Nicht im Scope:

  • Kein Reverse-Sync (Chatbot-Antworten fließen nicht zurück in Confluence)
  • Kein Confluence-Server-SSO-Proxy

Verweise


Template-Inhalte von AVS 📋 Scoping

Zielversion: v1.0.0 Aufwand: wartend auf AVS-Beistellung (ca. Woche 4–5 des Projekts) Abhängigkeiten: Template-Verwaltung (Phase B), Block 3

Warum

Das sind die eigentlichen Plattform-Inhalte, mit denen die erste Produktiv-Nutzung startet. Meldeschein- und Kurverwaltungs-Templates sind AVS-Kernexpertise — die prompts, suggestions und evaluation-questions dafür können nur von AVS kommen, nicht von luki.

Scope

Im Scope:

  • Meldeschein-Template mit System-Prompt, Suggestions, recommended-connectors und 20 Evaluation-Questions
  • Kurverwaltungs-Template analog
  • Handover-Dokument für AVS: "So beschreiben Sie ein Template"

Nicht im Scope:

  • Kein luki-seitiges Prompt-Engineering (wenn AVS etwas will, machen sie das selber)
  • Keine A/B-Tests

Offene Fragen

  • Evaluation-Questions-Format: AVS liefert JSON oder SQL-Snippets oder händisch über die Template-Verwaltung? Standing: JSON, luki importiert einmalig.
  • Wer pflegt Templates nach Go-Live weiter? AVS-Operator-Admin selber (über Template-Verwaltung-UI aus Phase B) — das erzeugt die Dependency in die andere Richtung.

Phase D — Deployment, Migration & Go-Live

Deployment-Paket, Migrationspfad vom heutigen Demo-Stand und Go-Live-Operations. Strategie "frische Leinwand" aus Fundament §15a.4: keine Daten-Migration, nur Seed-Skripte plus DNS-Switch.

Block 14 — Deployment-Paket & Update-Mechanismus 📋 Scoping

Zielversion: v1.0.0 Aufwand: ~20h (Konzept §17.2 — inkl. Parallel-Dev-Setup, §15a) Abhängigkeiten: keine — kann parallel zu Phase B/C laufen

Warum

AVS muss das Update selbst fahren können, ohne luki-Shell-Zugang. Signiertes Artefakt, klare CLI, dokumentiertes Runbook — das ist die Voraussetzung dafür, dass der Betrieb nicht auf Dauer an luki hängt. Parallel dazu muss das Parallel-Dev-Setup (§15a.2) auf luki-ai laufen, sonst blockiert Phase A/B/C nicht die Demo.

Scope

Im Scope:

  • Docker-Compose + Images auf privater Registry (kora-platform-*)
  • kora-platform update-CLI (Download-Verify-Apply-Rollback)
  • Alembic-Migration als Bestandteil des Update-Pfads
  • Rollback-Snapshot-YAML pro Version (Images + DB-Dump-Hinweis)
  • Runbook: Install, Update, Backup/Restore, Troubleshooting
  • Keycloak-Init-JSON-Exports (§15.4) im Artefakt enthalten
  • SMTP-ENV-Variablen-Template für Produktiv-SMTP (analog MailHog-Dev)
  • Install-Skript (NPMplus-Routing, Subdomain-Setup dokumentiert)

Nicht im Scope:

  • Kein öffentlicher Release-Channel (nur private Registry für AVS)
  • Keine automatische Backup-Rotation (AVS verwaltet Backups extern)
  • Kein Zero-Downtime-Deploy (kurzer Wartungsfenster beim Update ok)

Verweise


Block 15 — Migration vom heutigen Stand & Go-Live 📋 Scoping

Zielversion: v1.0.0 Aufwand: ~12h (Konzept §17.2 — die einzelnen Go-Live-Operations- Unterpunkte unten liegen innerhalb dieses 12h-Budgets gemäß §15a; die vor-v5.1-Scoping-Einträge "Smoke-Tests", "Monitoring-Erweiterung", "DNS-Switch-Prozedur", "7-Tage-Observation" sind hier als Scope- Breakdown zusammengeführt) Abhängigkeiten: Phase C komplett, Block 14

Warum

"Frische Leinwand" statt Daten-Migration reduziert Migrations-Komplexität und Edge-Case-Behandlung für inkonsistente Demo-Altdaten. Go-Live via DNS-Switch braucht klare Rollback- Kriterien, die vor dem Switch definiert sind — nicht währenddessen entschieden. Sieben Tage Observation-Phase erfassen zwei volle Wochenverläufe plus ein Wochenende, reicht für das Vertrauen zum Demo-Abschalten.

Scope

Im Scope (Breakdown entsprechend §15a.5 / §15a.6):

  • Seed & Smoke mit AVS-Testdaten: Alembic 008 + Seed-Skripte erzeugen Plattform-Grundkonfiguration (Default-Tenant "AVS-Intern", Meldeschein- und Kurverwaltungs-Chatbot, Shared-Collection befüllt); Smoke-Run über 20 Queries Meldeschein + 20 Kurverwaltung; Latenz-SLO-Verifikation p50/p90/p99 < 3.5 s / 5 s / 8 s; Recall@5 ≥ 0.85 und MRR ≥ 0.60 gegen die AVS-Ground-Truth
  • Monitoring-Erweiterung: Prometheus-Scrape-Targets für kora-platform-api, -postgres, -qdrant, -keycloak; Grafana-Dashboard mit deployment="platform"-Label analog zur Demo; Per-Tenant-Query-Volume-Panel
  • DNS-Switch-Prozedur: Runbook mit NPMplus-Regel-Aktivierung, TTL-Reduktion auf 60 s 24 h vorher, DNS-CNAME-Umstellung, Verifikations-Queries; Rollback-Kriterien vor dem Switch fixiert (Latenz-p90 > 8 s für 5 min, Error-Rate > 1 % für 5 min, oder manuelle Eskalation durch AVS); Rollback-Prozedur: DNS-CNAME zurück, NPMplus-Regel zurück, Alert
  • 7-Tage-Observation: tägliche Alerts-Durchsicht, Error-Rate- Check, Qualitäts-Spot-Check (5 zufällige Queries), Session-Volume- Vergleich zu Demo-Baseline; nach Tag 7 Demo-Container stoppen, nach weiteren 30 Tagen löschen (Data-Retention-Policy)

Nicht im Scope:

  • Keine Live-Daten-Migration (bewusste "frische Leinwand"-Strategie, §15a.4)
  • Kein automatisches Rollback (Entscheidung bleibt menschlich)
  • Kein Chaos-Engineering (v1.x-Kandidat)

Verweise


Block 16 — Testing & Dokumentation 📋 Scoping

Zielversion: v1.0.0 Aufwand: ~30h (Konzept §17.2 — inkl. AVS-Konnektor-Entwickler- Guide, §13.10) Abhängigkeiten: Phase A, B, C komplett (Testing deckt alle Schichten ab)

Warum

Multi-Tenant-Isolation muss automatisiert nachweisbar sein — nicht nur "wir haben Code dafür", sondern eine Test-Suite, die Cross- Tenant-Leaks reproduzierbar ausschließt. Der AVV-Anhang mit TOM-Katalog ist AVV-Pflicht. Der AVS-Konnektor-Entwickler-Guide ist Liefergegenstand der SDK-Stufe 2 und macht AVS als designierten Zweit-Entwickler handlungsfähig (§13.10).

Scope

Im Scope:

  • Cross-Tenant-Isolationstests als Integration-Test-Suite unter tests/integration/platform/
  • End-to-End-Tests der Hauptflows (Tenant anlegen → Chatbot erstellen → Konnektor konfigurieren → Query stellen)
  • Runbook-Finalisierung (Install, Update, Backup, Troubleshooting, Break-Glass-Pfad)
  • AVV-Anhang "Technische und organisatorische Maßnahmen" (Markdown in docs-kora/, abgeleitet aus Bitkom-Muster-AVV)
  • AVS-Konnektor-Entwickler-Guide (Markdown in docs-kora/, §13.10)

Nicht im Scope:

  • Kein öffentliches SDK-Paket (SDK-Stufe 3 bleibt Backlog)
  • Keine Benutzer-Schulung durch luki (AVS trainiert selbst)

Verweise


Phase E — Post-Launch: Tenant-SSO-Self-Service (v1.0.1 / v1.1.0)

Status: geplant, startet nach Go-Live v1.0.0 Aufwand: ~49h Abhängigkeiten: v1.0.0 produktiv, erste 1–2 Tenants per Operator- oder Breakglass-Pfad durchgegangen (Erfahrungswerte für UI)

Rationale: Das Architektur-Fundament (Realm-Struktur, IdP-Fähigkeit) ist in v1.0.0 bereits gelegt — siehe Konzept §2.6 und §15.4. Die Self-Service-UI wird nach ersten Produktionserfahrungen ergänzt.

Diese Phase entspricht Phase D im Fundament-Konzept §18 — in der Roadmap ist sie als Phase E geführt, weil Phase D hier den Go-Live bezeichnet.

Block 17 — Tenant-SSO-Self-Service ⏳ Geplant

Zielversion: v1.0.1 / v1.1.0 (Post-Launch) Aufwand: ~49h Abhängigkeiten: v1.0.0 produktiv

Warum

Jede Kurverwaltung hat einen eigenen Identity-Provider (meist Microsoft Entra ID, seltener ADFS, Google Workspace, generisches OIDC/SAML). In v1.0.0 wird SSO-Setup manuell durch den Operator oder per Breakglass-Zugriff durch luki gemacht. Für nachhaltige Skalierung muss der Tenant-Admin das selbst können, ohne auf AVS oder luki warten zu müssen. Die Keycloak-Architektur in v1.0.0 ist bereits IdP-fähig — Block 17 legt nur die UI/UX darauf, keine Änderungen am Fundament.

Scope

Im Scope:

  • IdPProvisioningService als gemeinsame Backend-Komponente für alle drei Konfigurations-Pfade (Tenant-Self-Service, Operator-"Im Auftrag", Luki-Breakglass), siehe Konzept §21.2
  • Fünf Preset-Templates mit hart verdrahtetem First-Broker-Login-Mapper:
    • Microsoft Entra ID / Azure AD (OIDC)
    • Microsoft ADFS (SAML)
    • Google Workspace (OIDC)
    • Generisches OIDC (Power-User)
    • Generisches SAML (Power-User)
  • REST-API POST/GET/DELETE /api/v1/tenants/{id}/idp + POST /api/v1/tenants/{id}/idp/test (Metadata-Fetch)
  • Tenant-Admin-UI (Vue 3: Wizard + Detail-Ansicht)
  • Operator-UI-Erweiterung um "Im Auftrag"-Banner (wiederverwendet, minimaler Zusatz)
  • Integration-Tests mit Mock-Keycloak für Entra ID + generisches OIDC
  • Operator-Runbook "Tenant-SSO einrichten (Notfall-/Luki-Pfad)" als Fallback-Dokumentation

Sicherheits-Zusicherungen:

  • First-Broker-Login "Create User If Unique" verhindert Cross-Tenant-Account-Linking — aus Konzept §2.6 und §15.4
  • IdP-to-Group-Mapper ist vom Backend fest verdrahtet, nicht durch Tenant-Admin editierbar
  • Neue Shadow-User bekommen Default-Rolle tenant-viewer; höhere Rollen (editor/admin) vergibt der Tenant-Admin explizit pro User
  • Operator-Aktionen im "Im Auftrag"-Pfad werden zusätzlich im platform_audit_log protokolliert (neben dem Keycloak-Event)

Nicht im Scope:

  • Keine automatische User-Synchronisation (SCIM) — Shadow-User entstehen bei First-Login on-demand, das reicht für v1.x
  • Kein Just-In-Time-Role-Mapping (JIT) auf IdP-Gruppen — Rollenvergabe bleibt explizit im Tenant-Admin-UI, um Überraschungen zu vermeiden
  • Keine Multi-IdP-Kombination pro Tenant (ein Tenant = ein IdP)

Offene Fragen

  • Preset-Zahl verifizieren, sobald erste Tenants live sind: wird wirklich alles außer Entra ID zur Ausnahme, oder sind ADFS und Google Workspace ähnlich häufig?
  • UI-Sprache: Wizard komplett deutsch, oder englisch für IdP-Terme (SAML, OIDC, Assertion Consumer URL)?
  • Metadata-Refresh-Intervall bei OIDC/SAML-Providern — 24h oder manuell per "Verbindung testen"-Button?

Verweise


Backlog 💭

Themen, die nicht in v1.0.0 geplant sind. Einige werden später ein eigenes Release, andere bleiben permanent optional. Kontext pro Eintrag, aber weniger Detail als Phase-Themen — das sind Platzhalter, keine Pläne.

Lizenz-Server Stufe 2

Zielversion: v1.1.0+ Trigger: Akquise eines Kunden außerhalb AVS

Server-seitige Lizenzkontrolle, Doppelnutzungs-Erkennung, Remote-Widerruf. Aktuell redundant, weil AVS selbst betreibt und vertragliche Regelung reicht. Bei externem Kunden wird die Technik relevant, weil kein AVV mehr zwischen luki und dem Betreiber steht, der das vertraglich abfedert.

Unsloth Fine-Tuning (Global-Baseline)

Zielversion: v1.1.0+ Aufwand: ~64h (inkl. Dataset-Kurierung) Abhängigkeiten: Block P1 (Speculative-Baseline als Referenz), v1.0.0 Multi-Tenancy

LoRA-Fine-Tuning eines kleineren Basis-Modells (Qwen3-4B oder 8B) auf AVS-Domänen-Daten. Ziel: Qualität von Qwen3-14B bei 1/3 der Latenz. Risiko: Qualitäts-Regression ist Default bei kleinen fine-getunten Modellen — eine robuste Evaluation-Suite (aus Phase D vorhanden) ist zwingende Voraussetzung, bevor produktiv geswitcht wird.

Dataset-Kurierung ist der harte Teil: AVS-Dokumente + echte Session-Queries + manuell gelabelte Antworten, mindestens 1000 Samples. Ohne Dataset kein sinnvolles Fine-Tuning.

Strategische Hinweise (aus NVIDIA-Playbook-Recherche)
  • LoRA-Adapter pro Tenant: Bei v1.0.0-Multi-Tenancy denkbar — pro Tenant ein eigener LoRA-Adapter mit tenant-spezifischen Domänen- Daten. Inferenz-Switch über Adapter-ID, kein Modell-Reload nötig. Siehe auch Backlog-Eintrag "Custom-LoRA-Adapter-Modul" (v1.3.0+).
  • Kombination mit Speculative Decoding (Block P1): fine-getuned Qwen3-1.7B als Draft-Modell + Qwen3-14B-Base als Target. Bestes aus beiden Welten — Draft kennt Domänen-Vokabular, Target ist robust.
  • Aufwand-Realität: 40–80h inklusive Dataset-Kuratierung, Evaluation, Regression-Tests. Eval-Suite ist Vorbedingung (siehe bestehender Eintrag).
  • Tooling: Unsloth bringt 2× schnelleres Training durch Triton-Kernel, 4-Bit-QLoRA passt auf eine einzelne 4090, Gradient-Checkpointing "unsloth"-Modus → 30 % weniger VRAM.

Custom-LoRA-Adapter-Modul

Zielversion: v1.3.0+ Aufwand: noch nicht geschätzt Abhängigkeiten: Unsloth-Baseline-Fine-Tune

Platform-Modul, das pro Tenant einen eigenen LoRA-Adapter laden lässt. vLLM unterstützt Multi-LoRA-Serving nativ (--enable-lora). Produkt-Feature: "Ihr Chatbot lernt von Ihrem Team".

Architektonischer Platzhalter im Konzept §8 (Plattform-Module) sollte vor v1.1.0 aufgenommen werden, damit das Modul-Schema darauf vorbereitet ist — sonst retrofitting-Kosten.

VLM Multimodal (Qwen2.5-VL)

Zielversion: v1.2.0 Aufwand: ~40h (zzgl. DSGVO-Review) Blocker: Nutzungs-Volumen-Daten aus v1.0.0-Produktivbetrieb + AVS-Datenschutzbeauftragten-Freigabe

Neuer /api/v1/query/multimodal-Endpoint, neuer vLLM-VLM-Container. Use-Cases: Meldeschein-Screenshot, Ausweis-Foto, UI-Hilfe-Screenshots.

PII-Handling ist kritisch — striktes Non-Persistence-Design (Bild wird nur für die Query-Lebensdauer im RAM gehalten, nicht in Qdrant und nicht auf Platte). AVS-DSB-Freigabe ist vor Scope-Finalisierung zwingend.

Konkrete Use-Cases (aus AVS-Domänen-Mapping)
  • Meldeschein-Foto: Hotelmitarbeiter fotografiert ein verwirrendes Meldeschein-Feld → Bot erklärt, welche Information dort hineingehört.
  • Fehlermeldung-Screenshot: Screenshot einer Fehlermeldung → Bot gibt Handlungsanweisung statt nur Fehlertext zu erkennen.
  • Personalausweis-Frage: Foto eines Ausweises mit "welcher Ländercode gehört hier rein?" — Bot identifiziert Ausweistyp und liefert Code-Tabelle aus Handbuch.
Architektur-Skizze
  • Eigenständiger Endpoint /api/v1/query/multimodal — nur aktiv, wenn User Bild anhängt.
  • Kein Overhead für Text-Queries — Standard-Pipeline unangetastet.
  • Modell-Kandidat: Qwen2.5-VL-7B-Instruct-FP8 (OpenAI-API-kompatibel via vLLM).
  • Vorbedingung: AVS-DSB-Clearance für Bild-Daten-Verarbeitung (sensiblere Datenkategorie als Text).

OCR-Preprocessing (leichtere Alternative zu VLM)

Zielversion: v1.1.0+ Aufwand: ~15h Abhängigkeiten: keine

PaddleOCR (multilingual) oder Tesseract als Text-Extraktions-Stufe vor der bestehenden Text-Pipeline. Löst vermutlich 60–70 % der "Text-aus-Bild-lesen"-Use-Cases mit 10 % der VLM-Komplexität. Kann als Parallel-Pfad zu VLM existieren oder VLM komplett ersetzen — die Entscheidung fällt anhand der Produktivdaten aus v1.0.0.

SharePoint-Konnektor

Zielversion: v1.1.0+ (Welle-2) Aufwand: ~80h

Microsoft 365 Graph API, komplexes Permission-Modell mit Azure-AD-Groups + Site-Groups + Vererbung, Office-Content-Extraction für .docx/.xlsx/.pptx. Priorisierung hängt an AVS-Feedback: ist SharePoint in den Kurverwaltungen dominant, oder eher Confluence?

Teams-Konnektor

Zielversion: v1.1.0+ (Welle-2-Kandidat, Welle-3 in Konnektor-Roadmap) Aufwand: ~80h

Chat-Inhalte sind rauschig — 80 % belanglose Nachrichten, 20 % wertvolles Wissen. Vor der Implementierung: Rausch-Filter-Strategie klären (nur Thread-Root-Posts, nur Nachrichten >20 Worte, Opt-In pro Channel).

Jira-Konnektor

Zielversion: v1.1.0+ (Welle-2-Kandidat) Aufwand: ~50h

Tickets enthalten oft kritisches operatives Wissen (bekannte Bugs, Lösungswege). Jedes Ticket wird ein Dokument, Kommentare als Abschnitte. Permissions via Jira Project Permissions (einfacher als SharePoint).

MCP-Konnektor-Source-Type

Konzept-Anker: §13.6a — MCP als Source-Type Zielversion: v1.1.0 Aufwand: 40–60h Priorität: Mittel Abhängigkeit: v1.0.0 Multi-Tenancy-Fundament

Was es ist

Generischer mcp_connector-Source-Type parallel zu existing upload, confluence, sharepoint. Statt jeden neuen Konnektor von Grund auf zu bauen, können MCP-Server (Confluence, Jira, Notion, Slack, beliebig) als standardisierte Quellen angebunden werden.

Warum es wertvoll ist

  • Konnektor-Aufwand reduziert: Confluence-Konnektor war ursprünglich ~60h Eigenentwicklung. Mit MCP-Confluence-Server-Integration schrumpft das auf ~10–15h.
  • Standardisierte SDK-Stufe-2-Surface: AVS als designierter Zweit- Entwickler hätte mit MCP einen dokumentierten Industriestandard statt proprietärem Contract.
  • Multiplikator-Effekt: Ein generischer mcp_connector erlaubt beliebige zukünftige Quellen ohne Code-Anpassung.

Vorbedingungen (aus Konzept-Stub §13.6a)

Drei strukturelle Fragen müssen vor Implementierung geklärt sein:

  1. Vierter Type oder Meta-Type? mcp_connector parallel zu confluence/sharepoint, oder ist confluence ein Spezialfall von mcp_connector?
  2. Tenant-Isolation: Eigene MCP-Server-Instance pro Tenant oder shared mit Tenant-Header?
  3. Bulk-Ingestion vs. Tool-Use: Bulk-Sync über MCP hat Protokoll- Overhead — eigener Rate-Limit-Scheduler bleibt sinnvoll, MCP nur für inkrementelle Updates?

Akzeptanzkriterien

  • mcp_connector als Source-Type registriert, parallel zu existing Types
  • Mindestens ein MCP-Server angebunden (Beispielimplementierung Confluence-MCP)
  • Multi-Tenant-Isolation funktioniert analog zu existing Source-Types
  • Eval-Suite mit MCP-Source bestätigt Retrieval-Quality vergleichbar zu Native-Confluence-Konnektor

NVFP4-Quantisierung Benchmark

Zielversion: Backlog v1.0.0/v1.1.0 Aufwand: 4–6h Priorität: Niedrig Abhängigkeit: 5090-Node aktiv (bereits gegeben)

Was es ist

NVFP4 ist Blackwell-native 4-Bit-Quantisierung. NVIDIA liefert nvidia/Qwen3-14B-FP4 direkt als HuggingFace-Checkpoint. Aktueller 5090-Node läuft mit AWQ-INT4 (~9 GB), NVFP4 würde ~7 GB ergeben mit nativen Tensor-Core-Kerneln.

Erwartung

  • Single-Query-Speedup: Marginal (AWQ ist bereits gut tuned).
  • KV-Cache-Headroom: Mehr Platz für parallele Requests.
  • Concurrency: Höher (mehr Sequences gleichzeitig möglich).

Akzeptanzkriterien

  • Benchmark NVFP4 vs. AWQ-INT4 auf 5090-Node mit Test-Set-Queries
  • Latenz-Vergleich (p50/p95) und Concurrency-Vergleich
  • Entscheidung: Wechsel ja/nein basierend auf Headroom-Gewinn
  • Bei "ja": Switch dokumentiert, Rollback-Pfad zu AWQ-INT4 erhalten

Nicht-Ziel

NVFP4 für 4090-Node — Ada Lovelace unterstützt NVFP4 nicht hardware- seitig. Bleibt AWQ-INT4 auf der Backup-Inferenz.

Knowledge-Hub-Modul

Zielversion: v2.0.0 Aufwand: ~170h Abhängigkeiten: 2–3 Monate AVS-Feedback aus v1.0.0-Produktivbetrieb

Such-First-UI neben dem Chatbot, eigene Vue-3-SPA mit Bookmarks, Verlauf, Dokumenten-Zusammenfassungen. Bewusste Lernphase vor dem Bau: Ohne echte Nutzungsdaten können wir nur raten, ob das Paradigma angenommen wird. Siehe Knowledge-Hub-Konzept.

Ticket-Eskalation-Integration

Zielversion: v1.1.0+ Aufwand: ~40h

Output-Pfad (Chatbot eskaliert Anfragen an externes Ticket-System). Unabhängig vom Konnektor-Framework, weil Input-vs-Output-Architektur. Integration mit Jira / Freshdesk / E-Mail — hängt davon ab, welches Ticket-System AVS intern nutzt.

Erweiterung — Corrective-RAG / Grader-Stage (Konzept §6a.X)

Konzept-Anker: §6a.X — Corrective-RAG / Grader-Stage Zielversion: v1.0.0 Aufwand: +10–15 h zu dieser Karte

Optionale fünfte Pipeline-Stage zwischen Ranker und LLM, die Confidence proaktiv prüft via Grader-Prompt. Statt nur reaktiver Eskalation ("Button klicken wenn nicht zufrieden") eskaliert das System selbst, wenn der Grader niedrige Confidence anzeigt.

Pipeline-Erweiterung:

Ranker → Grader (LLM-light) → {
    confidence_high  → LLM-Generation (Standard-Pfad)
    confidence_low   → Eskalations-Pfad (Ticket-Hand-off, diese Karte)
}

Drei Vorbedingungen aus Konzept-Stub:

  1. Verhältnis zum existing no_match_threshold=0.10 klären (Ergänzung oder Replacement?).
  2. Latenz-Budget validieren (Grader-Call addiert ~200 ms zu aktuell 2–6 s End-to-End).
  3. Multi-Tenant-Customization (pro Tenant aktivierbar, Grader-Prompt pro Domäne customizable?).

STT / TTS-Integration

Zielversion: v1.1.0+ Aufwand: ~25h STT + ~15h TTS

Voice-I/O für das Widget. Sachbearbeiter am Tresen, am Telefon, auf Mobile — Sprache ist der natürliche Kanal. faster-whisper ist ohnehin für Zoom-Transkript-Konnektor-Welle-4 vorgesehen.

Kubernetes-Migration

Zielversion: v1.x+ Aufwand: ~80h

Bei Skalierungs-Bedarf ab ~10+ Tenants oder SLA-Kunden. Für 5–20 Tenants laut Fundament §6.4 noch nicht nötig — Docker Compose reicht. Vorher kein Aufwand, weil K8s-Operational-Cost signifikant über Compose liegt.

Öffentliches Konnektor-SDK (Stufe 3)

Zielversion: langfristig, Trigger: Ökosystem-Bedarf außerhalb AVS Aufwand: ~200h

Aktuell Stufe 2 (AVS als designierter Zweit-Entwickler, stabile interne API, kein öffentliches SDK — siehe Konnektor-Roadmap §7.4). Stufe 3 erfordert öffentliche Doku-Site, PyPI-Publikation, Zertifizierungs-Prozess, Security-Review-Pipeline.


Änderungen an dieser Roadmap

Datum Commit Änderung
2026-04-20 63454d6 Initiale Roadmap-Version nach Block 1 + MkDocs-Umzug
2026-04-20 dc62ccd Detail-Ausbau aller Blöcke und Themen (Warum/Ansatz/Komponenten), NVIDIA-Tracks integriert (Block P1 in Phase A, Unsloth/VLM/OCR/Custom-LoRA im Backlog)
2026-04-21 a0e5816 Phase E (Post-Launch, Block 17 Tenant-SSO-Self-Service) ergänzt nach Konzept v5 (§2.6, §15.4, §17.4, §21)
2026-04-21 7142ff8 Block 2 ✅ (Commit 2c57172, 20h inkl. vorgezogenem FastAPI-Skelett) — alter Block 2 (FastAPI) + alter Block 3 (Keycloak) zusammengeführt. Block 3 (API Scope-Middleware) von 20h auf 12h reduziert. Fortschritt 48/384h (~12,5 %). Monolith-Architektur als §9.3 im Konzept klargestellt (v5.1).
2026-04-21 2a41381 Korrektur Block-3-Aufwand-Fußnote: die zweite −4h-Gutschrift aus 7142ff8 ("Keycloak-Auth aus Block 2 schon da") war optimistisch. Code-Inventur zeigte 0 wiederverwendbare JWT/JWKS/Auth-Middleware-Zeilen. Reale Gutschrift nur −4h FastAPI-Skelett; Block 3 bleibt bei 12h (Konzept-Baseline 16h). Doppelbuchung "minus ~2h Überschneidungen" aus der Fortschritts-Sektion entfernt — Phase-A-Rest jetzt korrekt 60h.
2026-04-21 dieser Block 3 ✅ (Commit d18a1fc, Merge f558a38, real ~7h) markiert. Session-Pool-Benchmark 4eb764f (Merge 8439210) als Vorarbeit referenziert. Drei Cleanup-Runden als neuer Abschnitt "Zwischenstand-Aufräumen": Pre-Block-4 (da461d6), mkdocs-Hygiene (6e43f71), Cleanup-02 (610f459). Status-Box + Fortschritt auf 55/384h (~14 %). Nur noch TODO-B2-03 offen. Block 4 (Qdrant Collection-per-Tenant) als nächster.
2026-04-22 dieser Block 4 ✅ (Merge f21c030, real ~32h) und Block 5 ✅ (einstufig, relationale tenant_modules, real ~10h) markiert. Phase A abgeschlossen (55+32+10 = ~97/384h, ~25 %). Status-Box auf "Blocks 1-5 complete", nächster Block 6 (Operator-UI). Block-5-Abschnitt neu angelegt mit Commits 1eacd12, 58c20a2, 9dcc05b, 6831d3a. Runbook deployment/platform-modules.md ergänzt (§8 einstufig, Schema-Divergenz tenant_modules vs. Konzept-Array dokumentiert).
2026-04-23 23a9b10 Strukturelle Synchronisierung mit Konzept §17.2: alle 16 Blöcke + Block 17 + Block P1 als eigene Roadmap-Einträge geführt, 1:1 mit Konzept-Titeln und Aufwänden. Phasen-Gruppierung beibehalten (A/B/C/D/E), aber Phase-Namen auf "UIs & Automation" (B) und "Deployment, Migration & Go-Live" (D) präzisiert. Block 4 Titel auf "Qdrant Collection-per-Chatbot + Shared" angepasst (Konzept §6.1). Bestehender Block 5 "Plattform-Module" zu Block 6 umnummeriert; neuer Block 5 "Chatbot-Templates & CRUD" eingefügt. Bisherige Phase-B/D-Scoping-Einträge (Admin-Dashboard, Tenant-Provisioning-Flow, Template-Verwaltung, Vendor-Audit-Log-UI, Smoke-Tests, Monitoring-Erweiterung, DNS-Switch, 7-Tage-Observation) in die entsprechenden Blöcke 7/8/9/12/15 überführt. Widget-Integration wandert von Phase C nach Phase B (Block 11). Status-Emojis unverändert — Status-Sync folgt in separatem Commit.
2026-04-23 86a211f Status-Sync als Folge des Struktur-Sync (23a9b10). Block 4 (Qdrant Collection-per-Chatbot + Shared) ✅ mit Merge-Hash f21c030, Real-Aufwand ~32h, Runbook-Referenz deployment/qdrant-collections.md und Phase-D.1-uses_shared_docs-Gate-Hinweis (90e96f8, Fundament §6.2). Status-Box "Aktuelle Phase" + "Nächste geplante Blöcke" + "Abgeschlossen" auf neue Nummerierung aktualisiert (Block 5 Chatbot-Templates & CRUD jetzt offen, Block 6 ex-Plattform-Module ✅). Fortschritts-Box: Erledigt-Liste umnummeriert (Block 6 statt Block 5 für die ~10h), Phase-A-Restaufwand auf 16h (Block 5). Zwischenstand-Aufräumen um 22.–23.04.-Merges ergänzt. offene-todos.md — TODO-Block-4c-Abhängigkeit präzisiert, TODO-Block-5b Operator-UI-Referenz auf Block 7 aktualisiert, TODO-Block-5f analog. Nummerierungs-Hinweis als Block-Vorbemerkung zu "Aus Block 5 Phase E Code-Review" ergänzt (TODO-IDs bleiben als stabile Identifier). Progress-Zahl ~97h/384h (~25 %) unverändert — nur Zuordnung zum Block-Identifier wechselt.
2026-04-23 bb8fa4c Integration der Konzept-v5.2-Quality-Einschübe (Commit eb02fc9): drei neue Blöcke 18 (Docling, 18h), 19 (BGE-M3 + Hybrid Retrieval, 25h), 20 (AST-Aware Chunking, 13h) in Phase C vor Block 13 eingefügt. Block 13 konzept-konform expandiert zu "Konnektor-Subsystem (Framework + Upload + Credentials + Merkle-Sync)", Aufwand ~48h → ~57h (Konzept §17.2 v5.2: 48h Basis + §13.3a Merkle +9h). Bisheriger separater Upload-Konnektor-Eintrag in Block-13-Scope absorbiert (ersatzlos als eigene H3 entfernt). Phase-C-Header auf "Konnektoren, Quality & Templates-Content" erweitert, Einleitung begründet Block-Reihenfolge. Progress-Nenner 384h → 449h; Progress-Zahl ~97h unverändert, resultierender Anteil ~25 % → ~22 % (rechnerische Konsequenz der Nenner-Erweiterung, keine Regression). Status-Box "Aktuelle Phase" auf "Phase B+C Scoping" erweitert, Version-Hash auf 6472869 (Status-Sync-Merge-HEAD). Phase-C-Reihenfolge jetzt 18 → 19 → 20 → 13 → Confluence → MediaWiki → Template-Inhalte (7 Einträge total, war 5 mit separatem Upload). Gesamt-Block-H3-Zahl: 21 (Blöcke 1–20 + P1 + 17).
2026-04-24 966a578 Roadmap-Sync v3: Block 5 Scope erweitert um 7a UI-Framework-Scaffolding (16h → ~28h, Konsequenz aus Konzept v5.3 Block-7-Split); Block 7 reduziert auf Content-only (7b, 32h → ~20h; Ist-Basis war 32h, nicht 28h wie im Prompt angenommen); MediaWiki-H3-Eintrag aus Phase C entfernt (per Konzept v5.3.1 auf v1.1.0 verschoben, Cross-Link zu Konnektor-Roadmap §2.3 in Phase-C-Einleitung); v1.0.0-Budget von 449h auf 425h reduziert (Konzept-Header und Roadmap-Fortschritts-Box konsistent). Phase-A-Restaufwand von 16h auf ~28h angehoben (Block-5-Erweiterung um 7a). Status-Box: Version-Hash auf fceee19 (v5.3.1-MediaWiki-Merge-HEAD), Aktuelle-Phase-Text inkl. 7a-Scaffolding-Hinweis. Konzept-Patch v5.3.1 → v5.3.2 im selben Commit (atomare Konsistenz: Konzept-Header Aufwand-Zeile + Änderungshistorie v5.3.1 → v5.3.2).
2026-04-24 dieser Block-5-Status-Sync nach Merge 2a3e5b0. Block 5 (Chatbot-Templates & CRUD inkl. 7a UI-Framework-Scaffolding + TODO-4c-Auflösung) auf ✅ Erledigt, Detail-Block mit allen vier Sub-Commit-SHAs (7753067, f09b8ef, 85203db, c898d85) und Merge-Hash. Status-Box: "Aktuelle Phase" auf "A — Fundament abgeschlossen; Phase B bereit", "Abgeschlossen" um Block 5 erweitert, "Nächste geplante Blöcke" auf Block 7 (7b Content), Block 8, Block P1. Fortschritts-Box: Erledigt-Summe ~97h → ~125h (+28h Block 5), Anteil ~23 % → ~29 %; Phase-A-Restaufwand auf 0h. Phase A komplett. offene-todos.md: TODO-Block-4c als erledigt markiert (Commit c898d85, PlatformRetrieval zwei-stufiger Shared-Collection-Gate), Eintrag als Historie erhalten.
2026-04-24 4a19966 Block-5-Cleanup (Branch platform/block-5-cleanup-audit-delta): TODO-Block-5b / -5c / -5d geschlossen. Audit-Action differenziert (assigned/re_enabled/reassigned), POST liefert REST-konform 201 bei Create und 200 bei Update, assign_to_tenant auf race-safen Upsert (ON CONFLICT DO UPDATE RETURNING xmax = 0) umgestellt. 21/21 Unit + 4/4 Integration (inkl. 20×-asyncio.gather-Race-Test) + 11/11 Smoke. Ein Deferred-Finding TODO-Block-5g (Score 40, updated_at im SET-Dict fehlt). Kein neuer Alembic-Change, kein Scope-Expansion (TODO-5e/-5f bleiben post-Block-7). Fortschrittszahl unverändert (Cleanup, kein Block-Progress).
2026-04-24 287a292 Block 7.1a abgeschlossen (Branch platform/block-7-1a-tenants-backend): Operator-Tenants-CRUD-Backend unter /api/v1/platform/tenants/* mit Audit-Events tenant.created/.updated/.soft_deleted. Neuer Keycloak-Public-Client operator-ui im kora-platform-Realm (PKCE S256, Dev-Port 5174, Prod-Path /admin/operator/*). Audit-Helper write_module_auditwrite_platform_audit umbenannt (Prep für 7.2/7.3/7.4). Alte Block-3-Test-Route GET /admin/tenants ersetzt; smoke-block3 nachgezogen. 23/23 Unit + 7/7 Integration + 12/12 Smoke + Block-5-Regression 25/25 + Block-3-Smoke 12/12. Code-Review-Ergebnis: 0 Findings ≥ 80, 7 Deferred <80 als TODO-Block-7-01 .. -07. Neuer Integration-Learning L-B5-01 (SQLAlchemy Identity-Map vs. RETURNING) und L-B7-01 (.local-TLD blockt email-validator). Block 7 bleibt 📋 Scoping — 7.1a deckt ca. 25 % des Gesamtblocks ab; 7.1b (Frontend) folgt als separater Sub-Commit. Fortschritts-Box: ~125h → ~131h (+6h Block 7.1a), Phase-A-Restaufwand unverändert 0h.
2026-04-25 911930c Block 7.1b abgeschlossen (Branch platform/block-7-1b-operator-ui-frontend): Neues Vue-3-SPA frontend/operator-ui/ mit Tenants-CRUD-UI gegen das in 7.1a gebaute Backend. Bundle 130 KB raw / 55 KB gzipped (Ziel < 500 KB). Branding --kora-primary: #3730a3 (Indigo-800, WCAG AAA 10.79:1) zur Operator-Surface-Distinction; alle anderen Tokens identisch zu tenant-ui. useAuth.ts aus tenant-ui portiert, env-parametrisiert auf kora-platform-Realm + operator-ui-Public-Client + /admin/operator/auth/callback-Redirect, neu mit hasOperatorRole-Computed + /403-Guard. Reusable-Components (DataTable, FormInput/Textarea/Button, Toast+useToast, ConfirmDialog+useConfirm, Breadcrumbs, PageHeader). Build-Integration: neuer operator-ui-builder-Stage in Dockerfile.platform, FastAPI-SPA-Mount in main.py, sechs Makefile-Targets analog tenant-ui-*. Tests: 41/41 Vitest + 2/2 Playwright (Happy-Path + 409-Error-Path) + Backend-Regression 55/55 + Smoke-Block7-1a 12/12. Code-Review: 0 Findings ≥ 80, 8 Deferred <80 als TODO-Block-7-1b-01 .. -08 (E2E-Seed-Build-Flag, Slug-Availability-ILIKE, Tab-A11y, Form-Overlap, kein-SWR, useConfirm-Singleton, PATCH-Diff-ohne-Trim, PORTING.md-Verschiebung). Block 7 bleibt 📋 Scoping — 7.1a + 7.1b decken ca. 40 % des Gesamtblocks ab; 7.2/7.3/7.4 folgen. Fortschritts-Box: ~131h → ~140h (+9h 7.1b), Anteil ~31 % → ~33 %. NPMplus-Routing als Runbook (deployment/operator-ui-client.md Abschnitt "Prod-Deployment") skizziert; produktiver Rollout bleibt Block-14-Scope.
2026-04-25 e46b61e Block 7.2 abgeschlossen (Branch platform/block-7-2-templates-crud): Templates-CRUD-UI im Operator-UI gegen Block-5-Backend (/api/v1/operator/templates*). Pfad A bestätigt — Backend war bereits vollständig, 7.2 ist reines Frontend (~4h). Vier neue Pages (List, Create, Detail, Edit), neuer <ListInput>-Component für JSONB-list[str]-Felder (Suggestions, Connectors), Sidebar-Eintrag „Templates" aktiviert. Wichtige Pre-Flight-Findings (in PORTING-7.2.md): Templates sind global (nicht tenant-skopiert), Soft-Delete via is_active=false (reversibel), Pfad-Präfix /api/v1/operator/ (TODO-Block-7-01 unangetastet). Bundle 130 KB raw / 56 KB gzipped (+1 KB vs. 7.1b). Tests: 33 neue Vitest (total 74/74) + 2 neue Playwright (total 4/4) inkl. Deactivate→Reactivate-Workflow + 409-Error-Path. mintTokens mit 60s-Cache + 3× Retry gegen flaky Keycloak-master-Realm. Backend-Regression unverändert 55/55, Smoke-Block7-1a 12/12. Code-Review: 0 Findings ≥ 80, 7 Deferred <80 als TODO-Block-7-2-01..-07 (ListInput A11y, Backend-Search, listsEqual Reorder, Empty-Lists in POST, EntityForm-Decision deferred bis nach 7.3, Busy-Wait-Sleep, Trim-Diff inkonsistent). EntityForm-Refactor-Decision: laut Review wahrscheinlich nicht durchführen — Tenants-Form (4 Felder/Slug-Validator) und Templates-Form (8 Felder/ListInputs) zu unterschiedlich. TODO-Block-7-1b-04 bleibt offen, Re-Evaluation nach 7.3. Block 7 bleibt 📋 Scoping — 7.1a + 7.1b + 7.2 decken ca. 60 % des Gesamtblocks ab. Fortschritts-Box: ~140h → ~144h, Anteil ~33 % → ~34 %.
2026-04-25 529dc66 Block 7.3 abgeschlossen (Branch platform/block-7-3-modules-and-packages): Modules-Registry + Per-Tenant-Toggle im Operator-UI gegen Block-5/6-Backend (/api/v1/platform/modules* + /api/v1/tenants/{id}/modules*). Path A bestätigt — Backend war bereits vollständig, ~4h Frontend. Zwei neue Pages (ModulesListPage Read-Only-Registry mit Scope-Filter, ModulesDetailPage), neue <TenantModulesSection>-Component mit clientseitigem Set-Diff, Tab "Pakete & Module" in TenantsDetailPage aktiviert (war disabled mit "Kommt in Block 7.3"). Sidebar-Eintrag "Module" aktiviert. Wichtigste Pre-Flight-Erkenntnis (in PORTING-7.3.md): Pakete-Modell-Diskrepanz zwischen Code (Variante C — tenant_modules relational) und Konzept §8 (Variante A — Pro-Tenant-Pakete mit Tier/Limits). tenant_packages-Tabelle existiert seit Block 1 ohne API/Service/Schemas, 0 Rows live, kein Limits-Enforcement. 7.3 baut deshalb nur Modul-Toggle; Tier/Limits → TODO-Block-7-3-01 für Block 12. EntityForm-Refactor final verworfen (TODO-Block-7-1b-04 + TODO-Block-7-2-05): 7.3 baute keinen neuen Form-Datenpunkt, Block 12+13 bringen unterschiedliche Form-Shapes. A11y-Mit-Fix TODO-Block-7-1b-03: Tab-Row auf <button>-Elemente umgestellt. Bundle 130 KB raw / 64 KB gzipped (+8 KB vs. 7.2). Tests: 15 neue Vitest (total 89/89) + 2 neue Playwright (total 6/6) inkl. Toggle-Workflow + Registry-Navigation. Backend-Regression unverändert 55/55, Smoke-Block7-1a 12/12. Code-Review: 0 Findings ≥ 80, 7 Deferred <80 als TODO-Block-7-3-01..-07 (Tier/Limits-Block-12-Trigger, useModule-Detail-Endpoint, clientseitiger Set-Diff, Optimistic-Update, Mutation-Error-Detail, UUID-Truncation-Tooltip, BaseLayout-Footer-veraltet). Block 7 bleibt 📋 Scoping — 7.1a + 7.1b + 7.2 + 7.3 decken zusammen ~80 % des Gesamtblocks ab; nur noch 7.4 (Audit-Log + Bulk-Ops + Connectors) offen. Fortschrittsbox ~144h → ~148h, Anteil ~34 % → ~35 %.
2026-04-25 0b93d60 Block 7.4 abgeschlossen (Pfad-Split: 7.4a Backend-Merge 61689c2, 7.4b Frontend dieser Merge): Audit-Log-Viewer + Bulk-Ops + Connectors-Stub im Operator-UI. Backend (7.4a, ~3h): Audit-Reader-API /api/v1/platform/audit* mit List/Detail/CSV-Export (UTF-8-BOM, Hard-Limit, sichtbarer Truncated-Footer, optional include_details=true); JSONB-Search via cast(details, String).ilike(...) ohne GIN (TODO-Trigger > 10k Rows). Bulk-Soft-Delete für Tenants (POST /tenants/bulk-soft-delete) und Bulk-Module-Toggle für Tenant (POST /tenants/{id}/modules/bulk), atomar via request_scoped_session + Block-5-Cleanup-ON CONFLICT DO UPDATE-Pattern. Audit-Strategy: eine Audit-Zeile pro Bulk-Aktion mit IDs in details.after (Lutz-Entscheidung „Atomarität sichtbar machen"). 26 neue Tests (12 Unit + 14 Integration), Backend 79/79 + 26 = 105 grün. Frontend (7.4b, ~3h): AuditLogPage unter /admin/operator/audit mit Filter-Toolbar (Action-Dropdown via KNOWN_ACTIONS, Actor/Entity-ID/JSON-Search, Date-Range, 300 ms Debounce), Pagination, CSV-Export-Button (mit/ohne Details), Default-7-Tage-Range wenn keine URL-Filter. ConnectorsPage als reine UI-Stub mit Block-13-Hinweis-Card (kein Backend-Read — Block 13 designt API von Grund auf). Bulk-Soft-Delete in TenantsListPage (Checkbox-Spalte, Confirm-Dialog mit Slug-Vorschau), Bulk-Modul-Aktivieren in TenantModulesSection (Multi-Select über nicht-aktive non-core-Module). TenantsDetailPage-Tabs „Audit-Log" (Filter-Shortcut → /audit?entity_id=<tenant.id>) und „Connectors" aktiviert. Sidebar „Audit-Log" + „Connectors" aktiviert. Tests: 12 neue Vitest (total 100/100), 2 neue Playwright (total 8/8 sequential — workers: 1 als Pragma gegen Cross-Test-Isolation-Smell). Pre-Flight-Erkenntnisse (PORTING-7.4.md): Pfad-Split-Bestätigung durch 4-Layer-Discovery (table/service/route/live-data); GIN-Index deferred; Single-Audit-Entry-Pattern mit dokumentiertem Tradeoff (entity_id="bulk:N"-Filter findet Bulk-Events nicht). M1-Pre-Merge-Fix (a0ab7c9): TenantsDetailPage Audit-Tab-Shortcut las Query-Params nicht — useAuditEntries.ts:readUrlFilters() + Default-Date-Range nur bei fehlenden URL-Filtern. Code-Review: 0 Findings ≥ 80, 1 Pre-Merge-Fix (M1, war Score 75), 8 Deferred <80 als TODO-Block-7-4-01..-08 (Bulk-N+1-und-Cap, CSV-forensische-Felder, Bulk-Audit-entity_id-Konvention, KNOWN_ACTIONS-Drift Block 13/14, Playwright-workers:1-Pragma, datetime.utcnow()-Deprecation, Date-Range-Validation, Bulk-UI-Progress). Block 7 erreicht 100 %: 7.1a + 7.1b + 7.2 + 7.3 + 7.4 alle abgeschlossen — Operator-UI liefert die volle Phase-B-Read-Modify-Operate-Oberfläche. Phase D folgt mit Tier/Limits (TODO-Block-7-3-01) und Bulk-Cap-Hardening (TODO-Block-7-4-01). Fortschrittsbox ~148h → ~154h, Anteil ~35 % → ~36 %. Status-Box: „Aktuelle Phase" auf „B — Operator-UI komplett; Tenant-UI als nächstes", Block 7 in „Abgeschlossen" verschoben, „Nächste geplante Blöcke" auf Block 8 + Block P1 reduziert.