## Ergebnis Read-only-Audit für Sprint 6C abgeschlossen. **Keine Dateien erstellt oder geändert, keine DB/Env/Reports/Assets/Deployments geöffnet oder ausgeführt.** Arbeitsbaum war bereits nicht sauber: `tests/test_dashboard_v5_sprint6b1_integration.py` ist lokal geändert (27 hinzugefügte / 14 entfernte Zeilen); diese Änderung stammt nicht aus diesem Audit und sollte vor einem Sprint-6C-Gate geklärt werden. ## Minimaler synthetischer 6C-Testplan **Gemeinsames Setup (einmal):** - Ausschließlich `tests/fixtures/dashboard_v5_fixture.py`, feste Anchor-Date `2026-06-15`, neue private `/tmp/.../health.db` (`0600`), generiertes V5-HTML und lokaler Server auf Zufallsport. - Zusätzlich ein **wiederverwendbarer API-fixture-Overlay** statt der aktuell lokalen `api_database()`-Mutationen aus `test_dashboard_v5_sprint6b_api.py`: Such-/Dokument-/Event-Datensätze, echter numerischer Nullpunkt, Messlücke, beobachtungsspezifisches CRP-Referenzintervall und Redaction-Sentinels. - Browser erhält nur eine synthetische HttpOnly-Session via Test-Bootstrap. Die Explorer-Seite selbst erhält weder Basic-Secret noch Bearer. - Jeder Browserlauf prüft `X-Health-Synthetic-Instance`; keine Response-Interception zur Veränderung der Daten. | ID | Ebene | Minimaler Ablauf | Verbindliche Assertions | |---|---|---|---| | C6C-01 | Browser + API | Suche nach `HRV`, `CRP`, ISO-Tag und Medikamenten; Treffer auswählen. | `/search?q=` liefert die fünf festen Gruppen; Metrik-Hit übernimmt ausschließlich allowlistete ID; Tag-Hit ruft `/day/YYYY-MM-DD`; keine Dokumentpfade, Drive-IDs oder Volltexte im DOM/Netzwerk. | | C6C-02 | Browser + Contract | 7/30/90/180/Alle und freien gültigen Zeitraum wählen; täglichen und wöchentlichen Modus wechseln. | Serienrequests enthalten nur `metric`, `from`, `to`, `resolution`; Presets senden explizite Grenzen; freier Bereich ist inklusiv, nicht zukünftig, nicht >3660 Tage; Lücken bleiben Lücken, `0` bleibt `0`; Wochenpunkte nur gemäß `aggregation_rule`. Für **Alle** wird der tatsächlich von `/series` zurückgelieferte Bereich für `/events` verwendet. | | C6C-03 | Browser | Zwei kompatible Overlays aktivieren, eines deaktivieren, dann `Solo`; danach Reset. | Tatsächlich gerenderte ECharts-Legendenselektion und sichtbare Serienzahl ändern sich; Solo lässt exakt eine Serie; keine neue Statistik, keine Einheitenvermischung; Chartinstanz wird aktualisiert statt gestapelt. | | C6C-04 | Browser + Contract | CRP-/Laborserie und normale Apple-Serie öffnen; Ereignisse für denselben Zeitraum laden. | Referenzband nur bei tatsächlich vorhandener beobachtungsspezifischer Laborreferenz (`/labs`, min/max/source) sichtbar und textlich erklärt; normale Serie erhält **kein erfundenes** Normal-/Referenzband. Ereignisse liegen getrennt von `series` und behalten bei Perioden Start/Ende sowie Medikationstypen. | | C6C-05 | Browser | Realen sichtbaren Punkt per `convertToPixel` hovern und klicken; denselben Tag in zugänglicher Tabelle per Tastatur aktivieren. | Sichtbarer Tooltip enthält Datum, Serienlabel, Einheit und dokumentierten Wert; Chartklick und Tabellenaktivierung dispatchen beide exakt `health:day-select` mit identischem `YYYY-MM-DD`; genau ein `/day/` folgt. | | C6C-06 | Browser/A11y | Tabelle öffnen, mit Tab/Enter bedienen; Explorer mit Auswahl und ohne Auswahl prüfen. | Tabelle enthält exakt dieselben aktuell sichtbaren Punkte/Serien wie Chart, sinnvolle Caption/Headers, keine Canvas-only-Information; leere Auswahl zerstört/versteckt alten Chart und zeigt expliziten Empty-State. | | C6C-07 | Browser | 390×844 sowie Desktop; realer Chromium-Textscale 200% (`--force-text-scale-factor=2`, nicht nur Root-Font-Override). | Kein horizontaler Dokument-Overflow; alle sichtbaren Explorer-Targets ≥44×44 CSS-Pixel; Bottom-Nav verdeckt keine Controls; ECharts interne Breite/Höhe entspricht CSS-Box (Rundungstoleranz 2px), nutzbare Plot-Höhe und lesbare Labels bleiben erhalten. | | C6C-08 | Browser/Privacy | Explorer laden, Session einsetzen, Suche/Range/Tooltip/Tagaktion ausführen; Request-, Console- und Pageerror-Listener aktiv. | Keine externen Requests oder Requestfailures; CSP auf V5 `connect-src 'self'`; alle UI-API-Requests same-origin; **kein Bearer** in URL, HTML, DOM, local/sessionStorage, Cookie, Request-Headers oder Response; Session-Cookie bleibt HttpOnly/SameSite=Strict. Privacy-Modus maskiert Explorer-Text **und Canvas** transient. | | C6C-09 | Browser/Performance | Je fünf frische Browser-Kontexte für 1440×900 und 390×844: Navigation → API-Daten → ECharts-ready; danach Range-/Solo-Interaktion. | Rohwerte pro Lauf speichern: Navigation-to-ready, API-Dauer, Chart-Init, Interaktionslatenz; keine Fehler/externen Requests, keine wachsende Zahl ECharts-Instanzen. **Kein neues festes Produktionsbudget behaupten:** das dokumentierte `<2s/<500ms` gilt ausdrücklich nur für den 6A-Prototyp; Sprint 6C muss Messwerte liefern oder ein eigenes Budget freigeben. | | C6C-10 | Python-Contract | Direkte `dispatch_api()`-Tests mit derselben Fixture. | Suchgruppen/Redaction, freie Range-Grenzen, Null-vs-Lücke, Wochenregel, Eventtypen/Perioden, Day-Response, `no-store`/401/403/405 über Server-HTTP sowie `Cache-Control` auf Fehlerpfaden. | ## Vorhandene Seams - **Deterministische Basisfixture:** `tests/fixtures/dashboard_v5_fixture.py` - neuer Zielpfad muss nicht existieren; setzt Marker `dashboard-v5-synthetic-fixture-v1`; - feste Anchor-Date, Null-/Missingness-/Future-/lange-Label-Fälle, Medikamente und Explorer-Reihen vorhanden; - erzeugt byte-deterministische Fixture/HTML (`tests/test_dashboard_v5_explorer_sprint5b.py`). - **API-fixture-Erweiterung:** `api_database()` in `tests/test_dashboard_v5_sprint6b_api.py` ergänzt gezielt Apple-Metriken, Blutdruck, CRP-Dokumentmetadaten, Events und Redaction-Sentinels. Derzeit ist sie testlokal; für Browser-E2E müsste diese Semantik in einen gemeinsamen, synthetischen Builder überführt werden. - **Server-Seam:** `load_server()` sowie `_start_server()` in den Sprint-6B/6B.1-Tests erzeugen einen lokalen `ThreadingHTTPServer` auf Port `0`. Der Server unterstützt die Browser-Session, strenge Host/Origin-Prüfung, `no-store` und `X-Health-Synthetic-Instance`. - **Browser-Seam:** `tests/browser/dashboard_v5*.spec.js`; `playwright.config.js` hat keinen `webServer`. Der Server muss daher vor Playwright gezielt aus der synthetischen Fixture gestartet werden. Das vorhandene dokumentierte Setup steht in `docs/sprint5-dashboard-v5-desktop-first.md`, ist aber noch auf den älteren statischen Bundle-Pfad ausgerichtet. - **Bestehende ECharts-Referenz:** `dashboard_v5_echarts_prototype.spec.js` deckt bereits reale Tooltip-/Pixel-Interaktion, Toggle/Solo, Pan/Brush, Tabelle/Callback, 390px, einfache 200%-Prüfung, CSP/externe Requests und fünf Performance-Läufe ab. Für 6C muss dies auf reale API-Verträge und den neuen `chart-controller` übertragen werden. ## Wesentliche Fallstricke / Gaps 1. **Referenzband-Vertrag ist unvollständig für allgemeine Metriken.** `/api/v1/series` liefert kein Baseline- oder Bandfeld; der Browser darf laut Architektur keine neue medizinische Statistik berechnen. In 6C sind daher nur durch `/labs` belegte, beobachtungsspezifische Laborbänder zulässig; für andere Reihen explizit „kein Referenzband verfügbar“ statt Berechnung/Erfindung. 2. **`Alle` versus Events:** `/series` erlaubt ausgelassene Grenzen, `/events` verlangt `from/to`. Der Controller muss den effektiven Antwortbereich der Serie übernehmen; keinesfalls freie/unbegrenzte Eventabfrage erzeugen. 3. **Bestehende Explorer-Tests verwenden Chart.js und eingebettetes Bundle.** Sie beweisen weder API-getriebene ECharts-Darstellung noch Search-/Range-Requestbildung. 4. **200%-Test ist derzeit nur `documentElement.style.fontSize = '200%'`.** Für 6C zusätzlich echter Browser-Textscale erforderlich, sonst bleibt Canvas-/Resize-Reflow unbewiesen. 5. **`dashboard_v5_api_session.spec.js` ist im aktuellen Tree nicht verlässlich ausführbar:** `basic(...et)` referenziert ein nicht definiertes `et`; die parallele Änderung in `test_dashboard_v5_sprint6b1_integration.py` entfernt zudem `base64`, obwohl `_basic()` es noch nutzt. Wegen des laufenden lokalen Diffs als Konflikt-/Stabilisierungsrisiko melden, nicht dem Sprint-6C zuschreiben. 6. **Performance-Grenzen:** Die dokumentierten 6A-Grenzen gelten ausdrücklich nur für den isolierten Prototyp; 6C sollte Messung und Leck-/Instanzregression als Gate nehmen, aber keine 6J-Produktionsbudgets vorwegnehmen. 7. **Keine HTML-Interception für API-Verhalten.** Bestehende Browser-Tests manipulieren teils eingebettetes HTML; das ist für alte Bundle-Regressionen sinnvoll, würde aber den 6C-API-, Session-, Redaction- und Range-Vertrag umgehen. ## Geprüfte Unterlagen - Sprint-/Architektur-/ADR-Dokumentation: `docs/sprint6a-dashboard-v5-foundation-echarts.md`, `docs/sprint6b-metric-catalog-read-api.md`, `docs/dashboard_v5_architecture_target.md`, `docs/adr/0001-dashboard-v5-chart-engine.md`. - Relevante Source-/Server-/API-/Render-Seams sowie Fixture, Python-Contracts und alle drei Browser-Specs. - Keine Tests gestartet; der Auftrag war ein read-only Plan-Audit und verbot Datenbank-/Env-/generierte-Report-Nutzung.