## Ergebnis ### Findings - **HOCH – API-DB ist nicht vom Legacy-/V4-Pfad getrennt.** `scripts/health/health_dashboard_server.py:29-34` setzt `DB = API_DB or ...`. Dadurch verändert `HEALTH_DASHBOARD_DB` zugleich die bestehende V4-/Dokument-Datenbank. `document_path()` öffnet diese DB zudem normal statt read-only (`:157-172`), und `/health-doc/{id}` greift ohne Bearer-Authentisierung darauf zu (`:537-547`). Eine explizite API-DB mit Dokumentreferenzen kann somit über den Legacy-Dateipfad erreichbar werden. Das verletzt sowohl die explizite API-DB-Isolation als auch „V4 unverändert“. - **HOCH – Pfad-/URL-Redaktion ist umgehbar.** `FORBIDDEN_METADATA_TEXT` in `dashboard_v5/read_api.py:49-52` erkennt Unix-Pfade und URLs nur am Stringanfang oder nach Whitespace. Werte wie `prefix:/home/agent/private.db`, `see:https://drive.invalid/private` und `x|/tmp/private/report.pdf` wurden synthetisch unverändert akzeptiert. Diese Funktion schützt öffentlich ausgegebene Dokument-, Medikamenten- und Ereignisfelder (`:408-417`, `:554-583`, `:601-614`). Damit können lokale Pfade/URLs aus verschmutzten Metadaten austreten. - **MITTEL – Keine Laufzeitbegrenzung und teilweise keine SQL-seitigen Zeilenlimits.** `connect_read_only()` setzt keinen SQLite-Progress-Handler/Query-Deadline (`read_api.py:93-98`). Symptom- und Ernährungsabfragen laufen ohne `LIMIT` (`:268-302`, `:330-345`); das Serienlimit wird erst nach vollständigem Lesen und Aggregieren geprüft (`:510-517`). Ein authentisierter Client kann damit Threads durch große Tabellen langfristig belegen. - **MITTEL – Unerwartete API-Ausnahmen erzeugen keine kontrollierte `no-store`-Fehlerantwort.** Der Handler fängt nur `APIError`, `OSError` und `UnicodeError` (`health_dashboard_server.py:578-586`). Ein synthetisch injizierter `RuntimeError` führte zu `RemoteDisconnected`, Server-Traceback und keiner HTTP-Antwort bzw. keinem `Cache-Control: no-store`. - **MITTEL – Methoden-Allowlist ist nicht vollständig fail-closed.** Einige Methoden werden explizit als JSON-`405` behandelt, unbekannte Methoden jedoch nicht. Ein synthetisches `PROPFIND /api/v1/labs` ergab den Standard-`501`-HTML-Fehler ohne `no-store`. Host-Fehler wurden im aktuellen Tree dagegen korrekt als JSON-`421` mit `no-store` behandelt. ### Positiv verifiziert - Bearer-Token aus expliziter Datei, `O_NOFOLLOW`, reguläre Datei, Eigentümerprüfung, exakt `0600`, Größen-/Formatgrenze und `compare_digest`. - API ohne explizite DB und Token-Datei fail-closed. - API-SQLite verwendet URI `mode=ro`, `query_only=ON` und `trusted_schema=OFF`. - Exakte Route-/Query-/Metrik-Allowlisting und parametrisierte SQL-Parameter; keine browsergesteuerte Tabellen- oder Spaltenwahl gefunden. - Origin-/Fetch-Metadata-Prüfung, keine CORS-Freigabe, restriktive API-CSP. - 512.000-Byte-Response-Limit sowie mehrere Source-/Ergebnislimits vorhanden. - Symlink auf die Token-Datei wird abgelehnt. ### Ausführung - Aktueller Sprint-6B-Slice: **15 passed**. - Gesamtsuite: **176 passed**; anschließend wurde der aktuelle Serverstand nochmals mit dem Sprint-6B-Slice geprüft. - `git diff --check`: bestanden. - AST-Prüfung der sechs Python-Dateien: bestanden. - Keine Produktionsdaten, DBs, Reports oder Secrets geöffnet. - Keine Dateien erstellt oder verändert. Der erste Testlauf scheiterte nur an fehlendem `PYTHONPATH=.`; der korrigierte Lauf war grün. BLOCK