# Dashboard V5 — Release-Candidate-Abnahmematrix

**Stand:** Sprint 7A

**Kandidat:** lokaler V5-RC einschließlich Telegram-Symptom-/Kalendersichtbarkeitsfix

**Schutzgrenze:** ausschließlich synthetische dynamische Tests; private Echtdaten nur in abschließenden read-only Runtime-Smokes. V4 bleibt unverändert als Fallback.

## 1. Verbindlicher Fixture-Vertrag

- Alle dynamischen Unit-/API-/Browsertests verwenden neue temporäre SQLite-Datenbanken unter `/tmp`.
- `tests/fixtures/dashboard_v5_fixture.py` ist die allgemeine deterministische Basis mit festem Ankerdatum.
- Dokument-, Originaldatei- und lokale Medienfälle verwenden ausschließlich die spezialisierten synthetischen 6E-/6I-Fixtures.
- Browserläufe verlangen `X-Health-Synthetic-Instance`; fehlt der Sentinel, ist der Lauf ungültig.
- Produktionsdatenbanken, PDFs, Reports, Logs, Rohmedien und Credentials dürfen nicht in Tests, Screenshots oder Traces gelangen.
- Missingness bleibt `null`/unbekannt; explizite Null bleibt numerisch `0`.
- Geplant, verabreicht, ausgelassen und korrigiert bleiben getrennte Medikationszustände.
- Laborreferenzen werden nur mit kanonischer Metrik, sicherer Einheit und beobachtungsspezifischer verifizierter Provenienz dargestellt.

## 2. RC-Gates

| Gate | Abdeckung | Verbindliche Evidenz |
|---|---|---|
| G1 Git-/Kandidatenidentität | Branch, HEAD, `origin/main`, vollständige tracked/untracked Kandidatenmenge | `git status --short --branch`, `git diff --check`, staged name/status und Kandidatendigest |
| G2 Telegram-/Day-/Kalendervertrag | Zusätzliche gemeldete Symptome; lange optionale Eventnotiz darf sicheren Titel nicht ausblenden; Kalendercount und Tagesansicht konsistent | `tests/test_dashboard_v5_sprint6d_day_calendar.py` und aktuelle Browsergruppe `7a-rc` |
| G3 Read-only API/Datenschutz | Katalog, Serien, Suche, Day, Kalender, Akte, Dokumente; Allowlist, Limits, Redaction, `no-store` | V5-Python-Vertragssuite, insbesondere 6B–6E und 6G-A |
| G4 Medizinische Semantik | Missingness, Referenzen, Medikation, Zukunftsgrenzen, keine Diagnose-/Therapie-/Kausalitätsaussage | 6A/6C/6D/6E/6F/6G/6K-Vertragstests und Added-lines-Review |
| G5 Sichere Schreibgrenze | Browser schreibt nie direkt in Health-DB; Origin/Session/CSRF, Queue, Worker, Idempotenz | synthetische Capture-/Review-/Mapping-/6K-A-Tests; keine produktive Action im Smoke |
| G6 Dokumente und Medien | reviewed-first Suche, opaque IDs, sichere Originalroute, Quarantäne, lokale Decode-/Derivatverträge | 6E-/6H-/6I-Python- und Browsergruppen auf synthetischen Dateien |
| G7 Ernährung und Referenzen | kontrollierte Einheiten, Unknown statt Null, 1/7/30 Tage, BLV-Provenienz, kein Mangel-/Supplementclaim | 6G- und 6K-A-Python-/Browserverträge |
| G8 Explorer/Zusammenhänge | kanonische Metriken, Lücken, Coverage, Lags/Phasen, keine Kausalität, URL-/History-Restore | 6C-/6F-/6J-A/B-Verträge |
| G9 UX/Accessibility | Desktop und 390 px, kein Seitenoverflow, 44-px-Ziele, Keyboard/Fokus, Reduced Motion, Druckdisclaimer | isolierte Browsergruppen; Screenshots/Traces nur außerhalb des Repos |
| G10 Runtime/Legacy | Dienst-Interpreter, private Listener-Topologie, Auth 401/200, CSP/`no-store`, Runtimehashes, V4-Hash | finaler privater read-only Smoke nach exaktem Commit |

## 3. Testausführung

### Python

Der Dienst-Interpreter enthält die produktiven Laufzeitabhängigkeiten. `pytest`, `openpyxl` und `reportlab` dürfen für RC-Tests aus einer temporären `uvx`-Umgebung übergeben werden; sie werden nicht in die produktive Venv installiert.

