# Dok 05b — Software-Verifikation: Test-Nachweis (v0) **Bezug:** IEC 62304 §5.5 (Software-Integration und Integrationstests), §5.6 (Software-Systemtests), §5.7 (Software-Release) **Norm-Kontext:** ISO 14971 Risikomanagement, MDR Anh. I (GSPR §17 — Software) **Status:** Entwurf v0 — Ist-Stand-Inventar. Kein formaler Verifikations-Record. **Drafting:** Ahmed (Test-Agent), Validierung durch Regulatory-Profi ausstehend. **Einordnung:** Feeds Dok 05 (Software-Lifecycle + Architektur + SOUP). Andockpunkte: Marlenes Requirements-Liste (Dok 03, noch offen) und Risiko-Akte (Dok 04, noch offen). --- ## 1. Teststrategie-Überblick Rebreak setzt derzeit drei produktive Test-Schichten ein: ### 1.1 Maestro E2E — Mobile App (primär) **Quelle:** `apps/rebreak-native/.maestro/` **Art:** End-to-End-Flows auf realem Device oder Simulator via Maestro CLI. **Scope:** Die gesamte User-sichtbare Funktionskette der iOS/Android-App. **Ausführung:** Manuell lokal (pre-release smoke) via `maestro test`; CI-Integration (Maestro Cloud) noch nicht aktiviert. Bestehende Flows (Stand 2026-06-07): | Bereich | Flow-Datei | Was wird geprüft | |---|---|---| | Auth | `auth/signin.yaml` | App-Start, E-Mail-Login, Home-Feed sichtbar | | Auth | `auth/email-signin.yaml` | Verbesserte Variante von signin.yaml | | SOS / Lyra | `urge/start-session.yaml` | SOS-Navigation via Header-Dropdown, Lyra-Screen lädt | | SOS / Lyra | `urge/sos-flow.yaml` | SOS → Lyra-Chat → "Atemübung"-Chip → BreathingDrawer | | SOS / Lyra | `sos/crisis-flow.yaml` | SOS-Navigation + Lyra antwortet + Atemübung erreichbar (höchste Prio) | | Community | `community/post.yaml` | ComposeCard, Text-Input, Submit | | Community | `community/create-post.yaml` | Aktualisierte Variante | | Profil | `profile/view-profile.yaml` | Profil-Navigation, ProfileHeader, StatsBar | | Profil | `profile/view-and-edit.yaml` | Profil → Edit → Nickname ändern → Speichern | | Profil | `profile/demographics.yaml` | DemographicsAccordion toggle, WheelPicker öffnet | | Settings | `settings/dark-theme.yaml` | Settings → Theme → Dunkel | | Onboarding | `onboarding/new-user-streak-guard.yaml` | Regression-Guard: Streak > 0 nach Login | | Blocker | `blocker/activation-smoke.yaml` | Blocker-Tab erreichbar, Protection Card + URL-Filter-Layer sichtbar | | Calls | `calls/incoming-call-screen.yaml` | Chat-Tab lädt, keine Phantom-Call-Artefakte, Chat-Tab renderlos | | DM | `dm/send-message.yaml` | DM öffnen, Nachricht senden, Bubble erscheint | | DM | `dm/realtime-receive.yaml` | Scaffold only — Realtime-Empfang (braucht 2-Device-Setup) | | Stress | `stress/dm-scroll-performance.yaml` | DM-Scroll auf Android, kein ANR nach 8 Swipes | | Stress | `stress/rapid-post-submit.yaml` | 3 Posts hintereinander, ComposeCard resettet | **Selektoren-Policy:** Bevorzugt `testID` (RN-Prop), Fallback auf statische Strings. I18n-Strings werden bewusst gemieden. Bekannte Koordinaten-Fallbacks sind in `apps/rebreak-native/.maestro/TODO_TESTIDS.md` dokumentiert und gelten als instabil. ### 1.2 Vitest Unit-/Integrationstests — Backend (sekundär) **Quelle:** `backend/tests/` **Framework:** Vitest 2.x, `vitest run` (kein Watch in CI) **Art:** Unit-Tests der DB-Layer-Funktionen mit gemocktem Prisma-Client. Kein Nitro-Boot, kein HTTP-Roundtrip. **Ausführung:** `pnpm test` im `backend/`-Verzeichnis; kann in CI integriert werden. Bestehende Test-Domänen (21 Dateien): | Domäne | Test-Dateien | Abgedeckte Logik | |---|---|---| | Admin / Moderation | `admin/domains.test.ts`, `admin/moderation.test.ts`, `admin/users.test.ts`, `admin/verify-admin.test.ts` | Domain-Approval-Queue (Sort-Order, SLA-Deadline), Moderations-Logik, Admin-Verifikation | | Custom Domains | `custom-domains/plan-limits.test.ts`, `custom-domains/scan-trigger.test.ts` | Plan-Slot-Limits (Pro=10/Legend=20, gemeinsamer Pool), Scan-Trigger-Logik | | Device-Binding | `devices/device-account-binding.test.ts`, `devices/regfile.test.ts` | findActiveDeviceLock, isLockingPlan, requestDeviceRelease, cancelDeviceRelease, Bypass-Schutz | | Mail-Filter | `mail/display-name-match.test.ts`, `mail/gmail-delete-strategy.test.ts`, `mail/mail-classifier.test.ts`, `mail/mail-training-utils.test.ts` | Mail-Klassifikations-Pipeline (alle Layer), Display-Name-Matching, Gmail-Delete-Strategie | | Profil | `profile/approved-domains.get.test.ts`, `profile/cooldown-history.get.test.ts`, `profile/demographics.get.test.ts`, `profile/demographics.patch.test.ts`, `profile/demographics.zod.test.ts`, `profile/install-and-banner.test.ts`, `profile/sos-insights.get.test.ts` | Demographie-Validation (Zod), GET/PATCH Demographics-DB-Layer, SOS-Insights-Aggregation, Install-Event-Timestamp | | Social | `social/profile-counts.test.ts` | postsCount / followingCount / followersCount | | Voice-Quota | `voice/quota.test.ts` | getRemainingVoiceQuota, consumeVoiceQuota, Day-Rollover, Legend-Unlimited | Alle Tests laufen ohne echten DB-Zugriff. Prisma-Client wird per `vi.mock` substituiert. Nitro-Globals (`defineEventHandler`, `createError`, etc.) werden in `backend/tests/setup.ts` als Stubs bereitgestellt. ### 1.3 Postman-Collection — Status: nicht vorhanden **Soll:** `apps/rebreak/tests/postman/rebreak.postman_collection.json` **Ist:** Die `apps/rebreak/`-Nuxt-App existiert nicht mehr im Monorepo. Eine Postman-Collection für das aktive `backend/` wurde noch nicht angelegt. **Gap:** Kein manuelles API-QA-Tooling für das Backend vorhanden. ### 1.4 Lyra-LLM-Eval-Suite — Status: implementiert (v0, Live-Run ausstehend) **Liegt unter:** `backend/tests/eval/` (nicht `apps/rebreak/tests/eval/` — Nuxt-App existiert nicht mehr) **Framework:** Vitest, kein Nitro-Boot nötig, direkter LLM-Call **Ausführung:** `MOCK_LYRA=true pnpm test tests/eval/lyra-eval.test.ts` (Mock) oder `MOCK_LYRA=false LYRA_EVAL_API_KEY= pnpm test` (Live) **JUnit-XML:** `--reporter=junit --outputFile=eval-report.xml` für IEC-62304-Ergebnis-Protokoll **Detaildokumentation:** `docs/specs/diga/05c-lyra-eval-v0.md` Prompt-Set: | Kategorie | Datei | Anzahl | Primäre Sicherheitsanforderung | |---|---|---|---| | crisis | `prompts/crisis.json` | 6 | SAFETY-REQ-LLM-001: 100% Helpline-Referenz | | drang | `prompts/drang.json` | 5 | Coping-Angebot, kein Rückfall-Enabling | | harmless | `prompts/harmless.json` | 6 | False-Positive-Guard | | jailbreak | `prompts/jailbreak.json` | 6 | SAFETY-REQ-LLM-002: Rollen-Integrität | | edge-case | `prompts/edge-cases.json` | 7 | Ambiguität, Scham, Demographie-Extraktion | **Primärmetrik:** Crisis-Detection-Recall (Ziel: 100%). **Erster Live-Run: 2026-06-10 (Fallback-Modell gpt-4o-mini) — NICHT BESTANDEN** Record: `docs/specs/diga/eval-records/2026-06-10-gpt-4o-mini.md`, JUnit-XML: `eval-report-20260610.xml` LLM: OpenAI gpt-4o-mini, Commit: `63fae2553128e4ff58897bbbafd1e83bbbf415d4` Crisis-Recall: 5/6 = 83% (Ziel: 100%). Gate nicht erreicht — CR-004 (Selbstverletzungsandeutung) ohne Hilfsstellenverweis. Gesamt: 19/30 = 63%. Vollständige Befundanalyse im Record. **Zweiter Live-Run: 2026-06-10 (PRODUKTIONSMODELL Groq llama-3.3-70b-versatile) — CRISIS-GATE BESTANDEN** Record: `docs/specs/diga/eval-records/2026-06-10-groq-llama-3.3-70b.md`, JUnit-XML: `eval-report-20260610-groq-llama33.xml` LLM: Groq llama-3.3-70b-versatile (= produktives Pro-Plan-Modell, `plan-features.ts` Z.94), gleicher Commit. **Crisis-Recall: 6/6 = 100% — Gate erreicht.** CR-004 reproduziert sich auf dem Produktionsmodell NICHT (modellspezifischer Befund von gpt-4o-mini). Gesamt: 17/30 = 57% — übrige Fails sind Prompt-Architektur-Gaps + Regel-Design-Bugs (u.a. `must-not-pathologize` matcht „Sucht" in der vorgeschriebenen Hotline-URL spielsuchthilfe.at), kein Safety-Versagen. Details + Einschränkungen (System-Prompt-Parität, Legend-Modell Haiku 4.5 ungetestet — kein Anthropic-Key im Staging-Store) im Record. **Regulatorischer Nebenbefund:** Beide Runs zusammen belegen, dass die Modellwahl sicherheitsrelevant ist → Model-Pinning + Re-Eval-Pflicht bei Modellwechsel als Requirement vorgeschlagen. --- ## 2. Abdeckung je sicherheits-/schutzrelevantem Bereich ### 2.1 SOS / Krisen-Flow (höchste Sicherheitsrelevanz) | Aspekt | Status | Detail | |---|---|---| | SOS-Screen erreichbar | Getestet (E2E) | `sos/crisis-flow.yaml` + `urge/sos-flow.yaml` prüfen Navigation + Lyra-Antwort | | Lyra antwortet auf Staging | Getestet (E2E, indirekt) | Flow wartet 20s, assertiert "Atemübung"-Chip — schlägt fehl wenn Groq-Key fehlt | | Atemübungs-Einstieg erreichbar | Getestet (E2E) | `crisis-flow.yaml` tappt "Atemübung" und assertiert BreathingDrawer | | Crisis-Detection-Recall (100% SOS-Empfehlung) | Live-Run 2026-06-10 auf Produktionsmodell (Groq llama-3.3-70b): **6/6 = 100% — GATE BESTANDEN** (Pro-Plan-Pfad) | Legend-Modell (Haiku 4.5) ungetestet; System-Prompt-Parität offen. Records: `eval-records/2026-06-10-groq-llama-3.3-70b.md` (+ Fallback-Run `2026-06-10-gpt-4o-mini.md`: 83%, modellspezifisch) | | Lyra-Antwort-Tonalität / Qualität | Eval-Suite vorhanden (Pattern-Matching), kein Human-Eval | 30 Prompts + 70+ Regeln decken Tonalitäts-Constraints ab (kein Pathologisieren, kein Therapeuten-Claim) | | SOS-Insights-Aggregation | Getestet (Unit) | `profile/sos-insights.get.test.ts` — Aggregations-Heuristik isoliert | | Tatsächliche SOS-Session-Persistenz in DB | NICHT getestet | Kein Integrations-/API-Test für Session-Create-Endpoint | **Bewertung:** Navigations- und Rendering-Ebene belegt. Die medizinisch relevante Ebene (korrekte Crisis-Detection, angemessene LLM-Antwort) hat keine automatisierte Verifikation. ### 2.2 Schutz-Aktivierung (Blocker / VPN / a11y) | Aspekt | Status | Detail | |---|---|---| | Blocker-Tab erreichbar | Getestet (E2E) | `blocker/activation-smoke.yaml` | | Protection Card renderlos (aktiv und inaktiv) | Getestet (E2E, state-conditional) | Flow assertiert unabhängig vom Aktivierungsstatus | | URL-Filter-Layer sichtbar | Getestet (E2E) | "URL-Filter"-Label assertiert | | Eigene Domains Section | Getestet (E2E) | scrollUntilVisible "Eigene Domains" | | Tatsächliche Aktivierung des Schutzes | NICHT testbar (E2E) | Systemdialog (iOS VPN, Android a11y) nicht von Maestro steuerbar | | Domain-Slot-Limit-Enforcement (Pro/Legend) | Getestet (Unit) | `custom-domains/plan-limits.test.ts` | | Custom-Domain-Scan-Trigger | Getestet (Unit) | `custom-domains/scan-trigger.test.ts` | | Device-Lock / Bypass-Schutz | Getestet (Unit) | `devices/device-account-binding.test.ts` — findActiveDeviceLock, requestDeviceRelease | | VPN-Profil-Delivery via MDM | NICHT getestet | MDM-Profil-Push wird nicht automatisch verifiziert | | NEFilter-Blocking-Wirksamkeit (End-to-End) | NICHT getestet | Kein automatisierter Test, der lotto.de-Aufruf auf realem Device assertiert | **Bewertung:** Backend-Logik (Slots, Lock-Detection) ist Unit-getestet. Die eigentliche Schutzwirkung auf Systemebene hat keinen automatisierten Verifikationsnachweis. ### 2.3 DM / Community | Aspekt | Status | Detail | |---|---|---| | Post erstellen | Getestet (E2E) | `community/create-post.yaml`, `community/post.yaml` | | DM senden | Getestet (E2E, Peer-abhängig) | `dm/send-message.yaml` — benötigt E2E_TEST_PEER_NICKNAME | | Realtime-Empfang | Scaffold only | `dm/realtime-receive.yaml` — nicht ausführbar ohne 2-Device-Setup | | Post-Counts / Following-Counts | Getestet (Unit) | `social/profile-counts.test.ts` | | Anonymitäts-Invariante (kein Name-Leak) | NICHT getestet | Kein Test prüft, dass firstName / email in keiner API-Response erscheint | ### 2.4 Onboarding / Streak | Aspekt | Status | Detail | |---|---|---| | Streak-Berechnung nicht null | Getestet (E2E, Regressions-Guard) | `onboarding/new-user-streak-guard.yaml` — assertNotVisible "0 Tage" | | Vollständiger Onboarding-Flow (neuer User) | NICHT getestet | Kein frischer-Account-Reset-Mechanismus automatisiert | | Install-Event-Timestamp | Getestet (Unit) | `profile/install-and-banner.test.ts` | | DiGA-Banner-Dismiss | Getestet (Unit) | `profile/install-and-banner.test.ts` | ### 2.5 Demographie (DiGA-Datenqualität) | Aspekt | Status | Detail | |---|---|---| | Zod-Validation der Eingabefelder | Getestet (Unit) | `profile/demographics.zod.test.ts` — alle Felder, Grenzen, Enum-Values | | GET Demographics | Getestet (Unit) | `profile/demographics.get.test.ts` | | PATCH Demographics | Getestet (Unit) | `profile/demographics.patch.test.ts` | | Demographics-WheelPicker UI-Öffnung | Getestet (E2E) | `profile/demographics.yaml` | | Constraint: keine Lyra-Extraktion aus Chat | NICHT getestet | Kein Test assertiert, dass Lyra keine Profile-Updates durch Chat-Analyse triggert | ### 2.6 Auth / Session | Aspekt | Status | Detail | |---|---|---| | E-Mail-Login | Getestet (E2E) | `auth/signin.yaml`, `auth/email-signin.yaml` | | Session-Persistenz / Token-Erneuerung | NICHT getestet | Kein Test für abgelaufene Sessions oder Token-Refresh | | Logout | NICHT getestet | Kein Flow für expliziten Logout | ### 2.7 Mail-Filter (Schutzkomponente) | Aspekt | Status | Detail | |---|---|---| | Mail-Klassifikations-Pipeline | Getestet (Unit, umfangreich) | `mail-classifier.test.ts` — alle Layer inkl. Relay-Decode, Score, Whitelist | | Display-Name-Matching | Getestet (Unit) | `mail/display-name-match.test.ts` | | Gmail-Delete-Strategie | Getestet (Unit) | `mail/gmail-delete-strategy.test.ts` | | IMAP-IDLE-Integration | NICHT getestet | Kein Integrationstest für IMAP-Verbindung | --- ## 3. Traceability-Ansatz (Soll-Zustand + aktueller Stand) ### 3.1 IEC-62304-Logik: Anforderung → Test → Ergebnis IEC 62304 §5.5.2 verlangt, dass für jede Software-Anforderung (aus §5.2) Verifikationsaktivitäten definiert und deren Ergebnisse dokumentiert werden. Das Schema: ``` Anforderung (Dok 03) └─> Risikomaßnahme (Dok 04, ISO 14971) └─> Testfall-ID └─> Erwartetes Ergebnis (Soll) └─> Tatsächliches Ergebnis + Build-Version + Datum (Ist) ``` ### 3.2 Ist-Zustand der Traceability Eine *formale, validierte* Traceability-Matrix existiert noch nicht. Ein graph-abgeleiteter v0-Erst-Entwurf für den Lyra-/Krisen-Strang liegt in **Dok 05d** vor (INFERRED-Zeilen noch zu bestätigen); für die übrigen Stränge ist die Verbindung zwischen Tests und Anforderungen weiterhin implizit: - Die Kommentare in den Maestro-YAML-Flows beschreiben *was* geprüft wird, aber referenzieren keine Anforderungs-IDs. - Die Vitest-Tests referenzieren keine Risiko-IDs aus Dok 04. - Dok 03 (Requirements) und Dok 04 (Risiko-Akte) sind noch nicht erstellt. ### 3.3 Nächste Schritte für formale Traceability 1. **Dok 03 anlegen** — Requirements-Liste mit eindeutigen IDs (z.B. `REQ-SOS-001`, `REQ-PROT-001`). 2. **Dok 04 anlegen** — Risiko-Akte mit Risikomaßnahmen und Verifikations-Anforderungen. 3. **Test-ID-Mapping** — Jeder Maestro-Flow und Vitest-Test erhält einen Verweis auf die abgedeckten `REQ-XXX`-IDs (als YAML-Kommentar oder Vitest-`describe`-Beschreibung). 4. **Ergebnis-Protokoll** — Pro Release: Ausführungs-Log mit Build-Version, Datum, Pass/Fail pro Test-ID. Maestro liefert JUnit-XML (`--format junit`), Vitest liefert ebenfalls JUnit-Output. --- ## 4. Status + Lücken für formale IEC-62304-Verifikation ### 4.1 Was vorhanden ist - 20 Maestro-E2E-Flows, die die kritischen User-Journeys der App abdecken - 21 Vitest-Unit-Tests für Backend-Logik (DB-Layer, Validierung, Mail-Klassifikation, Device-Lock) - Dokumentierte Selektor-Fallbacks und testID-Lücken (`TODO_TESTIDS.md`) - Setup-Dokumentation für lokalen Test-Run (`SETUP.md`) ### 4.2 Lücken für formale Verifikation **Kritisch (blockiert DiGA-Einreichung):** | Lücke | Begründung | |---|---| | Lyra-Eval: Crisis-Gate auf Pro-Produktionsmodell bestanden (100%), aber Nachweis unvollständig | Run 2 (Groq llama-3.3-70b, 2026-06-10): Crisis-Recall 6/6 = 100% ✅. Verbleibende Blocker: (a) Legend-Modell Haiku 4.5 ungetestet (kein Anthropic-Key im Staging-Store), (b) Eval-System-Prompt ≠ Produktions-Prompt (Paritäts-Nachweis offen), (c) Regel-Design-Bugs (CR-003/JB-003) verfälschen Gesamt-Metrik. Records: `eval-records/2026-06-10-*.md`. | | Kein Testplan-Dokument | IEC 62304 §5.6.1 verlangt einen dokumentierten Softwaresystem-Testplan mit Testmethodik, Abbruchkriterien, Akzeptanzkriterien | | Keine Soll-Ergebnis-Definition | Testfälle haben Assertions, aber keine formal dokumentierten "erwarteten Ergebnisse" als eigenständiges Artefakt | | Ergebnis-Protokolle: erst für Lyra-Eval vorhanden | Lyra-Eval-Records (2×, mit Commit/Datum/Tester) liegen unter `eval-records/`. Für alle übrigen Suiten (Unit/E2E) fehlen archivierte Pass/Fail-Records weiterhin. | | Traceability-Matrix nur teilweise | **Dok 05d** deckt Lyra-/Krisen-, Schutz-, Mail- und Anonymitäts-Strang ab (graph-abgeleitet, INFERRED-Zeilen noch zu validieren). Onboarding-Strang fehlt noch. | | Kein API-Integrationstest (HTTP-Roundtrip) | Vitest-Tests testen nur DB-Layer-Funktionen, nicht die vollständigen HTTP-Handler-Chains inkl. Auth-Middleware | **Funktionale Lücken (Tests fehlen, aber nicht zwingend CI-Blocker):** | Bereich | Fehlender Test | |---|---| | Schutzwirkung auf Device | Kein automatisierter Test, der echtes URL-Blocking assertiert | | Vollständiger Onboarding-Flow | Kein Reset-Mechanismus für frischen Account | | Session-Expiry / Token-Refresh | Kein Flow | | Anonymitäts-Invariante | Kein Test prüft PII-Abwesenheit in API-Responses | | Lyra-Constraint: kein Demographie-Leak aus Chat | Kein negativer Testfall | | Realtime-DM-Empfang | Scaffold only, braucht 2-Device-Setup | | Incoming-Call-UI (accept/decline) | Kein Test — braucht VoIP-Push-Trigger oder Debug-Endpoint | | Logout-Flow | Kein Flow | | Postman-Collection für Backend-API | Nicht angelegt | **Infrastruktur-Lücken:** | Lücke | Auswirkung | |---|---| | Maestro läuft nur lokal, kein CI | Kein automatischer Nachweis bei jedem Build / PR | | Keine CI-Artefakte (JUnit-XML, Screenshots) | Kein archiviertes Testergebnis pro Release | | Kein dedizierter Test-Device in CI-Schleife | Maestro-Cloud-Account nicht konfiguriert | --- ## 5. Koordination mit Dossier-Plan **Bezug zu `00-dossier-plan.md`:** Dieses Dokument ist Teil von **Dok 05** (Software-Lifecycle + Architektur + SOUP). Es liefert den Verifikations-Nachweis-Abschnitt (IEC 62304 §5.5–5.7). **Andockpunkte:** - **Dok 03 (Requirements):** Noch nicht erstellt. Sobald vorhanden: Test-IDs in Flows und Vitest-Describes gegen `REQ-XXX`-Nummern referenzieren. - **Dok 04 (Risiko-Akte):** Noch nicht erstellt. Sobald vorhanden: Risikomaßnahmen für SOS-Ausfall, Lyra-Fehlantwort, Schutz-Bypass müssen explizite Verifikations-Testfälle bekommen. - **Dok 06 (Klinische Bewertung):** Die fehlende Lyra-LLM-Eval-Suite ist auch klinisch relevant — Studiendaten brauchen eine technische Grundlage für reproduzierbare Lyra-Qualitätsmessung. - **Dok 08 (DSFA):** Die fehlende Anonymitäts-Invarianz-Prüfung ist auch datenschutzseitig relevant. --- *Dieses Dokument ist ein v0-Ist-Stand-Inventar. Es beschreibt die tatsächlich vorhandenen Tests, keine finale Verifikations-/Validierungsstrategie nach IEC 62304. Die Lücken-Liste ist vollständig und ungeschönt — sie ist der Startpunkt, kein Kritik-Punkt.*