# Review-Fixes 2026-04-18 — Implementation Plan > **Quelle:** `docs/superpowers/review/REVIEW-2026-04-18.md` + Sub-Reports. > **Branch:** `review-fixes-2026-04-18` > **Goal:** Alle HIGH/MEDIUM Findings aus dem Code-Review adressieren, bewusst verschobene Items dokumentieren. > **Architecture:** Inkrementelle Refactors, jeder atomar committed + gepusht, Tests nach jedem Wave grün. > **Tech-Stack:** SvelteKit, TypeScript-strict, Zod, Vitest, better-sqlite3, Service-Worker. --- ## Was wird angegangen (must-do) | # | Wave | Zeit | Begründung | |---|------|------|------------| | 1 | Doku-Fixes (ARCHITECTURE/OPERATIONS/handoff) | 5 min | Hoher Wert, trivialer Aufwand | | 2 | constants.ts + Image-Endpoint EN + interne Types | 30 min | Alle "Quick-Wins" aus REVIEW | | 3 | api-helpers.ts (parsePositiveIntParam + validateBody) | 1-2 h | Refactor A — 9+11 Call-Sites | | 4 | requireProfile() + asyncFetch Wrapper | 1 h | Profile-Guard 4× + fetch-Pattern 5× | | 5 | Cleanup (yauzl-Doku, baseRecipe-Fixture, Console-Logs) | 30 min | Restliche LOW-Findings | | 6 | Ingredient-Parser Edge-Cases (Refactor D) | 2-3 h | Locale-Komma, Unicode-Brüche, Bounds | | 7 | Verifikation (test/check/build, Docker-Smoke) | 30 min | Baseline gegen Regressionen | | 8 | Re-Review + OPEN-ISSUES-NEXT.md | 1 h | Beweis + Ausblick | ## Was bewusst NICHT angegangen wird (Begründung in OPEN-ISSUES-NEXT.md) - **Refactor B** (Search-State-Store, halber Tag): Touch von 808-Zeilen-Page + 678-Zeilen-Layout, bricht riskant Frontend ohne UAT. Eigene Phase planen. - **Refactor C** (RecipeEditor zerlegen): Review sagt explizit "keine Eile, solange niemand sonst drin arbeitet". - **SearXNG Rate-Limit Recovery**: Größeres Feature, eigene Phase. - **SW-Zombie-Cleanup Unit-Tests**: Bereits 6 pwa-store-Tests vorhanden, Erweiterung wäre Bonus. - **JSON-LD Parser Edge-Cases** (Locales): Weniger Käse als Ingredient-Parser-Issues, eigene Iteration. --- ## Wave 1 — Doku-Fixes **Files:** `docs/ARCHITECTURE.md:55`, `docs/OPERATIONS.md:135`, `docs/superpowers/session-handoff-2026-04-17.md:46` - [ ] ARCHITECTURE.md: `recipe_ingredient` + `recipe_step` → `ingredient` + `step` - [ ] OPERATIONS.md: `IMAGES_PATH` → `IMAGE_DIR` - [ ] session-handoff: `/api/recipes/[id]/image` (POST/DELETE) ergänzen - [ ] Commit `docs(review): Doku-Mismatches korrigiert` ## Wave 2 — Konstanten + Cleanup **Files:** `src/lib/constants.ts` (neu), `src/routes/+page.svelte`, `src/lib/client/pwa.svelte.ts`, `src/routes/api/recipes/[id]/image/+server.ts`, `src/lib/sw/cache-strategy.ts`, `src/lib/sw/diff-manifest.ts` - [ ] `src/lib/constants.ts` mit `SW_VERSION_QUERY_TIMEOUT_MS = 1500`, `SW_UPDATE_POLL_INTERVAL_MS = 30 * 60_000` - [ ] Image-Endpoint: deutsche Fehlermeldungen → englisch (Konsistenz) - [ ] `RequestShape` / `ManifestDiff`: `export` weg wenn rein intern - [ ] Test + check, Commit ## Wave 3 — api-helpers.ts (TDD) **Files:** `src/lib/server/api-helpers.ts` (neu), `tests/unit/api-helpers.test.ts` (neu), `src/lib/types.ts` (ErrorResponse) ### 3a Helper bauen - [ ] Test: `parsePositiveIntParam("42", "id")` → 42 - [ ] Test: `parsePositiveIntParam("0", "id")` wirft 400 - [ ] Test: `parsePositiveIntParam("abc", "id")` wirft 400 - [ ] Test: `parsePositiveIntParam(null, "id")` wirft 400 - [ ] Test: `validateBody(invalid, schema)` wirft 400 mit issues - [ ] Test: `validateBody(valid, schema)` returns parsed - [ ] Implement helpers - [ ] Tests grün, Commit ### 3b Migration parseId → parsePositiveIntParam (9 Sites) Files (jeder Endpoint): - `src/routes/api/recipes/[id]/+server.ts` - `src/routes/api/recipes/[id]/favorite/+server.ts` - `src/routes/api/recipes/[id]/rating/+server.ts` - `src/routes/api/recipes/[id]/cooked/+server.ts` - `src/routes/api/recipes/[id]/comments/+server.ts` - `src/routes/api/recipes/[id]/image/+server.ts` - `src/routes/api/profiles/[id]/+server.ts` - `src/routes/api/domains/[id]/+server.ts` - `src/routes/api/wishlist/[recipe_id]/+server.ts` - [ ] Pro Endpoint: lokales parseId entfernen, Helper importieren - [ ] Tests grün - [ ] Commit ### 3c Migration safeParse → validateBody Files: alle `+server.ts` mit `safeParse`. ErrorResponse-Shape standardisieren. - [ ] Pro Endpoint umstellen - [ ] Tests grün - [ ] Commit ## Wave 4 — Client-Helpers ### 4a requireProfile() - [ ] Helper in `src/lib/client/profile.svelte.ts` ergänzen - [ ] 4 Sites in `src/routes/recipes/[id]/+page.svelte` ersetzen - [ ] Test + Commit ### 4b asyncFetch Wrapper - [ ] `src/lib/client/api-fetch-wrapper.ts` mit `asyncFetch(url, init, actionTitle)` - [ ] 5 Sites umstellen: `recipes/[id]/+page.svelte` (2×), `admin/domains/+page.svelte` (2×), `admin/profiles/+page.svelte` - [ ] Test + Commit ## Wave 5 — Cleanup - [ ] yauzl: Inline-Kommentar in package.json: "Reserved for Phase 5b ZIP-Backup-Import" - [ ] baseRecipe Fixture nach `tests/fixtures/recipe.ts` (wenn dupliziert) - [ ] Console-Logs: per `if (import.meta.env.DEV)` wrappen oder absichtlich-Kommentar - [ ] Commit ## Wave 6 — Ingredient-Parser Edge-Cases **Files:** `src/lib/server/parsers/ingredient.ts`, `tests/unit/ingredient.test.ts` ### Tests zuerst (red) - [ ] Locale-Komma: `"1,5 kg Mehl"` → qty 1.5 - [ ] Unicode-½: `"½ TL Salz"` → qty 0.5 - [ ] Unicode-⅓: `"⅓ Tasse Wasser"` → qty 1/3 - [ ] Unicode-¼: `"¼ kg Zucker"` → qty 0.25 - [ ] Negativ: `"-1 EL Öl"` → wirft / qty=null - [ ] Null: `"0 g Mehl"` → wirft / qty=null - [ ] Führende Null: `"0.5 kg"` → 0.5 - [ ] Wissenschaftliche Notation: `"1e3 g"` → wirft / qty=null ### Parser fixen - [ ] Unicode-Brüche-Map - [ ] Locale-Komma-Handling (sicher: "1,5" wenn nur 1 Komma + Ziffern drumrum) - [ ] Bounds: 0 < qty <= 10000 (Zod refinement oder Pre-Check) - [ ] Tests grün, Commit ## Wave 7 — Verifikation - [ ] `npm test` — 158+ Tests grün - [ ] `npm run check` — 0 Errors - [ ] `npm run build` — erfolgreich - [ ] Optional: Docker-Smoke `docker compose -f docker-compose.prod.yml up --build` - [ ] Push aller Commits ## Wave 8 — Re-Review + OPEN-ISSUES-NEXT.md - [ ] Parallele Explore-Agenten: dead-code, redundancy, structure, docs-vs-code - [ ] Befunde in `docs/superpowers/review/OPEN-ISSUES-NEXT.md` - [ ] Bewusst verschobene Items mit Begründung - [ ] Neue Findings (falls vorhanden) - [ ] Commit + Push --- ## Erfolgs-Kriterien 1. Tests grün (158+) 2. svelte-check: 0 Errors, 0 Warnings (oder ≤ Baseline) 3. Build erfolgreich 4. Alle 8 Quick-Wins + Refactor A + Refactor D umgesetzt 5. OPEN-ISSUES-NEXT.md vorhanden mit klarer Trennung "verschoben (warum)" vs "neu entdeckt" 6. Branch ready zum Mergen / PR