```bash
TEST_SITE="$(uvx --from pytest==9.0.2 --with openpyxl --with reportlab \
  python -c 'import pathlib,pytest; print(pathlib.Path(pytest.__file__).parent.parent)')"
PYTHONDONTWRITEBYTECODE=1 PYTHONPATH="$TEST_SITE" \
  ~/.hermes/hermes-agent/venv/bin/python3 -m pytest -q tests/test_dashboard_v5*.py
```

Wenn die historische Gesamtauswahl fehlschlägt, muss jeder Fehler als Produktregression, veralteter Testvertrag, fehlende optionale Fixture-Abhängigkeit oder reproduzierbare Baseline-Schuld klassifiziert werden. Ein nicht grüner Gesamtlauf darf nicht als bestanden gemeldet werden.

### Browser

`tests/browser/run_v5_isolated_matrix.sh` erzeugt pro Gruppe eine neue private Fixture, einen zufälligen Loopback-Port, eigene Token-/Queue-/Medienpfade und einen synthetischen Instanz-Sentinel. Für Sprint 7A mindestens:

```bash
HEALTH_DASHBOARD_BROWSER_GROUP=7a-rc tests/browser/run_v5_isolated_matrix.sh
HEALTH_DASHBOARD_BROWSER_GROUP=6k-a tests/browser/run_v5_isolated_matrix.sh
```

Die historische Browsergruppe `calendar` bildet die frühere 6D-Navigation ab und ist nach dem 6J-C-Navigationsumbau kein RC-Gate mehr. `7a-rc` verwendet das aktuelle `record-files`-Profil und deckt Ernährung, Akte/Dokumente, Kalender, 390 px und Reduced Motion ab. Weitere spezialisierte Gruppen dürfen weiterhin nicht gegen ein unpassendes Standardprofil ausgeführt werden.

## 4. Statische und Security-Gates

```bash
# Python ohne Bytecode-Artefakte parsen
python3 - <<'PY'
import ast
from pathlib import Path
for path in Path('scripts/health').rglob('*.py'):
    ast.parse(path.read_text())
for path in Path('tests').rglob('*.py'):
    ast.parse(path.read_text())
PY

# JavaScript- und Shell-Syntax
for file in scripts/health/assets/health-assets/*.js tests/browser/*.spec.js; do node --check "$file"; done
bash -n tests/browser/run_v5_isolated_matrix.sh

git diff --check
git status --short --untracked-files=all
```

Der Abschlussreview prüft zusätzlich:

- keine neuen externen URLs/CDN-/Chartbibliotheken;
- keine DDL/DML- oder direkten Browser-DB-Schreibpfade im Sprint-7A-Diff;
- keine Secrets, Credential-Dateien, Datenbanken, PDFs, Tabellen, Medien oder Testartefakte im Kandidaten;
- keine medizinischen Ampeln, Diagnosen, Therapie-/Supplementempfehlungen oder scheinpräzisen Kausalitätsclaims;
- V4-Laufzeitartefakt weiterhin SHA-256 `798d11f191b402c556ec9233f50f5622d7f849022ff301cb4336ef2556e5f3a8`.

## 5. Private Runtime-Abnahme

Nach Commit und Push:

1. lokalen Commit, `origin/main` und Runtimequellen bytegenau abgleichen;
2. V5 mit dem bestehenden privaten Produktionsprofil regenerieren, ohne V4 zu verändern;
3. nur `health-dashboard.service` kontrolliert neu starten;
4. tatsächlichen privaten Listener prüfen — der Dienst kann absichtlich nicht an Loopback gebunden sein;
5. V4 `200`, V5 ohne Auth `401`, V5 authentifiziert `200`, `Cache-Control: no-store`, CSP und `nosniff` prüfen;
6. Kalender- und Day-API für einen bereits dokumentierten Tag ausschließlich read-only prüfen;
7. Ernährung, Dokumente, Kalender, Desktop/390 px und Capture-Dialoge öffnen, aber keine Action absenden;
8. SQLite ausschließlich per read-only URI öffnen und `integrity_check` ausführen;
9. Runtimehashes, V4-Hash, aktiven Dienst und sauberen Git-Status erneut prüfen.

## 6. Terminalkriterium Sprint 7A

Sprint 7A kann als **V5 Release Candidate konsolidiert** abgeschlossen werden, wenn alle ausgeführten Gates ehrlich dokumentiert, der Telegram-/Kalenderfix veröffentlicht, Runtime und Git synchron, V4 unverändert und keine offene P0/P1-Sicherheits- oder Medical-Safety-Abweichung vorhanden ist.

Sprint 7A ist ausdrücklich **keine Freigabe**, V4 zu entfernen oder `/health-dashboard` auf V5 umzuschalten. Die Paritätsmatrix führt verbleibende teilweise/offene Post-RC-Punkte weiter.