diff --git a/docs/sprints/backlog.md b/docs/sprints/backlog.md index 48afb12f..d876a029 100644 --- a/docs/sprints/backlog.md +++ b/docs/sprints/backlog.md @@ -3,7 +3,7 @@ title: "Produktbacklog" description: "Alla kända stories och uppgifter, speglar roadmap.md. Plockas in i sprintar vid behov." category: sprint status: active -last_updated: 2026-05-13 +last_updated: 2026-05-14 tags: [backlog, roadmap, planning] sections: - Blockerare @@ -54,7 +54,7 @@ sections: | withApiHandler resterande routes (131 st) | Löpande | Opportunistiskt | | console.* i legacy docs | 0.5 dag | Låg prioritet | | **BDD integrationstester — horses, booking-series, bookings POST, group-bookings join** | 1 dag | Kärndomäner saknar integration: Horses (8 routes, noll integration), Booking-series (3 routes, precis releasad), `POST /api/bookings` (viktigaste CREATE-routen), `POST /api/group-bookings/join` (Serializable-transaktion). 18/181 routes har integration totalt. Audit: [bdd-coverage-audit-2026-04-25.md](../research/bdd-coverage-audit-2026-04-25.md). | -| **Pre-existing fail i `booking-series/route.test.ts` (8 tester)** | 2-4h | 8 av 17 tester i `src/app/api/booking-series/route.test.ts` failar på både `main` och `staging`. Verifierat 2026-05-08 under S67-0-arbete: failet är oberoende av S67-0 men blockerar pre-push-hooken för alla feature-branches (måste pushas med `--no-verify`). Felet är inte regression från en specifik PR utan har funnits en längre tid (sannolikt sedan recurring_bookings-arbetet). **Åtgärd:** isolera och fixa testerna, eller uppdatera dem till matchande nuvarande kodbeteende. **Effekt vid fix:** pre-push-hooken kan användas utan override för alla framtida pushes, mindre risk att andra fail döljs av `--no-verify`. Hittad: 2026-05-08 (S67-0). | +| ~~**Pre-existing fail i `booking-series/route.test.ts` (8 tester)**~~ FIXAD 2026-05-14 | ~~2-4h~~ 10 min | **Root cause: time-bomb-test.** Test-fixture hade hårdkodat `firstBookingDate: "2026-05-01"` (commit `f9b47c43d`, 2026-02-17). När dagens datum passerade 2026-05-01 började route:s `firstBookingDate.refine(val => new Date(val) >= today)` returnera 400 istället för 201. Production-koden är korrekt — testet var fel. Fixad med dynamiskt datum (`Date.now() + 30 dagar`). Pre-push-hook kan nu användas utan `--no-verify`. Backlog-uppskattning på 2-4h var ~24x överskattad eftersom rotorsaken inte hade analyserats. Se follow-up "Audit hårdkodade framtida datum i tester" nedan. | | **Hårdkodad fel domän i `data-retention-warning.ts`** | 10 min | `src/lib/email/templates/data-retention-warning.ts:4` har fallback `https://equinet.vercel.app` (utan `-app`) — fungerar inte. Bör använda samma logik som övriga email-templates: `process.env.APP_URL \|\| 'http://localhost:3000'`. Hittad 2026-04-30 vid felsökning av password reset till localhost. | | **CI-guard: kräv APP_URL i prod-build** | 1-2h | `APP_URL` saknades i Vercel prod-env i månader → alla email-länkar pekade på `http://localhost:3000` (password reset, bokningsbekräftelser, route-announcements m.fl.). Lägg till build-time-validering som faller om kritiska env-variabler saknas i prod (APP_URL, DATABASE_URL, NEXT_PUBLIC_SUPABASE_URL, RESEND_API_KEY, STRIPE_SECRET_KEY). Förslag: `scripts/check-prod-env.ts` körs i `prebuild` när `VERCEL_ENV=production`. | | **Fixa fire-and-forget i AuthService och övriga notifiers (HÖG PRIO)** | 1-2h | `AuthService.requestPasswordReset` (rad 396-401) skickar `emailService.sendPasswordReset(...).catch(() => {})` och returnerar response omedelbart. I Vercel/Fluid Compute kan function-instansen termineras innan fetch-anropet mot Resend slutförs → mail skickas aldrig. **Bevis 2026-04-30**: Tre password reset-försök, mail #1 vann racen mot termination, mail #2 och #3 hann ALDRIG fram till Resend (token i DB, inget i Resend dashboard). Tyst leveransbortfall i prod. **Påverkan**: Kan drabba alla fire-and-forget i kodbasen — `RouteAnnouncementNotifier` och fler. **Fix**: ersätt `.catch(() => {})` med `await waitUntil(...)` från `@vercel/functions`, eller blockerande `await`. Audit alla fire-and-forget i kodbasen (`grep -rn "\.catch(() => {})" src/`). | @@ -63,6 +63,7 @@ sections: | **URL-konfigurationsmatris** | 30 min | Skapa `docs/operations/url-configuration.md` som listar alla URL-config-platser och vad varje styr: Vercel `APP_URL`, Supabase Site URL + Redirect URLs, Stripe webhook endpoint, Resend domän-verifiering, ev. iOS prod-URL i `AppConfig.swift`. Vi har precis brunnit oss på trippel-miss (APP_URL + Site URL + Redirect URLs alla satta fel) — dokumentationen ska göra det tydligt vad som måste uppdateras vid byte av domän. Inkluderar checklista och länkar till dashboard-vägar. | | **Städa Vercel env-variabler med literal `\\n` på slutet** | 15 min | `NEXT_PUBLIC_SUPABASE_URL` och `NEXT_PUBLIC_SUPABASE_ANON_KEY` i Vercel prod har literal backslash-n (`\\n`) på slutet av värdena. Next.js runtime kan strippa det, men `vercel env pull` skriver det som literal i .env-filen vilket bryter direktanrop mot Supabase API från lokala scripts. Hittad 2026-04-30. Fix: Vercel UI → respektive variabel → ta bort `\\n`-suffixet → spara → redeploy. | | **Help-data drift protection** | 15-30 min | CI-validation som regenererar `articles-data.ts` och diffar mot committed version — failar PR om out-of-sync. Plus README-rad om `npm run generate:help`-workflow. Bevisat behov efter PR #333 (2026-05-13): staging hade tom hjälpsektion eftersom build-time-generator + `.vercelignore` (`*.md`) filtrerade bort markdown-källor. Detaljerad story med A/B/C/D-alternativ: [help-data-drift-protection.md](../stories/help-data-drift-protection.md). | +| **Audit hårdkodade framtida datum i tester (time-bomb-audit)** | 30 min – 1h | Pre-existing booking-series-fail (fixad 2026-05-14) hade rotorsak i hårdkodat `firstBookingDate: "2026-05-01"` som tickade ner till "förflutet" och bröt 8 tester samtidigt. Risk: fler test-fixtures i `src/**/*.test.ts` och `e2e/**` kan ha samma time-bomb. **Åtgärd:** (1) `grep -rE '"20[2-3][0-9]-[0-1][0-9]-[0-3][0-9]"' src/**/*.test.ts e2e/**` för att hitta alla hårdkodade datum-strängar i tester, (2) byt till dynamiska datum där schemat har relativ validering (`>= today`, `< now + N`), (3) överväg ESLint-regel eller pre-commit-check som varnar för hårdkodade datum-strängar i `.test.ts`-filer. **Värde:** förhindrar framtida `--no-verify`-vana som maskerar verkliga regressioner. Hittad 2026-05-14 vid 5 Whys på booking-series-fail. | ## Kodeffektivitet (tech debt) diff --git a/src/app/api/booking-series/route.test.ts b/src/app/api/booking-series/route.test.ts index 45e5ebdf..fc0149f0 100644 --- a/src/app/api/booking-series/route.test.ts +++ b/src/app/api/booking-series/route.test.ts @@ -110,10 +110,16 @@ function makeRequest(body: object): NextRequest { }) } +// Use a dynamic future date (30 days ahead) so the test does not +// time-bomb when the hard-coded date drifts into the past. The route +// schema's `firstBookingDate.refine(val => new Date(val) >= today)` +// is correct production behavior — the test must move forward with us. const validBody = { providerId: "a0000000-0000-4000-a000-000000000001", serviceId: "a0000000-0000-4000-a000-000000000003", - firstBookingDate: "2026-05-01", + firstBookingDate: new Date(Date.now() + 30 * 86400000) + .toISOString() + .split("T")[0], startTime: "10:00", intervalWeeks: 2, totalOccurrences: 4,