## Schlussverdikt: **BLOCK** ### P0 — 0 Keine P0-Funde. ### P1 — 3 1. **Model-Preview liefert nach einem blockierten Lauf mit vorhandenem Modellwert HTTP 500** - `src/jarvis_finance/api/schemas/performance_activation.py:339-343` - `src/jarvis_finance/services/truewealth_valuation.py:236-264` - `frontend/src/api/portfolio.ts:44` - Gespeichert wird `source="truewealth_modelled_valuation_v1"`, API- und Frontend-Contract erlauben dagegen nur `"truewealth_modelled_daily"`. - Reproduziert: blockierter neuer Modelllauf plus vorhandener letzter Modellwert führt zu `ResponseValidationError` und HTTP 500. - **Fix:** Producer, Pydantic-Schema und TypeScript-Typ auf einen kanonischen Source-Wert vereinheitlichen; Regressionstest für `blocked + latest_modelled_value != null`. 2. **Das vom Frontend konsumierte Setup-API ist weiterhin offen und exportiert interne Diagnostik** - `src/jarvis_finance/api/routers/overview.py:237-240` - `src/jarvis_finance/services/performance_hardening.py:859-874` - `frontend/src/components/performance/PortfolioPerformancePanel.vue:182-184` - OpenAPI für `/api/portfolio/performance/setup`: `additionalProperties: true`. Die Diagnostik kann interne Snapshot-/Batch-/Account-/Instrumentzeilen enthalten und wird unverändert kopier- bzw. downloadbar gemacht. - **Fix:** Geschlossene, verschachtelte Response-Modelle und eine explizit redigierte öffentliche Diagnostikprojektion einführen; keine rohen Service-Dictionaries an das UI geben. 3. **Nicht überlappende oder eintägige Zeiträume werden stillschweigend auf den gesamten verfügbaren Zeitraum erweitert** - `frontend/src/components/performance/PortfolioPerformancePanel.vue:193` - Sobald `actualFrom >= actualTo`, ersetzt das Frontend die Auswahl durch `valuation_from … valuation_to`. Eine zukünftige, vergangene oder eintägige Auswahl kann dadurch historische Vollperioden-KPIs anzeigen, obwohl der gewünschte Zeitraum keine auswertbare Überlappung besitzt. - **Fix:** Echte Intersektion bilden; bei weniger als zwei belastbaren Tagen „nicht verfügbar“ darstellen und keine Performance-Abfrage für einen anderen Zeitraum ausführen. ### P2 — 2 1. **Confirm-Response ist nicht gegen spätere Formzustände geschützt** - `PortfolioPerformancePanel.vue:185,191` - Preview- und CSV-Requests besitzen Generationsschutz, der Confirm-Pfad dagegen nicht. Während eines laufenden Confirms kann eine Eingabeänderung `twBusy` zurücksetzen; die alte Antwort kann anschließend einen neueren Preview-/Meldungszustand löschen. - **Fix:** Eigene Confirm-Generation bzw. unveränderlichen Confirm-Snapshot verwenden und Eingaben während des Confirms sperren. 2. **Security-Test prüft wegen falscher URL nicht die reale Aktivierungsroute** - `tests/unit/test_sprint20d_truewealth_productization.py:517-521` - Getestet wird `.../truewealth-bank-payments/recipient-rule/activate`; implementiert ist `.../truewealth-recipient-rule/activate` in `overview.py:394-405`. Das erwartete 403 entsteht bereits in der globalen Middleware und deckt den tatsächlichen Contract nicht ab. - **Fix:** Korrekte Route testen und zusätzlich Audit-/Write-Sentinels prüfen. ### Verifikation - Backend-Fokustests: **27 passed** - Frontend-Komponententests: **13 passed** - Typecheck und Produktions-Build: **grün** - `git diff --check`: **grün** - Angegebene Responsive-UAT-Matrix 1440/820/390: keine zusätzlichen Overflow-, Clipping- oder Touch-Target-Funde. - Final geprüfte Candidate-ID: `485e6e9662f71e891a44b440222be68d786b0cfa3e19b88b61c2975f8958df` - **Keine Dateien erstellt oder verändert.**