# Backlog Prioriterade förbättringar och kända luckor. Top-down ungefär i prioritetsordning. ## Bäställningsdisclaimer - det är bäställarens ansvar att veta hur mycket dom får lov i sin by. 60 liter per 40 deltagare. 2012 (4,8liter) PC5(12,2 liter) PC10 (23,8 liter) ## P0 — innan skarp lansering - [ ] **Rate-limit på `POST /api/bookings` och `POST /api/customer/magic-link`**: enkel IP-baserad throttle (t.ex. 5 bokningar/timme/IP) för att stoppa spam/bots. Magic-link-endpointen är extra känslig — utan throttling kan någon trigga obegränsat med mejl. Implementera i respektive route eller via en middleware-wrapper. - [ ] **Honeypot eller hCaptcha på formuläret**: bokningsformuläret är publikt utan skydd. Honeypot är minimalistiskt och räcker ofta. - [ ] **Generera riktigt `AUTH_SECRET`**: dokumenterat i README men måste göras manuellt vid deploy. - [ ] **Verifiera Mailjet-avsändare**: `MAIL_FROM_EMAIL` måste vara verifierad i Mailjet-kontot innan mejl kommer fram. - [ ] **Skarpa produktpriser och upphämtningstider**: ändra i `prisma/seed.ts` eller via Prisma Studio innan lansering. - [ ] **Cookie-banner / GDPR-info**: bokningen samlar PII (namn, e-post, org.nummer, adress). Kort policy-text + länk. - [ ] **Backup-rutin för SQLite-volymen**: cron-jobb på värden som kör `cp` mot en separat disk eller S3. ## P1 — höjer kvaliteten - [ ] **Admin-UI för produkter och upphämtningstider**: idag måste man köra seed-filen eller Prisma Studio. Lägg till `/admin/products` och `/admin/pickup-slots` med CRUD. - [ ] **Admin-UI för att skapa fler administratörer**: tabellen `Admin` stöder flera men det finns ingen invite-flow. Antingen self-serve invite via mejl-länk eller manuell skapa-form i admin-panelen. - [ ] **Kund-avbokning via token-länk**: lägg till `cancelToken` på `Booking`, inkludera unik avbokningslänk i bekräftelsemejlet. Trigger på `GET /booking/cancel/{token}` med bekräftelsesida. - [ ] **Lagerbegränsning per produkt**: idag finns kapacitet bara på upphämtnings-slots. Lägg `totalStock` på `Product` och kontrollera i POST-routen att `Σ confirmed quantity ≤ stock`. - [ ] **Mailjet Templates (Template-ID) istället för inline HTML**: gör det möjligt att ändra mejldesign utan redeploy. Inline HTML kvar som fallback om template-id saknas. - [ ] **Resend-bekräftelse loggar**: idag skickar admin-knappen "Resend confirmation" tyst — visa toast/success vid lyckad sändning. - [ ] **Statusmejl vid byte SCHEDULED/DELIVERED**: kund får idag bara bekräftelse på att begäran är mottagen — borde få mejl när admin schemalägger eller markerar levererat. - [ ] **Cleanup-jobb för expired customer-tokens**: `CustomerMagicLink` och `CustomerSession` rensas inte automatiskt. Lägg till en cron eller städa i `getCustomerEmail`/`consumeMagicLink`. - [ ] **Bookings-vy: paginering**: nuvarande tar `take: 200`. Lägg cursor-paginering vid skarp volym. - [ ] **PDF-faktureringsunderlag per bokning**: utöver CSV — en PDF som matchar fakturamall, lättare att bifoga. - [ ] **Audit log för admin-actions**: tabell `AuditEvent` med vem som ändrade status, körde resend, etc. - [ ] **Healthcheck-endpoint**: `GET /api/health` returnerar 200 + `{db: 'ok'}` för proxy/uptime-monitor. ## P2 — bra att ha - [ ] **Prisma migrate istället för db push**: när schemat är stabilt, kör `prisma migrate dev` initialt och commita migrations-mappen. Byt entrypoint till `migrate deploy`. - [ ] **Multi-event-stöd**: idag är allt knutet till ett event via `NEXT_PUBLIC_EVENT_NAME`. Lägg till `Event`-tabell med egen produkt- och slot-koppling om systemet ska användas till fler läger. - [ ] **E-mail verification innan bokning**: skicka kod eller bekräfta via dubbelt opt-in. Idag litar vi på att kunden anger korrekt mejl. - [ ] **Slot-omval via avbokningslänk**: kunden kan byta upphämtningstid utan att kontakta admin. - [ ] **Skicka påminnelse-mejl** dagen innan upphämtning (cron + Mailjet). - [ ] **Status-mejl vid statusbyte**: kunden får mejl när bokningen markeras `INVOICED` eller `CANCELLED`. - [ ] **Inbjudnings-mejl till nya admins** (kopplat till P1 admin-UI för admins). - [ ] **Tester**: minst en smoke-test för `POST /api/bookings` (Playwright eller Vitest + Supertest). - [ ] **CI**: GitHub Actions som kör `npm run build` på PR. - [ ] **Telemetri / felrapportering**: Sentry eller liknande. ## P3 — framtida överväganden - [ ] **Postgres istället för SQLite**: när volymen växer eller om vi vill ha managed backups. Prisma byter provider med en rad + ny `DATABASE_URL`. - [ ] **Prisma 7-uppgradering**: ny `prisma.config.ts` med driver adapter (t.ex. `@prisma/adapter-better-sqlite3`), uppdaterad `PrismaClient`-init. Inte värt det förrän Prisma 7 är stabilare och vi har annat skäl att uppgradera. - [ ] **Server-side e-postvalidering**: t.ex. DNS/MX-koll eller integration mot Mailjet Address Validation. - [ ] **Bilder på produkterna i formuläret**: laddas från egen `/public/products/*.webp` eller via en CDN. - [ ] **Skip-link och bättre a11y-audit**: fokushantering i stegen, ARIA-live för felmeddelanden. - [ ] **Webhooks från Mailjet** (bounce/spam-rapport) — markerar bokningar med ogiltig e-post. ## Beslutslogg - **2026-05-22**: `ReplacementRequest` snapshottar pris från `Product` (samma som ny flaska) vid request-tid — fält `sku/nameSv/nameEn/unitPriceOre/vatBp/lineTotalOre`. CSV-export utökad med `LineType=Booking|Replacement`-kolumn; CANCELLED-byten exkluderas, `BillableQuantity` = quantity om `status=DELIVERED` annars 0. En faktura per org = original-rader + levererade byten. - **2026-05-22**: Kund-portal (`/min-sida`) + flaskbyte tillagt som del av MVP. Magic-link på begäran (kund matar in mejl, får länk via mejl). Token-scope = alla bokningar för mejlen. `ReplacementRequest`-modell kopplad till `BookingItem` + valbar `PickupSlot`. Inga antalsgränser — admin avgör per ärende. - **2026-05-22**: Valt SQLite + Prisma 5 (inte 7) för MVP. SQLite-fil i Docker-volym räcker för ett event. Prisma 5 fungerar utan `prisma.config.ts`. - **2026-05-22**: `prisma db push` istället för `migrate deploy` i entrypoint — färre artefakter att hålla reda på i MVP. Byt vid stabilt schema. - **2026-05-22**: Priser i öre (`Int`) snarare än `Decimal` — enklare och säkrare för en valuta (SEK). - **2026-05-22**: Egen inline HTML-mall i `src/lib/mailjet.ts` istället för Mailjet Templates — färre externa beroenden för MVP, men ändras inte utan deploy. - **2026-05-22**: NextAuth Credentials + lokal Admin-tabell (inte magic link) — användaren valde detta för flera admins. - **2026-05-22**: next-intl med `localePrefix: "as-needed"` — `/` är svenska, `/en/*` engelska. Switch i header behåller path.