## Ergebnis - Sprint-6B-Plan, kanonisches DDL, V5-Provider/Contracts, Serverrouten, Registries, synthetische Fixture und vorhandene Tests mechanisch geprüft. - Keine produktive DB, Reports, Dokumentinhalte, Secrets oder private Laufzeitdaten geöffnet. - Keine Dateien erstellt oder geändert; Git-Status blieb `main...origin/main [voraus 1]` ohne Working-Tree-Änderungen. - Keine medizinische Interpretation vorgenommen. ## Sprint-6B-Stand Sprint 6B verlangt laut `docs/source/healthmanager-v5-repo-audit-zielbild-sprint6.md:749-803`: - Metrikkatalog V2 mit Alias-/Quell-/Aggregations-/Datenschutzmetadaten - gruppierte Suche - begrenzte read-only APIs für Katalog, Serien, Tage, Events, Labore und Suche - sichere Dokumentmetadaten, aber noch keinen Dokumentvolltext - harte Allowlists, Limits, Redaction, `Europe/Zurich`, Missing-vs.-Null/0-Tests **Aktueller Stand:** Sprint 6B ist noch nicht implementiert. - Keine `test_*6b*.py`-Datei gefunden. - Keine Search-Implementierung gefunden. - `health_dashboard_server.py` bedient nur Dashboard, Assets, Dokumentdateien, Reports und Symptom-POST; keine `/api/v1/*`-Routen. - `metric_registry.py` ist noch V1-artig: 6 Metriken und keine Felder für Aliasse, Suchbegriffe, Quelle, erwartete Frequenz, Reference-Policy, Drill-down, Lags oder Datenschutzklasse. - Aktuelle Events im V5-Bundle sind ausschließlich `medication_administered`. - Dokumente und Tagesdetails fehlen vollständig im Bundlevertrag. ## Inventar sicher nutzbarer Metadaten ### Dokumente Vorhandene Schemafelder in `database/schema.sql:68-79`: - potentiell freigabefähig: `id`, `daten_typ`, `upload_datum`, `groessekbytes`, `status`, `verarbeite_datum`, `kategorie`, `datei_hash`, `quelle`, `review_status`, `processing_quality`, `document_date`, `institution` - **nicht an API/Search ausgeben:** `dateipfad`, `local_original_path`, `drive_file_id`, `drive_web_url`, `extrahierte_inhalte` - `datei_name` ist ein Dateiname und damit nicht automatisch ein sicherer Titel. - Ein explizites Dokument-`title`-Feld existiert nicht; `document_insights.titel` gehört zu einer anderen Tabelle. Empfohlener 6B-Metadatenvertrag: ```json { "document_id": "doc.synthetic.001", "title": "Synthetischer Befund", "document_date": "2026-06-10", "category": "synthetic_category", "institution": "Synthetische Institution", "document_type": "pdf", "status": "eingearbeitet", "review_status": "geprueft", "processing_quality": "complete", "has_original": true, "day_route": "/day/2026-06-10" } ``` Kein Pfad, Dateiname, Volltext, Drive-Identifier, URL oder ungefiltertes `quelle`. ### Tage Sichere gemeinsame Schlüssel: - kanonisches `date`/`datum` als `YYYY-MM-DD` - `timezone = Europe/Zurich` - Domänen-Präsenz und begrenzte Counts - technische Qualität/Coverage - stabile Drill-down-Route Nicht direkt ausgeben: `health_daily_summary.*_json`, `notes` oder sonstige Freitexte. Vorgeschlagene Day-Summary-Felder: ```text date, timezone, domains_present[], counts{symptoms, medications, events, documents, labs}, coverage_status, quality_flags[], drilldown_target ``` ### Symptome Vorhanden: - `symptom_log`: `datum`, `symptom`, `schwergrad`, `kontext`, `notizen`, `created_at` - sieben kanonisch verwendete Dimensionen: - `Aphthen/Mundulzera` - `GI/Darm` - `Müdigkeit/Fatigue` - `Haut` - `Augen` - `Gelenke` - `Vaskulär/Thrombose-Warnzeichen` Sicher projizierbar: ```text date, canonical_symptom_id, label, score(0..3|null), context_allowlisted, quality(complete|incomplete), observed ``` `notizen` und beliebiger `kontext` sollten in 6B nicht Bestandteil globaler Suchergebnisse sein. ### Medikamente Schemafelder: ```text datum, medication_name, dose, route, event_type, scheduled_next_date, notes, source, created_at ``` Der bestehende V5-Vertrag erlaubt bereits: - `last_administered`: `date`, `name`, `dose` - `next_planned`: `date`, `name`, `dose`, `status=planned` - Event: `date`, `type=medication_administered`, `label` Für 6B sicher erweiterbar: ```text date, medication_id/name, event_type, status, dose, route, scheduled_next_date, source_category, drilldown_target ``` `notes` und ungefiltertes `source` nicht global durchsuchen oder ausgeben. ### Events und Phasen `health_events` besitzt: ```text date, category, parameter, value, unit, source, notes ``` `health_event_periods` besitzt: ```text start_date, end_date, event_type, label, severity, location, source, notes, confidence ``` Sicherer 6B-Eventvertrag: ```text event_id, start_date, end_date, type, label_sanitized, status, confidence/quality, source_category, day_route ``` Nicht standardmäßig ausgeben: `location`, `notes`, freies `value`, ungefiltertes `source`. Vorhandene Phasenbegriffe: - `baseline_pre_treatment` - `early_treatment` - `stable_treatment` - `unknown` Wichtige bestehende Invariante: Intervalle dürfen nicht zu einem Einzelmarker reduziert werden. ## Vorhandene Aliasbegriffe Bereits im Code vorhanden: - Medikamentengabe: - `administered`, `verabreicht` - `erste injektion / therapiebeginn` - `planmäßige injektion` - `planmässige injektion` - `planmaessige injektion` - Planung: `planned`, `scheduled`, `geplant` - Ausschluss: `cancelled`, `canceled`, `abgesagt`, `missed`, `verpasst` - Labor-Rohaliase: - `CRP`, `C-Reaktives Protein (CRP)` - `D-Dimer`, `Fibrinogen`, `Faktor VIII`, `Thrombozyten`, `Leukozyten`, `Ferritin` - Symptom-Key-Alias: `aphthen` → `Aphthen/Mundulzera` - Schema für Lebensmittelaliase vorhanden: `histamine_food_aliases(alias, canonical_food)`; Inhalte wurden nicht gelesen. Die in Sprint 6B geforderten globalen Suchaliasse sind noch nicht als Suchregistry implementiert. ## Vorgeschlagene synthetische Aliasfixture ```python SYNTHETIC_SEARCH_ALIASES = [ { "canonical_id": "panel.blood_pressure", "group": "metrics", "label": "Blutdruck", "aliases": ["blutdruck", "bd", "rr", "systolisch", "diastolisch"], "children": ["vital.blood_pressure.systolic", "vital.blood_pressure.diastolic"], "data_status": "supported_no_data", }, { "canonical_id": "apple.resting_heart_rate", "group": "metrics", "label": "Ruhepuls", "aliases": ["ruhepuls", "herzfrequenz", "puls"], "data_status": "available", }, { "canonical_id": "apple.hrv", "group": "metrics", "label": "HRV", "aliases": ["hrv", "herzfrequenzvariabilitaet", "herzfrequenzvariabilität"], "data_status": "available", }, { "canonical_id": "apple.sleep", "group": "metrics", "label": "Schlaf", "aliases": ["schlaf", "schlafdauer"], "data_status": "available", }, { "canonical_id": "lab.crp", "group": "labs", "label": "CRP", "aliases": ["crp", "c-reaktives protein", "c reaktives protein"], "data_status": "available", }, { "canonical_id": "lab.d_dimer", "group": "labs", "label": "D-Dimer", "aliases": ["d-dimer", "d dimer", "ddimer"], "data_status": "supported_no_data", }, { "canonical_id": "lab.factor_viii", "group": "labs", "label": "Faktor VIII", "aliases": ["faktor viii", "faktor 8", "fviii"], "data_status": "supported_no_data", }, { "canonical_id": "symptom.aphthae", "group": "symptoms_events", "label": "Aphthen/Mundulzera", "aliases": ["aphten", "aphthen", "mundulzera"], "data_status": "available", }, { "canonical_id": "medication.synthetic_alpha", "group": "medications", "label": "SYNTHETIC_MEDICATION_ALPHA", "aliases": ["synthetic medication alpha", "synthetic alpha"], "data_status": "available", }, { "canonical_id": "document.synthetic_001", "group": "documents", "label": "Synthetischer Befund", "aliases": ["synthetischer befund"], "safe_metadata_only": True, "data_status": "available", }, ] ``` Fixture sollte zusätzlich Aliasnormalisierung für Groß-/Kleinschreibung, Umlaute, Bindestriche und Mehrfachleerzeichen abdecken, aber keine medizinischen Synonyme eigenmächtig ergänzen. ## Vorgeschlagene Contract-Testmatrix | Bereich | Testfall | Erwartung | |---|---|---| | Katalog | exakte V2-Feldmenge | unbekannte/fehlende Felder abweisen | | Katalog | doppelte ID oder Alias-Kollision | fail closed | | Suche | `Blutdruck`, `BD`, `RR` | dasselbe Panel plus beide Komponenten | | Suche | `Aphten` und `Aphthen` | derselbe Symptomtreffer | | Suche | Großschreibung/Umlaut/Whitespace | deterministisch normalisiert | | Suche | leere, zu lange oder Control-Char-Abfrage | `400`, keine DB-Abfrage | | Suche | Gruppierung | nur `metrics`, `labs`, `symptoms_events`, `medications`, `documents`, `days` | | Suche | Dokumenttreffer | nur sichere Metadaten, kein Volltext | | Redaction | Pfad/URL/Drive-ID/Filename in Quelldaten | nie in Antwort oder Fehlertext | | Serie | unbekannte Metrik/Spalte/SQL-artiger Parameter | `400/404`, keine freie Auswahl | | Serie | `0`, `null`, fehlender Tag | drei unterschiedliche Zustände | | Serie | Antwortmetadaten | Einheit, Aggregation, Quelle, Coverage, `Europe/Zurich` vorhanden | | Serie | 7/30/90/180/freier Bereich | deterministische Grenzen und Reihenfolge | | Serie | `Alle` | serverseitig begrenzt, kein unbeschränktes Payload | | Tag | ungültiges/future ISO-Datum | fail closed | | Tag | identisches Datum über Suche/Event/Dokument | identischer Day-Contract | | Tag | leere Domäne | kompakt abwesend, nicht als Null-Beobachtung | | Event | offenes und mehrtägiges Intervall | Start/Ende erhalten | | Event | Typenfilter | nur allowlistete Typen | | Medikation | geplant/verabreicht/verpasst/abgesagt | getrennte Statussemantik | | Labor | verifizierter Treffer | observationsbezogener Referenzkontext und sichere Dokument-ID | | Labor | Duplikat, unbekannte Einheit, unverified | nicht freigeben | | Limits | Rows, Zeitraum, Trefferzahl, Payloadgröße | harte Obergrenzen | | HTTP | GET/HEAD, Auth, Host, Cache | Auth erforderlich, `no-store`, Host-Allowlist | | Datenschutz | Response rekursiv prüfen | keine Pfade, Drive-IDs, Rohtexte, Notizen oder freie SQL-/Spaltennamen | ## Bereits brauchbare Testgrundlagen Vorhandene Tests decken bereits wichtige Basissicherheiten ab: - Missing vs. `null` vs. echte `0` - strikte Bundle-Feldmengen und Registry-Drift - Pfadtext-Redaction - Allowlist/Provenienz für Laborwerte - geplante vs. tatsächliche Medikation und deutsche Event-Aliasse - zukünftige/unordentliche Serien, Baseline und Größenlimits - `Europe/Zurich` bei Symptomaufnahme - synthetische Fixture-Markierung, read-only DB und private Ausgabe - deterministische Fixture-/HTML-Erzeugung - Host-, Methode-, CSP- und Pfadgrenzen des Servers **Noch fehlend:** sämtliche Sprint-6B-Endpunkt-, Such-, Alias-, Day-, Dokumentmetadaten- und allgemeinen Eventintervall-Contracttests.