# Scrum4Me — Implementatie Backlog **Versie:** 0.1 — april 2026 **Volgt op:** Functionele Specificatie v0.2, Architectuur v0.1 --- ## MVP-definitie De MVP is klaar wanneer Lars — de primaire persona — de volledige cyclus kan doorlopen: een product aanmaken, een Product Backlog opbouwen met PBI's en stories, een Sprint plannen, taken aanmaken, en Claude Code de volgende story laten ophalen, implementeren en vastleggen — allemaal zonder hulp of handleiding. De app draait stabiel op Vercel en is volledig lokaal opzetbaar via één README. --- ## Milestone-overzicht | Milestone | Doel | Tasks | |---|---|---| | M0: Foundation | Project, database, auth, navigatieshell | ST-001 – ST-008 | | M1: Producten & Product Backlog | Producten, PBI's, gesplitst scherm | ST-101 – ST-110 | | M2: Stories & Drag-and-drop | Stories als blokken, dnd-kit, Zustand | ST-201 – ST-210 | | M3: Sprint Backlog & Sprint Planning | Sprint aanmaken, stories slepen, taken | ST-301 – ST-312 | | M4: Claude Code REST API | Alle endpoints, tokenbeheer | ST-401 – ST-410 | | M5: Todo-lijst | Todo CRUD, promotie naar PBI/story | ST-501 – ST-506 | | M6: Polish & Launch-ready | Foutafhandeling, toegankelijkheid, CI/CD, beveiliging | ST-601 – ST-612 | --- ## Backlog ### M0: Foundation - [ ] **ST-001** Project scaffolding - `create-next-app` met TypeScript strict, Tailwind CSS, App Router; installeer shadcn/ui, Zustand, dnd-kit, iron-session, bcrypt, Zod; configureer path aliases (`@/`) - Done when: `npm run dev` start zonder fouten; `npm run lint` geeft geen errors; shadcn `Button` rendert op een testpagina - [ ] **ST-002** Prisma v7 setup + `prisma.config.ts` - Installeer Prisma v7 + `@prisma/adapter-pg`; schrijf `prisma.config.ts` met `DATABASE_URL` via Zod-gevalideerde env; schrijf `lib/prisma.ts` singleton - Done when: `npx prisma db push` slaagt; Prisma Client importeerbaar in een testbestand zonder fouten - [ ] **ST-003** Database schema migratie (volledige initiële migratie) - Schrijf het volledige `schema.prisma` op basis van het architectuurdocument: `User`, `UserRole`, `ApiToken`, `Product`, `Pbi`, `Story`, `StoryLog`, `Sprint`, `Task`, `Todo`; alle enums, indexes, cascade deletes - Done when: `npx prisma migrate dev --name init` slaagt; alle tabellen zichtbaar in DB-client; `npx prisma validate` geeft geen fouten - [ ] **ST-004** Seed met testdata - Schrijf `prisma/seed.ts` op basis van het Product Backlog document (devplanner-product-backlog.md); seed één gebruiker, één product (Scrum4Me zelf), alle PBI's en stories als testdata; voeg demo-gebruiker toe - Done when: `npx prisma db seed` slaagt; DB bevat alle PBI's en stories uit het backlog-document; demo-gebruiker aanwezig - [ ] **ST-005** Environment variabelen + `lib/env.ts` - Schrijf Zod-schema voor alle env vars (`DATABASE_URL`, `DIRECT_URL`, `SESSION_SECRET`, `NODE_ENV`); exporteer gevalideerd `env` object; schrijf `.env.example` met instructies - Done when: app gooit een begrijpelijke fout bij ontbrekende env var; `.env.example` volledig gedocumenteerd - [ ] **ST-006** Authenticatie — registratie en inloggen - Schrijf `lib/auth.ts` (registreer met bcrypt hash, verifieer bij inloggen); schrijf `lib/session.ts` (iron-session config); implementeer `/register` en `/login` pagina's met Server Actions; sla `{ userId, isDemo }` op in sessiecookie - Done when: registreren → ingelogde sessie → redirect `/dashboard`; inloggen met verkeerde credentials geeft generieke foutmelding; sessie blijft actief na paginaverversing - [ ] **ST-007** Route-beveiliging via `middleware.ts` - Schrijf `middleware.ts` die iron-session cookie uitleest; redirect naar `/login` bij alle `/dashboard`, `/products/*`, `/todos`, `/settings/*` routes zonder geldige sessie; authenticated users worden van `/login` en `/register` doorgestuurd naar `/dashboard` - Done when: directe navigatie naar `/dashboard` zonder sessie redirect naar `/login`; ingelogde gebruiker op `/login` redirect naar `/dashboard` - [ ] **ST-008** Navigatieshell + dashboard-layout - Schrijf `app/(app)/layout.tsx` met navigatiebalk (logo, productenlink, todolink, instellingen, uitlogknop); implementeer uitlog Server Action; implementeer `/dashboard` als lege productenlijstpagina met "Maak je eerste product aan" lege staat; zet demo-badge zichtbaar als `isDemo === true` - Done when: volledige auth-flow (register → login → dashboard → logout → login) werkt end-to-end; demo-gebruiker ziet badge in navigatie --- ### M1: Producten & Product Backlog - [ ] **ST-101** Product aanmaken - `/products/new` pagina met formulier (naam, beschrijving, repo URL, definition of done); `createProduct` Server Action met Zod-validatie; uniekheidscontrole op naam per gebruiker; redirect naar `/products/[id]` na aanmaken - Done when: product aangemaakt en zichtbaar op dashboard; dubbele naam geeft inline validatiefout; lege naam blokkeert submit - [ ] **ST-102** Productenlijst op dashboard - Haal actieve producten op via Prisma Server Component; toon naam, beschrijving (ingekort 80 tekens), repo-link; lege staat met CTA; klikken opent Product Backlog - Done when: twee producten zichtbaar na aanmaken; gearchiveerd product niet zichtbaar in standaardlijst - [ ] **ST-103** Product bewerken en archiveren - Bewerkformulier (naam, beschrijving, repo URL, DoD) via Server Action; archiveerknop met bevestigingsdialoog; hersteloptie voor gearchiveerde producten; "toon gearchiveerd"-filter op dashboard - Done when: naam bijwerken persisteert; archiveren verbergt product; herstel maakt het weer zichtbaar - [ ] **ST-104** Gesplitst scherm layout component (`SplitPane`) - Bouw herbruikbaar `` Client Component met versleepbare horizontale splitter; sla splitter-positie op in `localStorage` per sleutel; standaard 40/60 verhouding; minimale panelbreedte 200px; responsive fallback naar tabs op < 1024px - Done when: splitter versleepbaar en positie behouden na paginaverversing; tabs getoond op smal scherm - [ ] **ST-105** Navigatiebar-component per paneel - Bouw herbruikbaar `` component met slots voor knoppen (aanmaken, filter, verwijderen); consistent design voor linker- en rechterpaneel - Done when: navigatiebar herbruikt in minimaal twee gesplitste schermen zonder duplicatie - [ ] **ST-106** PBI aanmaken en weergeven - Linkerpaneel van `/products/[id]`: haal PBI's op gegroepeerd op prioriteit en sort_order; "PBI aanmaken" knop opent inline formulier (titel, prioriteit); `createPbi` Server Action; nieuw PBI verschijnt onderaan de juiste prioriteitsgroep - Done when: PBI aangemaakt en zichtbaar in juiste prioriteitsgroep; lege staat toont prompt - [ ] **ST-107** PBI prioriteitsgroepen met visuele scheiding - Render PBI's gegroepeerd per prioriteit (1–4) met gelabelde scheidingslijn per groep (bijv. "Kritiek", "Hoog"); lege groepen zijn niet zichtbaar; prioriteitsbadge per PBI - Done when: vier prioriteitsgroepen correct gerenderd met labels; PBI met prioriteit 1 staat boven prioriteit 4 - [ ] **ST-108** PBI bewerken en verwijderen - Inline bewerkingsmodus via dubbelklik of contextmenu (titel, omschrijving, prioriteit); `updatePbi` Server Action; verwijderen met bevestigingsdialoog inclusief waarschuwing cascade; `deletePbi` Server Action - Done when: titelbewering opgeslagen zonder paginaverversing; verwijderen cascade-verwijdert stories (verifieerbaar in DB) - [ ] **ST-109** PBI selecteren → stories laden - Klikken op PBI in linkerpaneel toont bijbehorende stories rechts via `useSelectionStore`; geselecteerd PBI visueel gemarkeerd; lege staat rechts als geen stories - Done when: klikken op PBI A toont stories van A rechts; klikken op PBI B schakelt direct over - [ ] **ST-110** PBI filter - Filterknop in linkerpaneel navigatiebar; dropdown voor prioriteit (1–4, alle); filter werkt realtime op gerenderde lijst; actief filter zichtbaar als badge; wissen via ×-knop - Done when: filter op prioriteit 1 verbergt alle andere PBI's; wissen herstelt volledige lijst --- ### M2: Stories & Drag-and-drop - [ ] **ST-201** `usePlannerStore` Zustand-store - Schrijf `stores/planner-store.ts` met `pbiOrder`, `storyOrder`, `taskOrder`; `init*`, `reorder*`, `rollback*` actions; TypeScript strict types - Done when: store importeerbaar in een Client Component; `initPbis` vult order; `reorderPbis` muteert order; `rollbackPbis` herstelt vorige staat - [ ] **ST-202** `useSelectionStore` Zustand-store - Schrijf `stores/selection-store.ts` met `selectedPbiId`, `selectedStoryId`, setters en `clearSelection` - Done when: selectie in linkerpaneel via store zichtbaar in rechterpaneel zonder prop drilling - [ ] **ST-203** dnd-kit setup + PBI drag-and-drop - Installeer dnd-kit; wrap linkerpaneel in `DndContext` + `SortableContext`; implementeer `useSortable` per PBI-rij; `onDragEnd`: bereken nieuwe `sort_order` via float-gemiddelde; optimistisch updaten via `usePlannerStore`; `reorderPbisAction` Server Action; rollback bij fout - Done when: PBI versleepbaar binnen prioriteitsgroep; volgorde opgeslagen na loslaten; UI rollback bij gesimuleerde server-fout - [ ] **ST-204** PBI drag-and-drop over prioriteitsgrens - Uitbreiding ST-203: slepen over een prioriteitsgrens wijzigt `priority` van het PBI; `sort_order` wordt onderaan de doelgroep geplaatst; `updatePbiPriority` Server Action - Done when: PBI naar prioriteit 2 slepen vanuit prioriteit 3 wijzigt zowel prioriteit als volgorde - [ ] **ST-205** Story aanmaken en weergeven als blokken - Rechterpaneel van Product Backlog: haal stories op voor geselecteerd PBI; render als blokken (~10% schermbreedte, horizontaal); elk blok toont titel (ingekort), prioriteitsbadge, statusbadge; "Story aanmaken" knop; `createStory` Server Action - Done when: drie stories zichtbaar als blokken; nieuw blok verschijnt in juiste prioriteitsgroep - [ ] **ST-206** Story prioriteitsgroepen met visuele scheiding - Groepeer story-blokken per prioriteit; gekleurde band of scheidingslijn per groep; blokken horizontaal gerangschikt per rij; nieuwe rij bij overloop - Done when: stories van vier prioriteiten correct gescheiden weergegeven - [ ] **ST-207** Story drag-and-drop (horizontaal, binnen en tussen groepen) - dnd-kit horizontale `SortableContext` per prioriteitsgroep; `onDragEnd`: herrangschikking via float-gemiddelde in `storyOrder`; slepen naar andere groep wijzigt prioriteit; optimistisch via `usePlannerStore`; `reorderStoriesAction` Server Action; rollback bij fout - Done when: story versleepbaar binnen groep en naar andere groep; volgorde en prioriteit persistent na loslaten - [ ] **ST-208** Story detail-modal / slide-over - Klikken op storyblok opent slide-over of modal met titel, omschrijving, acceptatiecriteria, statusbadge, activiteitenlog (leeg bij nieuwe story); bewerkformulier voor titel/omschrijving/acceptatiecriteria; `updateStory` Server Action - Done when: klikken op blok opent detail; bewerken persisteert; sluiten keert terug naar backlog - [ ] **ST-209** Story verwijderen - Verwijderknop in story-detail of contextmenu; bevestigingsdialoog met waarschuwing cascade (taken); `deleteStory` Server Action; blok verdwijnt optimistisch uit het rechterpaneel - Done when: story verwijderd incl. cascade-taken (verifieerbaar in DB); blok direct verdwenen uit UI - [ ] **ST-210** Story filter in rechterpaneel - Filterknop in rechterpaneel navigatiebar; filter op status (OPEN, IN_SPRINT, DONE) en prioriteit; realtime; actief filter als badge; wissbaar - Done when: filter op OPEN verbergt IN_SPRINT stories --- ### M3: Sprint Backlog & Sprint Planning - [ ] **ST-301** `useSprintStore` Zustand-store - Schrijf `stores/sprint-store.ts`; `initSprint`, `addStoryToSprint`, `removeStoryFromSprint`, `reorderSprintStories`, `rollbackSprint` - Done when: store beheert sprint-story-volgorde onafhankelijk van planner-store - [ ] **ST-302** Sprint aanmaken - "Sprint starten" knop op productpagina (zichtbaar als geen actieve Sprint); modal met Sprint Goal invoerveld; `createSprint` Server Action; max. 1 actieve Sprint per product afgedwongen in service-laag - Done when: Sprint aangemaakt met Goal; tweede sprint aanmaken terwijl eerste actief is geeft foutmelding - [ ] **ST-303** Sprint Backlog scherm — layout - `/products/[id]/sprint` pagina; `SplitPane` met Sprint Backlog links (stories in Sprint op volgorde) en rechts de Product Backlog stories gegroepeerd per PBI (inklapbaar); Sprint Goal zichtbaar bovenaan; lege staat links met instructie - Done when: pagina rendert correct; Sprint Goal zichtbaar; beide panelen tonen juiste data - [ ] **ST-304** Story vanuit Product Backlog naar Sprint slepen - dnd-kit drag vanuit rechterpaneel naar linkerpaneel; `onDragEnd`: `addStoryToSprint` in store; story krijgt badge "In Sprint" in Product Backlog; `addStoryToSprintAction` Server Action (zet `sprint_id` + status `IN_SPRINT`); rollback bij fout - Done when: story gesleept naar Sprint verschijnt links en toont "In Sprint" badge rechts; persistent na herlaad - [ ] **ST-305** Sprint Backlog story volgorde aanpassen - dnd-kit verticale `SortableContext` in linkerpaneel; herrangschikking via float-gemiddelde in `useSprintStore`; `reorderSprintStoriesAction` Server Action - Done when: volgorde in Sprint Backlog persistent na loslaten en na paginaverversing - [ ] **ST-306** Story uit Sprint verwijderen - Verwijderknop per story in Sprint Backlog; `removeStoryFromSprintAction` Server Action (wist `sprint_id`, zet status terug op `OPEN`); story verdwijnt links en badge verdwijnt rechts - Done when: verwijderen persistent; story beschikbaar in Product Backlog rechterpaneel - [ ] **ST-307** Sprint Planning scherm — layout - `/products/[id]/sprint/planning` pagina; `SplitPane` met Sprint Backlog stories links (op volgorde) en taken van geselecteerde story rechts; Sprint Goal zichtbaar; lege staat rechts als geen story geselecteerd - Done when: pagina rendert; story selecteren links toont taken rechts - [ ] **ST-308** Taak aanmaken - "Taak aanmaken" knop in rechterpaneel navigatiebar; inline formulier (titel, omschrijving, prioriteit); `createTask` Server Action; voortgangsindicator per story (bijv. "0/0 Done") - Done when: taak aangemaakt en zichtbaar in takenlijst; voortgangsindicator toont "0/1 Done" - [ ] **ST-309** Taak drag-and-drop (verticaal) - dnd-kit verticale `SortableContext` in rechterpaneel; herrangschikking via float-gemiddelde in `usePlannerStore.taskOrder`; `reorderTasksAction` Server Action - Done when: taken versleepbaar; volgorde persistent na loslaten - [ ] **ST-310** Taakstatus bijhouden - Status-toggle per taak (TO_DO → IN_PROGRESS → DONE) via klikbare badge of dropdown; `updateTaskStatus` Server Action; voortgangsindicator op story updatet optimistisch - Done when: taak op DONE zetten verhoogt teller in voortgangsindicator; persistent na herlaad - [ ] **ST-311** Taak bewerken en verwijderen - Inline bewerken van titel, omschrijving en prioriteit; `updateTask` Server Action; verwijderen met bevestiging; `deleteTask` Server Action - Done when: titelwijziging persisteert; verwijderde taak verdwijnt uit lijst - [ ] **ST-312** Sprint afronden - "Sprint afronden" knop op Sprint-pagina; dialoog toont per story de status en vraagt: "Markeer als Done of terug naar Backlog?"; `completeSprint` Server Action zet Sprint op COMPLETED, verwerkt keuzes per story - Done when: Sprint afgerond; stories correct verplaatst naar DONE of OPEN; nieuwe Sprint aanmaakbaar --- ### M4: Claude Code REST API - [ ] **ST-401** API-token infrastructuur - Schrijf `lib/api-auth.ts`: parseer `Authorization: Bearer` header; bereken SHA-256 hash; zoek op in `api_tokens`; controleer `revoked_at`; retourneer `userId` of 401; retourneer 403 als `is_demo` - Done when: geldige token geeft userId terug; ongeldige token geeft 401; ingetrokken token geeft 401; demo-token op schrijf-endpoint geeft 403 - [ ] **ST-402** API-tokenbeheer UI - `/settings/tokens` pagina; token aanmaken (label optioneel); token eenmalig getoond in kopieerbaar veld na aanmaken; tokenoverzicht (label, datum, actief/ingetrokken); intrekken via Server Action; max. 10 actieve tokens - Done when: token aangemaakt en waarde zichtbaar; na sluiten dialoog niet meer te zien; intrekken maakt token onbruikbaar (getest via curl) - [ ] **ST-403** `GET /api/products` — productenlijst - Route Handler; authenticatie via `api-auth.ts`; retourneer actieve producten `[{ id, name, repo_url }]` als JSON - Done when: `curl -H "Authorization: Bearer " /api/products` retourneert correct JSON; 401 zonder token - [ ] **ST-404** `GET /api/products/:id/next-story` — volgende story ophalen - Route Handler; haal hoogst geprioriteerde OPEN story op van actieve Sprint van het product (priority ASC, sort_order ASC); retourneer `{ id, title, description, acceptance_criteria, tasks[] }`; 404 als geen open stories - Done when: endpoint retourneert eerste story van Sprint; 404 als Sprint leeg; 404 als geen actieve Sprint - [ ] **ST-405** `GET /api/sprints/:id/tasks` — taken ophalen - Route Handler met `?limit=N` query param (default 10, max 50); retourneer taken van actieve Sprint op `(story.sort_order, task.priority, task.sort_order)` volgorde; retourneer `{ id, title, story_id, priority, sort_order, status }` - Done when: endpoint retourneert max N taken in juiste volgorde; `?limit=5` retourneert max 5 - [ ] **ST-406** `PATCH /api/stories/:id/tasks/reorder` — taakvolgorde aanpassen - Route Handler; body: `{ task_ids: string[] }`; valideer alle IDs behoren tot de story; update `sort_order` via float-verdeling; retourneer `{ success: true }` - Done when: volgorde in DB veranderd na PATCH; gewijzigde volgorde zichtbaar in Sprint Planning UI na herlaad; ongeldige task_id geeft 400 - [ ] **ST-407** `POST /api/stories/:id/log` — activiteit vastleggen - Route Handler; body: `{ type, content, status?, commit_hash?, commit_message? }`; Zod-validatie per type; schrijf naar `story_logs`; retourneer `{ id, created_at }` - Done when: drie typen werken (IMPLEMENTATION_PLAN, TEST_RESULT, COMMIT); log-entry zichtbaar in story-detail UI na aanmaken via API; ontbrekend verplicht veld geeft 400 - [ ] **ST-408** `PATCH /api/tasks/:id` — taakstatus en implementatieplan bijwerken - Route Handler; body: `{ status?: "TO_DO" | "IN_PROGRESS" | "DONE", implementation_plan?: string }`; minimaal één veld verplicht; valideer dat taak aan requester's product behoort; retourneer `{ id, status, implementation_plan }` - Done when: status update via API zichtbaar in Sprint Planning UI; implementation_plan opgeslagen en opvraagbaar; lege body geeft 400; andere gebruikers taak geeft 403 - [ ] **ST-409** `POST /api/todos` — todo aanmaken - Route Handler; body: `{ title: string, product_id: string }`; valideer dat product bij de geverifieerde gebruiker hoort; schrijf naar `todos`; retourneer `{ id, title, created_at }` - Done when: todo aangemaakt via API met product_id verschijnt in todo-lijst UI gekoppeld aan het juiste product; lege titel of ontbrekend product_id geeft 400; onbekend product geeft 404 - [ ] **ST-410** Story-activiteitenlog UI - Activiteitenlog sectie in story-detail slide-over; haal `story_logs` op via Server Component; render chronologisch; visuele stijl per type (IMPLEMENTATION_PLAN = blauw, TEST_RESULT passed = groen, failed = rood, COMMIT = paars); commit-hash klikbaar als `repo_url` ingesteld; lege staat - Done when: drie log-entries (plan, test, commit) correct gestyled; commit-hash link opent in nieuw tabblad --- ### M5: Todo-lijst - [ ] **ST-501** Todo-lijst pagina - `/todos` pagina; haal actieve (niet-gearchiveerde) todos op inclusief productnaam; snel-invoerveld bovenaan met product-dropdown (verplicht) en titel (Enter om op te slaan); `createTodo` Server Action; lege staat met instructie; productnaam-badge per todo-item - Done when: todo aanmaken via Enter persisteert en verschijnt in lijst met productnaam; aanmaken zonder product geblokkeerd; lege staat zichtbaar bij geen todos - [ ] **ST-502** Todo afvinken - Checkbox per todo; `toggleTodo` Server Action; afgevinkte todos visueel doorgestreept; afgevinkte todos blijven zichtbaar onderaan de lijst - Done when: afvinken persistent na herlaad; visuele doorstreping correct - [ ] **ST-503** Afgevinkte todos archiveren - "Archiveer afgeronde items" knop; `archiveCompletedTodos` Server Action; gearchiveerde todos verdwijnen uit standaardweergave - Done when: archiveren verbergt alle afgevinkte todos; telling correct - [ ] **ST-504** Todo promoveren naar PBI - "Promoveer naar PBI" contextmenu of knop per todo; dialoog: product dropdown (actieve producten), prioriteit dropdown; titel vooringevuld (bewerkbaar); bevestigingswaarschuwing; `promoteTodeToPbi` Server Action (maak PBI aan, verwijder todo) - Done when: gepromoveerde todo verdwijnt; PBI zichtbaar in juist product met juiste prioriteit - [ ] **ST-505** Todo promoveren naar story - "Promoveer naar story" knop per todo; dialoog: product dropdown → PBI dropdown (gefilterd op product), prioriteit; titel vooringevuld; `promoteTodoToStory` Server Action (maak story aan, verwijder todo) - Done when: gepromoveerde todo verdwijnt; story zichtbaar in juist PBI met juiste prioriteit - [ ] **ST-506** Rolbeheer in instellingen - `/settings` pagina met roltoewijzing (checkbox per rol: Product Owner, Scrum Master, Developer); minimaal één rol verplicht; `updateRoles` Server Action; geselecteerde rollen zichtbaar in profielbalk - Done when: rollen bijwerken persisterend; profielbalk toont gekozen rollen; uitvinken van alle rollen geeft validatiefout --- ### M6: Polish & Launch-ready - [ ] **ST-601** Loading states en skeletons - `loading.tsx` voor alle zware routes (`/products/[id]`, `/sprint`, `/sprint/planning`); skeletoncomponenten voor PBI-lijst, story-blokken en takenlijst; pending states op alle form-submit-knoppen via `useFormStatus` - Done when: navigeren naar een trage route toont skeleton; submit-knoppen disablen tijdens Server Action - [ ] **ST-602** Error boundaries - `error.tsx` voor alle beschermde routes; toon gebruiksvriendelijke foutmelding met "Probeer opnieuw" knop; log fout naar console (Sentry in M6) - Done when: gesimuleerde Server Action-fout toont error boundary zonder witte pagina - [ ] **ST-603** Toast-notificaties (Sonner) - Installeer Sonner; success-toast na aanmaken/bewerken/verwijderen van producten, PBI's, stories, taken, todos; error-toast bij mislukte Server Actions; toast niet bij drag-and-drop (te frequent) - Done when: aanmaken van PBI toont success-toast; gesimuleerde netwerk-fout toont error-toast - [ ] **ST-604** Demo-gebruiker write-protection in UI - Alle aanmaak-, bewerk- en verwijderknoppen disabled + tooltip "Niet beschikbaar in demo-modus" voor demo-sessies; gebaseerd op `isDemo` in sessie - Done when: demo-gebruiker ziet alle knoppen maar kan niets wijzigen; tooltip zichtbaar bij hover - [ ] **ST-605** Keyboard-navigatie - Tab-volgorde logisch in alle formulieren; Enter submits formulieren; Escape sluit modals/slide-overs; dnd-kit keyboard-drag (Space om te pakken, pijltjestoetsen, Space om te laten vallen) - Done when: volledige PBI aanmaken-flow keyboard-only uitvoerbaar; dnd-kit drag via keyboard werkt - [ ] **ST-606** Desktop-first UI-review - Test alle flows op 1280px, 1440px en 1920px breedte; fix overflow, uitlijning en proportie-issues; controleer minimum schermbreedte 1024px (toon melding bij smaller) - Done when: alle M0–M5 flows correct op drie schermbreedtes; melding bij < 1024px - [ ] **ST-607** Toegankelijkheid (WCAG AA) - Kleurcontrast-check op alle tekst en badges; aria-labels op icon-only knoppen; focus-ring zichtbaar op alle interactieve elementen; `role` en `aria-selected` op geselecteerde PBI in linkerpaneel - Done when: geen WCAG AA contrastfouten op primaire flows; alle knoppen hebben toegankelijke labels - [ ] **ST-608** Ratelimiting op auth-endpoints - Max. 10 inlogpogingen per IP per minuut; max. 5 registraties per IP per uur; implementeer via in-memory counter (v1) of Vercel Edge middleware - Done when: 11 snelle inlogpogingen leiden tot 429-respons met duidelijke melding - [ ] **ST-609** Beveiligingsreview API-endpoints - Controleer alle Route Handlers: elke schrijfoperatie valideert dat de resource bij de geverifieerde gebruiker hoort; cross-user reads zijn onmogelijk; voeg integratietests toe die cross-user toegang testen - Done when: poging om andere gebruikers's product op te halen via API geeft 403; getest met twee test-gebruikers - [ ] **ST-610** CI/CD via GitHub Actions - Workflow: `lint` (ESLint), `typecheck` (tsc --noEmit), `prisma validate`, `build` (next build) op elke PR en push naar main; Vercel auto-deploy op main - Done when: een TypeScript-fout in een PR blokkeert merge; succesvolle merge triggert Vercel-deploy - [ ] **ST-611** README en lokale setup-documentatie - Schrijf `README.md` met: wat is Scrum4Me, quickstart lokaal (clone → env → prisma push → seed → dev), cloud deployment (Vercel + Neon stappenplan), API-documentatie (alle 7 endpoints met voorbeelden), Claude Code-integratie uitleg - Done when: iemand zonder context de app lokaal kan draaien op basis van alleen de README - [ ] **ST-612** End-to-end acceptatietest - Voer handmatig de volledige Lars-flow uit: product aanmaken → PBI's en stories aanmaken → Sprint starten → stories slepen → taken aanmaken → API-token aanmaken → curl `next-story` → curl `log` (plan, test, commit) → activiteitenlog controleren in UI - Done when: volledige flow werkt zonder fouten of onverwacht gedrag; alle API-responses correct JSON --- ## v2 Backlog (na MVP) - [ ] Meerdere gebruikers per Scrum Team — uitgebreide auth, rol-gebaseerde permissies, uitnodigingsflow - [ ] Daily Scrum scherm — voortgang per story bijhouden tijdens Sprint - [ ] Sprint Review scherm — demo en feedback vastleggen per story - [ ] Sprint Retrospective scherm — reflectie per Sprint - [ ] Automatische story-statusupdate na commit via API - [ ] Velocity tracking — statistieken over meerdere Sprints - [ ] Definition of Done per product configureerbaar (nu vaste instelling) - [ ] Notificaties / reminders - [ ] Timeline / kalenderweergave per Sprint - [ ] Integratie GitHub Issues / Linear - [ ] Mobiele app — uitsluitend taken afvinken - [ ] Export van Product Backlog en Sprint als markdown of CSV --- ## Definition of MVP Done - [ ] Alle M0–M6 tasks afgerond - [ ] Volledige Lars-flow succesvol doorlopen (ST-612) - [ ] Alle 7 API-endpoints getest via curl (ST-403 t/m ST-409) - [ ] Demo-gebruiker kan inloggen en heeft geen schrijfrechten (ST-604) - [ ] App lokaal opzetbaar via README zonder extra hulp (ST-611) - [ ] CI/CD actief — falende build blokkeert merge (ST-610) - [ ] Beveiligingsreview API geslaagd (ST-609) - [ ] Geen bekende blocker-bugs