ST-602 (error.tsx op (app)-niveau), ST-603 (Sonner), ST-604 (DemoTooltip), ST-609 (security tests), ST-610 (CI), ST-611 (README) waren al gereed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
31 KiB
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; Data Table + detail-kaart | ST-501 – ST-506, ST-509 – ST-510 |
| M6: Polish & Launch-ready | Foutafhandeling, toegankelijkheid, CI/CD, beveiliging | ST-601 – ST-612 |
Backlog
M0: Foundation
-
ST-001 Project scaffolding
create-next-appmet TypeScript strict, Tailwind CSS, App Router; installeer shadcn/ui, Zustand, dnd-kit, iron-session, bcrypt, Zod; configureer path aliases (@/)- Done when:
npm run devstart zonder fouten;npm run lintgeeft geen errors; shadcnButtonrendert op een testpagina
-
ST-002 Prisma v7 setup +
prisma.config.ts- Installeer Prisma v7 +
@prisma/adapter-pg; schrijfprisma.config.tsmetDATABASE_URLvia Zod-gevalideerde env; schrijflib/prisma.tssingleton - Done when:
npx prisma db pushslaagt; Prisma Client importeerbaar in een testbestand zonder fouten
- Installeer Prisma v7 +
-
ST-003 Database schema migratie (volledige initiële migratie)
- Schrijf het volledige
schema.prismaop 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 initslaagt; alle tabellen zichtbaar in DB-client;npx prisma validategeeft geen fouten
- Schrijf het volledige
-
ST-004 Seed met testdata
- Schrijf
prisma/seed.tsop 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 seedslaagt; DB bevat alle PBI's en stories uit het backlog-document; demo-gebruiker aanwezig
- Schrijf
-
ST-005 Environment variabelen +
lib/env.ts- Schrijf Zod-schema voor alle env vars (
DATABASE_URL,DIRECT_URL,SESSION_SECRET,NODE_ENV); exporteer gevalideerdenvobject; schrijf.env.examplemet instructies - Done when: app gooit een begrijpelijke fout bij ontbrekende env var;
.env.examplevolledig gedocumenteerd
- Schrijf Zod-schema voor alle env vars (
-
ST-006 Authenticatie — registratie en inloggen
- Schrijf
lib/auth.ts(registreer met bcrypt hash, verifieer bij inloggen); schrijflib/session.ts(iron-session config); implementeer/registeren/loginpagina'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
- Schrijf
-
ST-007 Route-beveiliging via
proxy.ts- Schrijf
proxy.tsdie sessiecookie-aanwezigheid controleert; redirect naar/loginbij alle/dashboard,/products/*,/todos,/settings/*routes zonder sessiecookie; authenticated users worden van/loginen/registerdoorgestuurd naar/dashboard; volledige sessievalidatie gebeurt server-side in de app layout - Done when: directe navigatie naar
/dashboardzonder sessie redirect naar/login; ingelogde gebruiker op/loginredirect naar/dashboard
- Schrijf
-
ST-008 Navigatieshell + dashboard-layout
- Schrijf
app/(app)/layout.tsxmet navigatiebalk (logo, productenlink, todolink, instellingen, uitlogknop); implementeer uitlog Server Action; implementeer/dashboardals lege productenlijstpagina met "Maak je eerste product aan" lege staat; zet demo-badge zichtbaar alsisDemo === true - Done when: volledige auth-flow (register → login → dashboard → logout → login) werkt end-to-end; demo-gebruiker ziet badge in navigatie
- Schrijf
M1: Producten & Product Backlog
-
ST-101 Product aanmaken
/products/newpagina met formulier (naam, beschrijving, repo URL, definition of done);createProductServer 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
<SplitPane>Client Component met versleepbare horizontale splitter; sla splitter-positie op inlocalStorageper 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
- Bouw herbruikbaar
-
ST-105 Navigatiebar-component per paneel
- Bouw herbruikbaar
<PanelNavBar>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
- Bouw herbruikbaar
-
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);createPbiServer Action; nieuw PBI verschijnt onderaan de juiste prioriteitsgroep - Done when: PBI aangemaakt en zichtbaar in juiste prioriteitsgroep; lege staat toont prompt
- Linkerpaneel van
-
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);
updatePbiServer Action; verwijderen met bevestigingsdialoog inclusief waarschuwing cascade;deletePbiServer Action - Done when: titelbewering opgeslagen zonder paginaverversing; verwijderen cascade-verwijdert stories (verifieerbaar in DB)
- Inline bewerkingsmodus via dubbelklik of contextmenu (titel, omschrijving, prioriteit);
-
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
- Klikken op PBI in linkerpaneel toont bijbehorende stories rechts via
-
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
usePlannerStoreZustand-store- Schrijf
stores/planner-store.tsmetpbiOrder,storyOrder,taskOrder;init*,reorder*,rollback*actions; TypeScript strict types - Done when: store importeerbaar in een Client Component;
initPbisvult order;reorderPbismuteert order;rollbackPbisherstelt vorige staat
- Schrijf
-
ST-202
useSelectionStoreZustand-store- Schrijf
stores/selection-store.tsmetselectedPbiId,selectedStoryId, setters enclearSelection - Done when: selectie in linkerpaneel via store zichtbaar in rechterpaneel zonder prop drilling
- Schrijf
-
ST-203 dnd-kit setup + PBI drag-and-drop
- Installeer dnd-kit; wrap linkerpaneel in
DndContext+SortableContext; implementeeruseSortableper PBI-rij;onDragEnd: bereken nieuwesort_ordervia float-gemiddelde; optimistisch updaten viausePlannerStore;reorderPbisActionServer Action; rollback bij fout - Done when: PBI versleepbaar binnen prioriteitsgroep; volgorde opgeslagen na loslaten; UI rollback bij gesimuleerde server-fout
- Installeer dnd-kit; wrap linkerpaneel in
-
ST-204 PBI drag-and-drop over prioriteitsgrens
- Uitbreiding ST-203: slepen over een prioriteitsgrens wijzigt
priorityvan het PBI;sort_orderwordt onderaan de doelgroep geplaatst;updatePbiPriorityServer Action - Done when: PBI naar prioriteit 2 slepen vanuit prioriteit 3 wijzigt zowel prioriteit als volgorde
- Uitbreiding ST-203: slepen over een prioriteitsgrens wijzigt
-
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;
createStoryServer Action - Done when: drie stories zichtbaar als blokken; nieuw blok verschijnt in juiste prioriteitsgroep
- 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;
-
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
SortableContextper prioriteitsgroep;onDragEnd: herrangschikking via float-gemiddelde instoryOrder; slepen naar andere groep wijzigt prioriteit; optimistisch viausePlannerStore;reorderStoriesActionServer Action; rollback bij fout - Done when: story versleepbaar binnen groep en naar andere groep; volgorde en prioriteit persistent na loslaten
- dnd-kit horizontale
-
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;
updateStoryServer Action - Done when: klikken op blok opent detail; bewerken persisteert; sluiten keert terug naar backlog
- Klikken op storyblok opent slide-over of modal met titel, omschrijving, acceptatiecriteria, statusbadge, activiteitenlog (leeg bij nieuwe story); bewerkformulier voor titel/omschrijving/acceptatiecriteria;
-
ST-209 Story verwijderen
- Verwijderknop in story-detail of contextmenu; bevestigingsdialoog met waarschuwing cascade (taken);
deleteStoryServer Action; blok verdwijnt optimistisch uit het rechterpaneel - Done when: story verwijderd incl. cascade-taken (verifieerbaar in DB); blok direct verdwenen uit UI
- Verwijderknop in story-detail of contextmenu; bevestigingsdialoog met waarschuwing cascade (taken);
-
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
useSprintStoreZustand-store- Schrijf
stores/sprint-store.ts;initSprint,addStoryToSprint,removeStoryFromSprint,reorderSprintStories,rollbackSprint - Done when: store beheert sprint-story-volgorde onafhankelijk van planner-store
- Schrijf
-
ST-302 Sprint aanmaken
- "Sprint starten" knop op productpagina (zichtbaar als geen actieve Sprint); modal met Sprint Goal invoerveld;
createSprintServer 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
- "Sprint starten" knop op productpagina (zichtbaar als geen actieve Sprint); modal met Sprint Goal invoerveld;
-
ST-303 Sprint Backlog scherm — layout
/products/[id]/sprintpagina;SplitPanemet 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:addStoryToSprintin store; story krijgt badge "In Sprint" in Product Backlog;addStoryToSprintActionServer Action (zetsprint_id+ statusIN_SPRINT); rollback bij fout - Done when: story gesleept naar Sprint verschijnt links en toont "In Sprint" badge rechts; persistent na herlaad
- dnd-kit drag vanuit rechterpaneel naar linkerpaneel;
-
ST-305 Sprint Backlog story volgorde aanpassen
- dnd-kit verticale
SortableContextin linkerpaneel; herrangschikking via float-gemiddelde inuseSprintStore;reorderSprintStoriesActionServer Action - Done when: volgorde in Sprint Backlog persistent na loslaten en na paginaverversing
- dnd-kit verticale
-
ST-306 Story uit Sprint verwijderen
- Verwijderknop per story in Sprint Backlog;
removeStoryFromSprintActionServer Action (wistsprint_id, zet status terug opOPEN); story verdwijnt links en badge verdwijnt rechts - Done when: verwijderen persistent; story beschikbaar in Product Backlog rechterpaneel
- Verwijderknop per story in Sprint Backlog;
-
ST-307 Sprint Planning scherm — layout
/products/[id]/sprint/planningpagina;SplitPanemet 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);
createTaskServer Action; voortgangsindicator per story (bijv. "0/0 Done") - Done when: taak aangemaakt en zichtbaar in takenlijst; voortgangsindicator toont "0/1 Done"
- "Taak aanmaken" knop in rechterpaneel navigatiebar; inline formulier (titel, omschrijving, prioriteit);
-
ST-309 Taak drag-and-drop (verticaal)
- dnd-kit verticale
SortableContextin rechterpaneel; herrangschikking via float-gemiddelde inusePlannerStore.taskOrder;reorderTasksActionServer Action - Done when: taken versleepbaar; volgorde persistent na loslaten
- dnd-kit verticale
-
ST-310 Taakstatus bijhouden
- Status-toggle per taak (TO_DO → IN_PROGRESS → DONE) via klikbare badge of dropdown;
updateTaskStatusServer Action; voortgangsindicator op story updatet optimistisch - Done when: taak op DONE zetten verhoogt teller in voortgangsindicator; persistent na herlaad
- Status-toggle per taak (TO_DO → IN_PROGRESS → DONE) via klikbare badge of dropdown;
-
ST-311 Taak bewerken en verwijderen
- Inline bewerken van titel, omschrijving en prioriteit;
updateTaskServer Action; verwijderen met bevestiging;deleteTaskServer Action - Done when: titelwijziging persisteert; verwijderde taak verdwijnt uit lijst
- Inline bewerken van titel, omschrijving en prioriteit;
-
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?";
completeSprintServer Action zet Sprint op COMPLETED, verwerkt keuzes per story - Done when: Sprint afgerond; stories correct verplaatst naar DONE of OPEN; nieuwe Sprint aanmaakbaar
- "Sprint afronden" knop op Sprint-pagina; dialoog toont per story de status en vraagt: "Markeer als Done of terug naar Backlog?";
M4: Claude Code REST API
-
ST-401 API-token infrastructuur
- Schrijf
lib/api-auth.ts: parseerAuthorization: Bearerheader; bereken SHA-256 hash; zoek op inapi_tokens; controleerrevoked_at; retourneeruserIdof 401; retourneer 403 alsis_demo - Done when: geldige token geeft userId terug; ongeldige token geeft 401; ingetrokken token geeft 401; demo-token op schrijf-endpoint geeft 403
- Schrijf
-
ST-402 API-tokenbeheer UI
/settings/tokenspagina; 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 voor producten waar de tokengebruiker eigenaar of teamlid is - Done when:
curl -H "Authorization: Bearer <token>" /api/productsretourneert correct JSON inclusief gedeelde product backlogs; 401 zonder token
- Route Handler; authenticatie via
-
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
- Route Handler; haal hoogst geprioriteerde OPEN story op van actieve Sprint van het product (priority ASC, sort_order ASC); retourneer
-
ST-405
GET /api/sprints/:id/tasks— taken ophalen- Route Handler met
?limit=Nquery 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=5retourneert max 5
- Route Handler met
-
ST-406
PATCH /api/stories/:id/tasks/reorder— taakvolgorde aanpassen- Route Handler; body:
{ task_ids: string[] }; valideer alle IDs behoren tot de story; updatesort_ordervia 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
- Route Handler; body:
-
ST-407
POST /api/stories/:id/log— activiteit vastleggen- Route Handler; body:
{ type, content, status?, commit_hash?, commit_message? }; Zod-validatie per type; schrijf naarstory_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
- Route Handler; body:
-
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
- Route Handler; body:
-
ST-409
POST /api/todos— todo aanmaken- Route Handler; body:
{ title: string, product_id: string }; valideer dat product bij de geverifieerde gebruiker hoort; schrijf naartodos; 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
- Route Handler; body:
-
ST-410 Story-activiteitenlog UI
- Activiteitenlog sectie in story-detail slide-over; haal
story_logsop via Server Component; render chronologisch; visuele stijl per type (IMPLEMENTATION_PLAN = blauw, TEST_RESULT passed = groen, failed = rood, COMMIT = paars); commit-hash klikbaar alsrepo_urlingesteld; lege staat - Done when: drie log-entries (plan, test, commit) correct gestyled; commit-hash link opent in nieuw tabblad
- Activiteitenlog sectie in story-detail slide-over; haal
M5: Todo-lijst
Herontwerp (april 2026): ST-501–505 beschreven de oorspronkelijke QuickInput-aanpak. Die is geïmplementeerd maar vervangen door een Data Table + detail-kaart ontwerp (ST-509–510). ST-501–505 zijn als referentie bewaard; de functionele eisen zijn ongewijzigd.
-
ST-501 Todo-lijst pagina (vervangen door ST-509)
/todospagina; haal actieve (niet-gearchiveerde) todos op inclusief productnaam; snel-invoerveld bovenaan met product-dropdown (verplicht) en titel (Enter om op te slaan);createTodoServer 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 (vervangen door ST-509)
- Checkbox per todo;
toggleTodoServer Action; afgevinkte todos visueel doorgestreept; afgevinkte todos blijven zichtbaar onderaan de lijst - Done when: afvinken persistent na herlaad; visuele doorstreping correct
- Checkbox per todo;
-
ST-503 Afgevinkte todos archiveren (vervangen door ST-510)
- "Archiveer afgeronde items" knop;
archiveCompletedTodosServer Action; gearchiveerde todos verdwijnen uit standaardweergave - Done when: archiveren verbergt alle afgevinkte todos; telling correct
- "Archiveer afgeronde items" knop;
-
ST-504 Todo promoveren naar PBI (vervangen door ST-510)
- "Promoveer naar PBI" contextmenu of knop per todo; dialoog: product dropdown (actieve producten), prioriteit dropdown; titel vooringevuld (bewerkbaar); bevestigingswaarschuwing;
promoteTodeToPbiServer Action (maak PBI aan, verwijder todo) - Done when: gepromoveerde todo verdwijnt; PBI zichtbaar in juist product met juiste prioriteit
- "Promoveer naar PBI" contextmenu of knop per todo; dialoog: product dropdown (actieve producten), prioriteit dropdown; titel vooringevuld (bewerkbaar); bevestigingswaarschuwing;
-
ST-505 Todo promoveren naar story (vervangen door ST-510)
- "Promoveer naar story" knop per todo; dialoog: product dropdown → PBI dropdown (gefilterd op product), prioriteit; titel vooringevuld;
promoteTodoToStoryServer Action (maak story aan, verwijder todo) - Done when: gepromoveerde todo verdwijnt; story zichtbaar in juist PBI met juiste prioriteit
- "Promoveer naar story" knop per todo; dialoog: product dropdown → PBI dropdown (gefilterd op product), prioriteit; titel vooringevuld;
-
ST-509 Todo Data Table
- Installeer
@tanstack/react-table; voeg shadcndata-table-patroon toe - Kolommen:
- Selectie-checkbox (kolom 1): multi-select voor bulk-archivering; header-checkbox selecteert/deselecteert alle zichtbare rijen
- Titel (kolom 2): max 2 regels,
line-clamp-2 truncate; afgevinkte todos doorgestreept; klik op rij (buiten checkbox) opent detail-kaart - Productnaam-badge (kolom 3)
- Aanmaakdatum (kolom 4)
- Toolbar boven de tabel:
- Product-filter dropdown (Alles / Geen product / per product)
- "+" knop: opent lege detail-kaart voor nieuw aanmaken (erft geselecteerd filter-product)
- "Archiveer geselecteerde (N)" knop: actief zodra ≥ 1 checkbox aangevinkt; roept
archiveSelectedTodosActionaan met de geselecteerde IDs; resettet selectie na afloop
- Paginering: max 10 rijen per pagina; vorige/volgende knoppen; paginatelling ("1–10 van 23")
- Lege staat: "Geen todo's voor deze selectie." bij lege filter; "Nog geen todo's. Gebruik + om er een aan te maken." bij volledig lege lijst
archiveSelectedTodosActiontoevoegen aanactions/todos.ts: valideert dat alle meegegeven IDs bij de ingelogde gebruiker horen vóór schrijven;archiveManyviaupdateMany- Done when: tabel toont alle actieve todos; paginering werkt; product-filter werkt; selectie-checkbox selecteert meerdere rijen; bulk-archiveren verwijdert geselecteerde rijen uit de weergave
- Installeer
-
ST-510 Todo detail-kaart
- Kaart onder de tabel; altijd zichtbaar (leeg als geen todo geselecteerd of aangemaakt wordt)
- Aanmaken: "+" in toolbar zet kaart in aanmaak-modus; velden: product-dropdown (erft filter-product, of "Geen product" bij "Alles"), titel; opslaan via
createTodoAction; na opslaan kaart leegmaken en tabel ververst - Bewerken: klik op tabelrij (buiten checkbox) laadt todo in kaart; velden: product-dropdown, titel, done-toggle; opslaan via nieuwe
updateTodoAction(title + product_id + done); annuleren deselecteert rij en leegt kaart - Promoveren: knoppen "→ PBI" en "→ Story" in de kaart; openen de bestaande
PromotePbiDialogenPromoteStoryDialog; alleen zichtbaar bij een bestaande geselecteerde todo - Demo-modus: kaart-invoervelden uitgeschakeld; knoppen verborgen of disabled
updateTodoActiontoevoegen aanactions/todos.ts: valideert eigenaarschap; pasttitle,product_iden/ofdoneaan;revalidatePath('/todos')- Done when: aanmaken via kaart persisteert; bewerken van titel, product en done-status werkt; promote vanuit kaart opent juist dialoog en verwijdert todo na bevestiging; kaart leeg bij geen selectie; demo-gebruiker ziet uitgeschakelde kaart
-
ST-506 Rolbeheer in instellingen
/settingspagina met roltoewijzing (checkbox per rol: Product Owner, Scrum Master, Developer); minimaal één rol verplicht;updateRolesServer Action; geselecteerde rollen zichtbaar in profielbalk- Done when: rollen bijwerken persisterend; profielbalk toont gekozen rollen; uitvinken van alle rollen geeft validatiefout
-
ST-507 Gebruikersprofiel (buiten originele backlog toegevoegd)
- Profielfoto-upload (JPEG/PNG/WebP, max 12 MB), server-side resizing naar max 700×700 WebP met Sharp, opgeslagen als bytea in Neon; bio (max 160) en bio_detail (max 2000) als aparte velden;
POST /api/profile/avatar+GET /api/profile/avatar+updateProfileAction - Done when: foto geüpload en zichtbaar in instellingen; bio opgeslagen; ongeldige bestanden geweigerd vóór verwerking
- Profielfoto-upload (JPEG/PNG/WebP, max 12 MB), server-side resizing naar max 700×700 WebP met Sharp, opgeslagen als bytea in Neon; bio (max 160) en bio_detail (max 2000) als aparte velden;
-
ST-508 Product Backlog-overzicht in instellingen (buiten originele backlog toegevoegd)
- Gecombineerde lijst op
/settingsvan eigen producten (badge "Eigenaar") en team-lidmaatschappen (badge "Developer" + eigenaarsnaam); klikbaar naar product; "Verlaten"-knop met bevestiging voor lidmaatschappen; lege staat met CTA - Done when: eigenaar-producten en team-producten zichtbaar in één lijst; verlaten werkt en verwijdert rij
- Gecombineerde lijst op
M6: Polish & Launch-ready
-
ST-601 Loading states en skeletons
loading.tsxvoor alle zware routes (/products/[id],/sprint,/sprint/planning); skeletoncomponenten voor PBI-lijst, story-blokken en takenlijst; pending states op alle form-submit-knoppen viauseFormStatus- Done when: navigeren naar een trage route toont skeleton; submit-knoppen disablen tijdens Server Action
-
ST-602 Error boundaries
error.tsxvoor 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
isDemoin sessie - Done when: demo-gebruiker ziet alle knoppen maar kan niets wijzigen; tooltip zichtbaar bij hover
- Alle aanmaak-, bewerk- en verwijderknoppen disabled + tooltip "Niet beschikbaar in demo-modus" voor demo-sessies; gebaseerd op
-
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;
roleenaria-selectedop geselecteerde PBI in linkerpaneel - Done when: geen WCAG AA contrastfouten op primaire flows; alle knoppen hebben toegankelijke labels
- Kleurcontrast-check op alle tekst en badges; aria-labels op icon-only knoppen; focus-ring zichtbaar op alle interactieve elementen;
-
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 binnen de toegankelijke product-scope valt; cross-scope reads zijn onmogelijk tenzij de gebruiker via
product_membersgekoppeld is; voeg integratietests toe die cross-user toegang testen - Done when: poging om een niet-gedeeld product van een andere gebruiker op te halen via API geeft 403 of 404; gedeelde producten zijn wel zichtbaar; getest met twee test-gebruikers
- Controleer alle Route Handlers: elke schrijfoperatie valideert dat de resource binnen de toegankelijke product-scope valt; cross-scope reads zijn onmogelijk tenzij de gebruiker via
-
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
- Workflow:
-
ST-611 README en lokale setup-documentatie
- Schrijf
README.mdmet: 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, Vercel Analytics status en directe dependencies zoals Sharp - De in-app landingspagina (
/) bevat al een gebruikershandleiding, Scrum-samenvatting en API-overzicht — de README richt zich op lokale setup en deployment - Done when: iemand zonder context de app lokaal kan draaien op basis van alleen de README en
.env.example
- Schrijf
-
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→ curllog(plan, test, commit) → activiteitenlog controleren in UI - Done when: volledige flow werkt zonder fouten of onverwacht gedrag; alle API-responses correct JSON
- Voer handmatig de volledige Lars-flow uit: product aanmaken → PBI's en stories aanmaken → Sprint starten → stories slepen → taken aanmaken → API-token aanmaken → curl
v2 Backlog (na MVP)
- Uitnodigingsflow voor teams — e-mailuitnodiging of link-gebaseerd; nu kunnen alleen admins met toegang tot het systeem Developers toevoegen via gebruikersnaam
- 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