# Rebreak — Testing State Audit & Roadmap Author: Ahmed (QA) · Stand: 2026-05-07 · Status: Initial Audit, READ-ONLY Dieses Dokument ist eine ehrliche Bestandsaufnahme. Antwort auf User-Frage: „was und wie testen wir, welche Abdeckungsrate, wo drückt der Schuh". Kurzfassung in einem Satz: Im neuen `rebreak-monorepo` existiert **null automatisierte Test-Coverage**. Nicht „wenig" — **Null**. Die alte trucko-Suite (114 Vitest-Tests + Postman + Playwright) deckt eine andere Architektur (Nuxt + Capacitor) ab und ist nicht 1:1 portierbar. --- ## 1. Status quo (rebreak-monorepo) ### 1.1 Backend (`backend/`, Nitro standalone, Prisma + Supabase) | Aspekt | Stand | | ------------------- | ------------------------------------------------------------ | | Test-Verzeichnis | nicht vorhanden (`tests/`, `__tests__/`, `*.test.ts` = leer) | | Test-Framework | nicht installiert | | Coverage-Tool | keins | | `package.json` test | kein `test`-Script vorhanden | | API-Endpoints | 122 Files in `server/api/**` — 0 abgedeckt | | DB-Layer | 16 Files in `server/db/**` — 0 abgedeckt | | Utils | 11 Files in `server/utils/**` — 0 abgedeckt | | Middleware | `cors.ts` — 0 abgedeckt | **Coverage-Schätzung Backend: 0 %.** ### 1.2 Frontend (`apps/rebreak-native/`, Expo SDK 53 + RN 0.79) | Aspekt | Stand | | ------------------- | ---------------------------------------------------------------- | | Test-Verzeichnis | nicht vorhanden | | `.maestro/` | nicht vorhanden | | Test-Framework | weder `jest-expo` noch `@testing-library/react-native` installed | | `package.json` test | nur `lint` + `typecheck`, kein `test` | | Components | 58 Files — 0 abgedeckt | | Hooks | 13 Hooks (`useMe`, `useUserPlan`, …) — 0 abgedeckt | | Stores | 4 Zustand-Stores (`auth`, `coach`, `community`, `notifications`) — 0 abgedeckt | | Lib (sosStream, llmProvider, ttsProvider, lyraResponse) | 17 Files — 0 abgedeckt | | App-Routes | 11 Top-Level (`urge.tsx`, `lyra.tsx`, `auth/*`, `(app)/*`, `profile/*`) — 0 abgedeckt | **Coverage-Schätzung Frontend: 0 %.** Native-Module-Pfad `apps/rebreak-native/modules/rebreak-protection/android/src/test` existiert als leerer Gradle-Skeleton, ohne reale Test-Klassen — Backyard's Scope. ### 1.3 CI / CD - `.github/workflows/` existiert nicht im rebreak-monorepo. - Es gibt **keinen** `rebreak-unit`-Job (existierte in trucko-monorepo, wurde nicht migriert). - `xgit`-Deploy-Pipeline buildet ohne Tests durchzulaufen. - Pre-commit-Hooks: keine. - TypeScript ist die einzige stille Schutzlinie (`pnpm typecheck` in beiden Paketen). ### 1.4 Zusammenfassung > 0 Tests, 0 CI-Gate, 0 Coverage. Die Auth-Middleware-500-Cascade dieser Woche wäre > mit einem 8-Zeilen-Vitest-Test für `requireUser()` verhindert worden. --- ## 2. Heritage aus trucko-monorepo (was portierbar / inspirierend ist) Pfad: `~/mono/trucko-monorepo/apps/rebreak/tests/` ### 2.1 Vitest Unit-Suite — gold-wert, ~70 % portierbar `tests/unit/` — 6 Dateien, 114 Tests, alle grün (geprüft 2026-04-28): | Datei | Was getestet | Portierbar? | | --------------------------- | ------------------------------------------------------------- | ------------------------ | | `cooldown.test.ts` | `signCooldownToken`, `verifyCooldownToken`, DB-Layer | Ja, 1:1 | | `domain-blocklist.test.ts` | `getBlocklistedDomainsSet` Subdomain-Matching | Ja, 1:1 | | `domain-limits.test.ts` | Plan-Limit-Enforcement bei Custom-Domains | Ja, 1:1 | | `domain-validation.test.ts` | Domain-Regex + Sanitisierung | Ja, 1:1 | | `domain-vote.test.ts` | `castDomainVote` Auto-Approve-Logik | Ja, 1:1 | | `plan-features.test.ts` | `PLAN_LIMITS`, `getPlanLimits` für free/pro/legend | Ja, mit Tier-Update | Alle nutzen `vi.mock('../../server/utils/prisma', …)` — keine echte DB nötig, läuft in Sekunden, kein Secret-Setup. **Quick win:** copy + adjust import-paths (`apps/rebreak/server/...` → `backend/server/...`). ### 2.2 Postman-Collection — sofort wiederverwendbar `tests/postman/rebreak.postman_collection.json` deckt 12 Domains (Auth, Profile, Streaks, Posts, Chat, Lyra, Notifications, Cooldown, Domain-Submissions, Blocklist, Scores, Sicherheit-401-Sammlung). Anpassungs-Aufwand: - `{{baseUrl}}` ist URL-only, funktioniert für Nitro-standalone identisch. - Auth-Pfad bleibt `POST /api/auth/login` — selbe Route in neuem Backend. - Token-Auto-Extract-Skript funktioniert, da Backend Bearer-Token zurückgibt. - Eventuell veraltete Endpoints (`/api/blocklist/*`, `/api/scores/*`) gegen neue routes der Standalone-API verifizieren. ### 2.3 Playwright Smoke (`tests/e2e/smoke/`) **Nicht portierbar** für Native-App. Nuxt-DOM-Selektoren, Browser-only, irrelevant für Expo. `fixtures/auth.ts` (`loginAs(page, …)`) ist konzeptuell wiederverwendbar für Maestro `JS-onFlowStart` — aber neu schreiben. ### 2.4 Cypress-Suite (`apps/rebreak/cypress/e2e/`) `01-smoke.cy.ts`, `02-a11y.cy.ts` — Capacitor-Webview, irrelevant für RN. Skip. --- ## 3. Risk-Matrix — Top 10 ungetestete Critical Paths Bewertung: **Risk = max(DSGVO-Risk, User-Trust-Risk, DiGA-Risk, Recovery-Risk)**. | # | Pfad | Risk | Why | Empf. Test-Form | | -- | ------------------------------------------------------ | -------- | ------------------------------------------------------------------------------ | -------------------------------- | | 1 | `server/utils/auth.ts` → `requireUser()` | KRITISCH | Diese Woche 500-Cascade durch Bug. Jeder Endpoint hängt dran. | Unit (vitest) + supertest | | 2 | `coach/sos-stream.get.ts` (Tier-LLM-Switch) | KRITISCH | Free/Pro=Groq, Legend=Haiku. Falscher LLM für falschen User = User-Trust-Bruch + Brand-Voice-Bruch. | Integration mit Plan-Mock | | 3 | `coach/sos-stream.get.ts` (SSE-Stream + Chip-JSON) | KRITISCH | SOS ist Recovery-Schutz. Stream-Bruch oder Chip-Parse-Fail = User in Krise allein. | Integration + Stream-Snapshot | | 4 | `community/post.post.ts` + `posts.get.ts` (Anonymität) | KRITISCH | DSGVO Art. 9 + Glücksspiel-Stigma. Wenn UI plötzlich `firstName`/`username` statt `nickname` liefert = Disaster. | Unit (DB-select-shape) + e2e | | 5 | `cooldown/{request,status,cancel}.post/get.ts` | HOCH | DiGA-relevant Recovery-Schutz. Token-Sign/Verify war in trucko getestet — muss in neue Codebase portiert. | Unit (vitest, gemockt) | | 6 | `urge/index.post.ts` + `lib/sosTtsQueue.ts` | HOCH | Urge-Logging ist Recovery-Kern-Feature. TTS-Queue = aktuell offen-modifiziert (siehe `git status`). | Unit + Component-Test | | 7 | `auth/login.post.ts` + `auth/me.get.ts`/`me.patch.ts` | HOCH | Profile-Update = Demographics = DiGA-Daten. Bug = falsche Kohorten-Daten in BfArM-Antrag. | Unit (Zod-validate) + Postman | | 8 | `stripe/webhook.post.ts` + Pro-Trial-Reward-Trigger | HOCH | Pro-Trial-Logik (Phase C, kommt). Missing Test = Free-User bekommen versehentlich Lifetime-Pro oder umgekehrt. | Unit + Integration mit Stripe-mock | | 9 | `lib/llmProvider.ts` + `lib/sosStream.ts` (Frontend) | HOCH | Resolved-Provider-Logik passt zum Backend. Wenn Drift entsteht, sehen User falschen LLM-Pill (UX-Lüge). | Unit (RN-jest) | | 10 | `mail/scan.post.ts` + `mail/connect.post.ts` | MITTEL | Mo's Scope, aber Recovery-relevant. Mail-Scan-Bug = User bekommt Casino-Newsletter durchgelassen. | Integration | Nicht in Top 10 aber erwähnenswert: - `protection/*` (URL-Filter-Blocklist) — DiGA-relevant, aber binär/idempotent - `scores/*` (Leaderboard) — Anonymität-Risk via `feedback_anonymity_nickname.md` - `notifications/*` — Push-Anrede mit `firstName` statt `nickname` = Anonymitäts-Bruch --- ## 4. Roadmap ### 4.1 Pre-TestFlight (Wochenende, Mai 2026) — absolutes Minimum Ziel: App stürzt im TestFlight nicht beim Launch ab + die zwei kritischsten User-Journeys (Login + SOS-Trigger) funktionieren auf einem echten iPhone-Build. | Task | Form | Aufwand | | ----------------------------------------------------------------- | ------------- | ------- | | Maestro CLI installieren + `apps/rebreak-native/.maestro/` anlegen | Setup | 30 min | | Smoke-Flow `auth/sign-in.yaml` (Username + Pwd → App-Shell) | Maestro | 1 h | | Smoke-Flow `sos/start.yaml` (Login → SOS-Button → Chat-Stream sieht 1+ Token) | Maestro | 1.5 h | | Smoke-Flow `community/feed-loads.yaml` (Login → Feed → 1+ Post sichtbar) | Maestro | 1 h | | Manueller Postman-Run der 12-Domain-Collection gegen Staging | manuell | 1 h | | Backend-Sanity: `pnpm build:backend` + curl-Smoke gegen 5 wichtigste Endpoints (`/api/auth/me`, `/api/coach/sos-stream`, `/api/community/posts`, `/api/cooldown/status`, `/api/urge`) | manuell | 30 min | **Wichtig:** das ist NUR Smoke. Keine Plan-Tier-Permutationen, keine Edge-Cases. „Stürzt nicht ab + Happy-Path geht durch" ist das einzige Bestehen-Kriterium. ### 4.2 Post-TestFlight (Woche 1-2 nach Wochenend-Cutover) | Task | Form | Aufwand | | ------------------------------------------------------------------------------------- | ------------ | ------- | | Vitest setup im `backend/` (vitest.config.ts, `pnpm add -D vitest @vitest/coverage-v8`) | Setup | 30 min | | Port `cooldown.test.ts` von trucko nach `backend/tests/unit/` | Port + adjust| 1 h | | Port `plan-features.test.ts` (mit Tier-Update legend-Pfad) | Port + adjust| 1 h | | Port `domain-{blocklist,limits,validation,vote}.test.ts` | Port + adjust| 2 h | | **NEU** `auth-requireUser.test.ts` — Bug-Replikation (Bearer fehlt, Bearer invalid, Plan-Lookup fail) | Unit | 2 h | | **NEU** `lyraMemoryExtract.test.ts` — Klarnamen-Replacement-Pipeline | Unit | 1 h | | Supertest-Setup für Integration (Nitro `.output/server` startable im Test) | Setup | 2 h | | Integration: `auth/login` + `auth/me` Happy + 401-Pfad | Integration | 2 h | | GitHub Action `rebreak-test.yml` — Job `backend-unit` (vitest run + coverage) | CI | 1 h | | Postman-Collection nach `backend/tests/postman/` portieren + `{{baseUrl}}` auf staging.rebreak.org | Port | 2 h | Coverage-Ziel nach Phase 2: **40 % Backend-Statements, 100 % der `utils/`-Files, 100 % `requireUser`-Branches.** ### 4.3 Phase C (Demographics + Pro-Trial) — TDD parallel User-Auftrag steht: Demographics-Form + 1-Woche-Pro-Trial-Reward. Hier MUSS Test parallel zur Implementation laufen, weil: - Reward-Trigger-Bug = Free-Lifetime-Pro oder Trial-nie-revoked (Stripe-revenue-leak) - DSGVO-Wording-Pflicht („nicht Daten-gegen-Geld") - DiGA-Daten-Integrität | Test | Form | | ----------------------------------------------------------------------- | ----------- | | `profile/me/demographics.patch.test.ts` — alle 5 Felder gesetzt → Trial | Unit | | `profile/me/demographics.patch.test.ts` — Free + bereits Trial-used → kein Re-Trial | Unit | | `profile/me/demographics.patch.test.ts` — Pro/Legend → kein Trial-Trigger | Unit | | Cron-Test: `pro-trial-revoke.cron.test.ts` — nach 7d zurück auf free, sofern kein Stripe-Abo | Unit | | Maestro `profile/demographics-fill.yaml` — Free-User füllt alle Felder, sieht Pro-Reward-Banner | E2E | ### 4.4 DiGA-Pathway — Hans-Müller-Frage BfArM erwartet für DiGA-Approval (laut `hans-mueller.md` Scope): - **Penetrationstest-Bericht** (jährlich) — externer Anbieter, nicht Ahmed's Scope - **DSFA-Dokument** (Datenschutz-Folgenabschätzung) — Hans-Müller's Scope - **ISO 27001 oder BSI-Grundschutz** — DevOps/Backyard's Scope Was BfArM **nicht direkt** verlangt aber bei Audit fragt: - „Ist Ihre Software automatisiert getestet? Welche Coverage?" - „Wie verhindern Sie Regressionen bei Updates?" - „Wie testen Sie Crisis-Detection-Logik?" **Ahmed-Empfehlung:** für DiGA-Antrag streben wir an: **70 % Backend-Coverage, 60 % Frontend-Coverage, 100 % Crisis-Detection-Recall (Lyra-Eval-Suite), dokumentierter Test-Plan + CI-Pipeline-Gate.** Das ist nicht Pflicht aber glaubwürdigkeits-prägend. **Frage an User: soll Hans-Müller das im DSFA-Dokument explizit machen?** --- ## 5. Tooling-Empfehlungen ### 5.1 Backend - **Test-Framework: vitest 2.x.** Schnell (esbuild), TS-nativ, `vi.mock`-Pattern matched 1:1 unsere trucko-Heritage. Kein Jest (langsamer, schlechtere TS-DX in Nitro-Welt). Bun-test ist verlockend aber nitro+prisma stack ist node-validiert. - **Coverage: `@vitest/coverage-v8`.** Built-in, schnell, accurate. - **Integration-Tests: supertest** gegen ein in-process Nitro-`.output/server` bundle. Alternativ: `pnpm dev` als Sidecar in CI starten und gegen `localhost:3001` fetchen. - **Mocking: Prisma via `vi.mock('../../server/utils/prisma', …)`** wie in trucko. Supabase-Client per `vi.mock('@supabase/supabase-js', …)`. - **Test-DB: NICHT setzen** in Phase 1+2. Mock reicht. Wenn später Migration-Tests gebraucht: Postgres-Container in CI. ### 5.2 Frontend (Native) - **Component-Tests: `jest-expo` + `@testing-library/react-native`.** Standard Expo-Stack, gut dokumentiert. Snapshot-Tests sparsam (nur für stabile Strings, kein i18n-Output). - **E2E: Maestro.** Bereits in `ahmed.md` als Standard definiert. iOS+Android YAML-Flows, kein Detox-Maintenance-Hell. Cloud-Run möglich für CI. **NICHT Detox** — Setup-Aufwand zu hoch für unsere Team-Größe. - **`testID`-Konvention:** `--`, z.B. `auth-username-input`, `urge-sos-trigger-btn`. Component-Edits dafür sind erlaubt (in ahmed.md geregelt). ### 5.3 CI - **GitHub Actions** `.github/workflows/rebreak-test.yml`: - Job `backend-unit`: `pnpm install` → `pnpm --filter rebreak-backend test` → Coverage-Upload als Artifact. Läuft auf jedem PR. - Job `frontend-unit`: `pnpm --filter rebreak-native test`. PR-only. - Job `maestro-cloud`: nur main-Branch + manuell via `workflow_dispatch`, Maestro-Cloud-Token aus Secrets, gegen Staging-Build. - **Coverage-Threshold (vitest):** Phase 2 weich (40/40), Phase C streng (70 % critical paths in `server/utils/`, `server/api/coach/`, `server/api/auth/`). --- ## 6. Konkrete TODOs nach Priorität ### Hoch (vor TestFlight, Wochenende) | # | TODO | Aufwand | Owner | | - | --------------------------------------------------------------------- | ------- | -------------- | | 1 | Maestro CLI auf Mac + Android-Emulator + iOS-Sim installieren | 30 min | User | | 2 | `apps/rebreak-native/.maestro/auth/sign-in.yaml` schreiben | 1 h | Ahmed | | 3 | `.maestro/sos/start.yaml` schreiben (testID's am SOS-Button + LLM-Pill nötig — Edit-Approval) | 1.5 h | Ahmed + UI | | 4 | `.maestro/community/feed-loads.yaml` schreiben | 1 h | Ahmed | | 5 | Postman-Collection nach `backend/tests/postman/` kopieren + Staging-Env | 1 h | Ahmed | | 6 | Manueller Curl-Smoke-Sheet der Top-5-Endpoints + Erwartungs-Status-Codes | 30 min | Ahmed | ### Mittel (Woche 1-2 nach TestFlight) | # | TODO | Aufwand | | -- | ------------------------------------------------------------------- | ------- | | 7 | Vitest setup `backend/` + erste Test `plan-features.test.ts` portiert | 1.5 h | | 8 | Port der 5 weiteren trucko-unit-Tests | 4 h | | 9 | Neuer Test `auth-requireUser.test.ts` (Bug-Replikation diese Woche) | 2 h | | 10 | GitHub Action `rebreak-test.yml` Job `backend-unit` | 1 h | | 11 | Supertest + Integration-Setup, dann `auth/login.integration.test.ts` | 2 h | | 12 | jest-expo + `@testing-library/react-native` setup im `apps/rebreak-native` | 1 h | | 13 | Erster RN-Test: `lib/llmProvider.test.ts` (Plan-Tier-Resolve-Logik) | 1.5 h | | 14 | Erster Component-Test: `components/profile/ProfileHeader.test.tsx` | 1.5 h | ### Niedrig (Woche 3+) | # | TODO | Aufwand | | -- | ------------------------------------------------------------------- | ------- | | 15 | Lyra-Eval-Suite (Crisis-Detection Golden-Prompts) aus trucko porten | 4 h | | 16 | Maestro-Flow für Phase-C Demographics + Pro-Trial-Reward | 2 h | | 17 | Stripe-Webhook-Test mit Stripe-Mock + Test-Mode | 3 h | | 18 | DSFA-Anhang: Test-Coverage-Statement mit Hans-Müller abstimmen | 1 h | | 19 | Penetrationstest-Provider auswählen (DiGA-Pflicht, jährlich) | User-Decision | | 20 | Coverage-Threshold in CI-Gate hochziehen auf 70 % critical paths | 1 h | --- ## 7. Wo der Schuh am stärksten drückt — TL;DR 1. **Auth-Middleware ungeschützt.** Der 500-Cascade dieser Woche war ein Lehrgeld-Bug. Ein 50-Zeilen-Vitest-File hätte ihn vor Deploy gefangen. Höchste Priorität. 2. **SOS-Stream + Tier-LLM-Routing ungeschützt.** Wenn ein Free-User den falschen LLM bekommt oder der Stream bricht ab in der Krise — wir verlieren Vertrauen plus das ist ein DiGA-Recovery-Risk. 3. **Anonymität-Pattern ungeschützt.** Wenn jemand bei einem Refactor versehentlich `select: { firstName: true }` schreibt statt `{ nickname: true }`, sehen plötzlich alle User echte Namen. DSGVO Art. 9 + Stigma + DiGA = sofortige Krise. 4. **Pro-Trial-Reward kommt ohne Tests** — Stripe-Revenue-Leak-Risiko, Phase C ist Pflicht-TDD-Zone. 5. **Kein CI-Gate.** Jeder Push kann grün durchdeployen, auch wenn die Codebase tot ist. Das muss als erstes nach TestFlight kommen. --- ## 8. Open Questions an User 1. **Maestro Cloud Account oder lokale Runs?** Cloud kostet ~10 EUR/Monat, gibt parallele iOS+Android-Runs in CI. Lokal ist gratis aber blockt Mac-CPU. 2. **Pen-Test-Provider für DiGA-Pflicht?** Jährlich, ca. 5-15k EUR. Ahmed kann Vorschläge sammeln (Cure53, SektionEins, CrowdStrike-Partner) — User-Decision. 3. **Demographics + Pro-Trial: TDD oder Test-after?** Empfehlung TDD, weil Reward-Logik in Stripe + DSGVO-relevante Pfade. Bestätigung gewünscht? 4. **Coverage-Threshold-Strategie:** soft (warning, kein Block) oder hard (PR-Block bei Drop)? Empfehlung: erste 6 Wochen soft, danach hard auf 60 %. 5. **Hans-Müller-Frage:** Soll die DSFA explizit eine Test-Coverage-Quote für DiGA-Antrag committen? Wenn ja — dann müssen wir vor BfArM-Submission beweisbar sein. --- Ende. — Ahmed