Commit graph

55 commits

Author SHA1 Message Date
c74d1337ce feat(backlog): sorteer PBI's en stories op prio/code/datum, onthoud keuze in localStorage; vergroot sprint-afronden dialoog
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 18:10:05 +02:00
2460eae9df
feat(M8): Realtime Solo Paneel via Postgres LISTEN/NOTIFY (ST-801..ST-806) (#8)
* feat(ST-801): pg_notify triggers on tasks and stories

Add notify_task_change() and notify_story_change() PL/pgSQL functions
plus AFTER INSERT/UPDATE/DELETE triggers on tasks and stories. Each
write emits a JSONB payload on the 'scrum4me_changes' channel with
op, entity, id, product_id, sprint_id, assignee_id and (for UPDATE)
the list of changed columns. Tasks resolve product/sprint/assignee
via their parent story so the SSE handler can filter without an extra
DB roundtrip.

The migration is a side-effect-only change (no Prisma model/schema
diff) so the Prisma Client and TypeScript types are unaffected.

Verified locally with a node-pg LISTEN client: both task and story
mutations produce the expected payload within milliseconds.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(ST-802): SSE route /api/realtime/solo for Solo Paneel updates

Node.js-runtime route handler die een dedicated pg-Client opent op
DIRECT_URL en LISTEN't op het scrum4me_changes-kanaal. Per inkomende
NOTIFY-payload filtert het server-side op product (uit query-param),
sprint (active sprint van het product) en persoonlijke relevantie
(assignee_id == userId, of assignee_id IS NULL voor stories voor de
claim-lijst).

Auth via iron-session cookie:
- 401 als sessie ontbreekt
- 400 als product_id query-param ontbreekt
- 403 als de user geen toegang heeft tot het product
- demo-tokens mogen lezen (geen write-tools op deze route)

Stream-bouw:
- text/event-stream met juiste headers (no-cache, no-transform,
  X-Accel-Buffering: no voor proxy-vrije buffering)
- ready-event bij connect met product_id en active sprint_id
- heartbeat (SSE-comment) elke 25s
- hard-close na 240s als safety-net onder Vercel maxDuration; client
  herconnect via EventSource
- cleanup op request.signal abort (tab dicht / refresh)

Cleanup-pad sluit de pg-client en de stream-controller idempotent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(ST-803): useSoloRealtime hook with EventSource lifecycle

Client-only hook die de SSE-stream van /api/realtime/solo opent en
voor de UI twee statussen exposed:
  - status: 'connecting' | 'open' | 'disconnected'
  - showConnectingIndicator: pas true als status !== 'open' >2s duurt
    (ST-805 animatie B — voorkomt flikker bij microscopische
    disconnects)

Lifecycle-gedrag:
- Reconnect met exponential backoff start 1s, plafond 30s, reset op
  'ready'-event
- Page Visibility API: bij hidden sluit de hook de connectie en stopt
  reconnect-pogingen; bij visible reopent direct
- onerror van EventSource wordt onderschept zodat we eigen backoff
  kunnen voeren ipv de browser-default
- Volledige cleanup op unmount

Voert events naar useSoloStore.getState().handleRealtimeEvent — de
echte dispatch-logica met pendingOps en gedifferentieerde
apply{Task,Story}{Update,Create,Delete} landt in ST-804. Hier is dat
nog een stub zodat dit zelf-staand kan compileren.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(ST-804): solo-store realtime dispatch + pendingOps

Wire de SSE-events uit /api/realtime/solo door naar de Zustand-store
zodat het Solo Paneel zonder refresh meebeweegt met DB-mutaties uit
welke bron dan ook (web, REST, MCP).

Migratie 20260427000216_extend_realtime_payload: voegt new-state
velden aan de pg_notify-payload toe (task_status, task_sort_order,
task_title, story_status, story_sort_order, story_title, story_code)
zodat de client geen extra fetch nodig heeft per event.

Store-uitbreiding (stores/solo-store.ts):
- pendingOps: Set<task-id> die optimistic-writes markeert; realtime
  echos voor die ids worden onderdrukt zodat eigen UI-mutaties niet
  twee keer toegepast worden of door een latere echo overschreven
- handleRealtimeEvent: dispatch op entity + op
  - task UPDATE/INSERT: bestaande tasks krijgen status/title/sort_order
    bijgewerkt; onbekende tasks worden genegeerd (story-context
    ontbreekt — gebruiker ziet ze pas na refresh)
  - task DELETE: verwijdert uit store
  - story UPDATE: werkt story_title/story_code bij op alle child-tasks
    in de store
  - story DELETE: verwijdert alle child-tasks (cascade reflectie)

Unit-test: 7 scenario's (status update, pendingOps echo-suppression,
DELETE, story-rename cascade, story-delete cascade, unknown task
no-op).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(ST-805): wire useSoloRealtime + live indicator + column-move animatie

- SoloBoard roept useSoloRealtime(productId) aan, zo komt elke task/
  story-mutatie uit web/REST/MCP binnen via SSE en wordt door de
  store-dispatcher (ST-804) verwerkt
- markPending/clearPending rond de drag-drop optimistic write zodat
  de echo van de eigen Server Action de store niet dubbel beweegt
- RealtimeIndicator: kleine status-dot in de header
  - groen ('Live') wanneer SSE-stream open OF tijdens de eerste 2s
    grace-period (animatie B in de hook — voorkomt micro-flikker)
  - grijs ('Verbinden…') na 2s in connecting-state
  - rood ('Verbroken') na 2s in disconnected-state
- Animatie A (kolom-move): bij task UPDATE-events wikkelt de hook de
  store-dispatch in document.startViewTransition + flushSync. SoloTask-
  cards krijgen view-transition-name `solo-task-<id>` (alleen wanneer
  niet aan het draggen) zodat de browser de positie-shift soepel
  animeert van bezig naar klaar (en omgekeerd)

Bestaande 89 tests blijven groen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore: pin dev to port 3000 + predev hook to clear stale processes

Voorkomt dat een stale next-dev op 3000 ervoor zorgt dat een tweede
'npm run dev' op 3001 start — wat sessies, cookies en MCP-config
inconsistent maakt.

- dev: '-p 3000' expliciet
- predev: lsof/kill alles op 3000 (idempotent — falen is ok)
- CLAUDE.md: regel toegevoegd onder Conventies

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(M8): make SSE-stream survive Solo Paneel mutations

Symptoom op feat/ST-801-realtime-triggers initial implementation:
elke task-update sloot de open SSE-stream af en triggerde een
herverbinding met backoff. In de tussentijd gemiste events.

Oorzaak: Server Actions in App Router doen een impliciete
route-tree refresh die client components remount; daarmee killt
React de useEffect die de EventSource beheert.

Fix in twee delen:

1. Hef de realtime-hook op naar de (app)-layout via een nieuwe
   `SoloRealtimeBridge`-component. Layouts overleven Server-
   Action-refreshes beter dan pages, en de bridge leest het
   product-id uit de URL via usePathname. Connection-status
   (status, showConnectingIndicator) gaat naar de solo-store
   zodat SoloBoard 'm uit een gedeelde plek kan lezen.

2. Vervang updateTaskStatusAction en updateTaskPlanAction in de
   Solo-componenten door fetch naar de bestaande Route Handler
   `PATCH /api/tasks/[id]`. Route Handlers triggeren geen
   page-refresh, dus de SSE-stream blijft staan. lib/api-auth.ts
   accepteert nu naast Bearer-tokens ook iron-session cookies
   zodat browser-fetches zonder token werken.

Bijkomend: actions/tasks.ts laat /solo bewust niet meer
revalideren (wordt nu via realtime gedekt). Sprint/planning blijft
wel revalidaten — geen realtime daar.

Toegevoegd:
- components/solo/realtime-bridge.tsx — mount in (app) layout
- scripts/realtime-mutate.ts — handige test-helper voor externe
  mutaties (alsof MCP/REST schrijft) tijdens acceptance

Debug-logs in app/api/realtime/solo/route.ts staan nog aan voor
ST-806 acceptance; worden later gestript.

Bekend issue: Chrome op localhost (HTTP/1.1) cycle't EventSource
om de paar seconden vanwege de 6-connectie-limiet en retry-
heuristiek. Safari werkt stabiel. Productie op Vercel (HTTP/2
multiplexing) zou beide browsers stabiel moeten houden — Vercel
preview test is volgende stap.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(dev): disable reactStrictMode for stable SSE testing locally

Strict Mode dubbel-mount maakt langlopende connecties tijdens
ontwikkeling moeilijk te observeren — de mount/unmount cycles in
dev rondom Hot Reload + Turbopack triggeren herhaalde EventSource-
reconnects die verbergen of de productie-flow stabiel is.

Productie kent dit gedrag niet (Strict Mode is dev-only). Heroverwogen
als M8 acceptance rond is — kan dan weer aan voor andere effects-
discipline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(M8): unguard debug logs in /api/realtime/solo for Vercel diagnose

Maakt de connect/listen/notify-logs zichtbaar in Vercel function-logs
op preview zodat we kunnen zien waarom events niet doorkomen ondanks
DIRECT_URL-fix. Logt ook hostname (gemaskeerd) + sprint id bij connect,
en pg client errors + end-events voor closed connections.

Wordt gestript in ST-806 voordat de PR uit draft gaat.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(debug): add /debug-realtime page + bare SSE endpoint

Tijdelijke debug-tooling voor M8-acceptance op Vercel preview.

- app/api/debug/realtime-stream/route.ts — geen auth, geen filtering;
  dropt elke pg_notify-event op scrum4me_changes rauw door als SSE
- app/debug-realtime/page.tsx — open zonder login op de root, toont
  binnenkomende events in een simpele <table>

Doel: isoleren of de SSE + Postgres LISTEN-pipe op Vercel überhaupt
events laat zien, los van iron-session, productfilter of solo-store.
Als ook deze niets binnen krijgt: probleem zit in pg connection of
Vercel function lifecycle. Als deze wel events toont: probleem zit
hoger in de stack (filter, store, hook).

VERWIJDEREN voordat de PR uit draft gaat.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(debug): extend /debug-realtime with stats, emit-button and filters

Bouwt de basale luister-tabel uit met diagnostische tooling om de
SSE+LISTEN-pipe stress-vrij te kunnen valideren.

Toegevoegd:
- POST /api/debug/emit-test-notify — vuurt een handmatige pg_notify
  op scrum4me_changes met een synthetic payload (debug:true) zonder
  een echte DB-UPDATE te doen. Isoleert de SSE-route van Prisma/triggers.
- DebugRealtimeClient: stats-grid (status, reconnects, total events,
  since last event met >30s rood-warning, largest gap, first-event-
  time), emit-button, reset-stats, filters op type en entity
  (incl. "debug only").
- Type/entity kolom in de tabel met kleuring per type.

Geen impact op productie- of solo-flow. Tijdelijke testtooling;
verwijderen wanneer we deze pagina niet meer nodig hebben.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(debug): add Layer 2 — mini Zustand-store + dispatch toggles

Test of SSE-event → store → render-pipeline werkt buiten de Solo
Paneel context. Mirrort het patroon van solo-store maar minimaal.

- debug-store.ts: kleine Zustand-store met tasks + applyEvent +
  applyCount/skipCount-tellers
- store-panel.tsx: rendert store-state in een tabel met statuskleuring
- client.tsx: drie layer-toggles (dispatch / flushSync / startView-
  Transition) + lift dispatch in onmessage. Zo kunnen we elke
  combinatie isoleren

Bevestigd: alle drie de toggles werken op het bare /debug-realtime
endpoint. Volgende laag is Server Action revalidation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(ST-806): cleanup debug-pages, document realtime, restore strict mode

M8 acceptance heeft de end-to-end pipeline bevestigd: trigger → NOTIFY →
SSE → store → View Transition. De cycling-symptomen waren een artefact
van testen via terminal (alt-tab triggert visibility-pause-by-design),
geen bug. Tijd om de tijdelijke instrumentatie en debug-pagina's weg te
halen en de architectuur op te schrijven.

- Verwijder /debug-realtime, /(app)/debug-realtime-app, /api/debug/*
- Strip debug-logs uit /api/realtime/solo (closed-reden alleen in dev)
- reactStrictMode weer aan
- CONNECTING_INDICATOR_DELAY_MS 2s → 4s (minder flikker bij micro-disconnects)
- Nieuwe sectie "Realtime updates (M8)" in scrum4me-architecture.md:
  diagram, NOTIFY-bron, server-filter, connection lifecycle inclusief
  visibility-pause + bekende beperking, animatie, auth
- DIRECT_URL env-rij uitgebreid met realtime-doel
- GET /api/realtime/solo gedocumenteerd in API.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 13:59:32 +02:00
8afbc4f6c4 chore(debug): add /debug-env page to verify Vercel env-var presence
Server-side gerenderde tabel die per env-var (DATABASE_URL, DIRECT_URL,
SESSION_SECRET) toont of ie gezet is, lengte, hostname (van DB-URLs)
en of het de Neon-pooler is. Geen secrets in de output.

Doel: bevestigen dat onze Vercel-env-config correct werd opgeslagen na
de eerdere ENOTFOUND 'base'-error. Tijdelijk; verwijderen zodra de
config is gevalideerd.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 10:37:46 +02:00
43a4294424
Todo description, entity codes, REST API extensions and Claude Code hardening (ST-509/511/512/513) (#2)
* docs(ST-511): add backlog entry for entity codes feature

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(ST-511): add createWithCodeRetry helper to handle P2002 race on auto codes

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(ST-511): retry on auto-code unique conflict in story and pbi create

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(ST-511): surface field errors for code and title in PBI dialog

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(ST-511): read create-state errors in Story dialog fieldError

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(ST-512): add backlog entry for REST API code/description/implementation_plan extensions; mark ST-511 done

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(ST-512): extend REST API with code, description and implementation_plan

- GET /api/products returns code, description and definition_of_done
- GET /api/products/:id/next-story returns story.code and per-task code + implementation_plan
- GET /api/sprints/:id/tasks returns description, implementation_plan, story_code and derived per-task code
- POST /api/todos accepts and returns optional description (max 2000)

All changes are additive — existing clients ignore unknown keys.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(ST-512): mark ST-512 as done

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(ST-513): add backlog entry for API hardening for Claude Code

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(ST-513): add task and story status mappers for API boundary

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(ST-513): expose lowercase status on API and accept lowercase in PATCH /api/tasks

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(ST-513): add metadata JSONB column to StoryLog

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(ST-513): accept optional metadata in story log and switch validation errors to 422

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(ST-513): add GET /api/health endpoint with optional db ping

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(ST-513): add GET /api/products/:id/claude-context bundled endpoint

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(ST-513): add docs/API.md and link from CLAUDE.md specs table

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(ST-513): mark ST-513 as done

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(ST-513): split 400 (malformed JSON) from 422 (validation), reject 'review'

Codex review on PR #2:

- P2.1: routes treated JSON parse failures as 422 instead of 400, breaking
  the contract in docs/API.md. Replace `request.json().catch(() => null)`
  with try/catch in 4 routes (tasks, reorder, todos, story-log) so a
  malformed body returns 400 and only well-formed-but-invalid bodies
  return 422.

- P2.2: PATCH /api/tasks/:id accepted `status: "review"`, but the sprint
  task list UI does not render REVIEW (no label/color, the cycle helper
  falls back to TO_DO). Reject `review` at the API until the sprint UI
  is extended; document the subset in docs/API.md.

Tests in __tests__/api updated for the new contract (29 assertions:
zod-failures now expect 422, status payloads use lowercase API values,
sprint-tasks mocks include the new story relation).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 23:40:54 +02:00
b71eb53fa8 feat(ST-507): show code badges on cards, lists and dialogs across the app
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 20:36:59 +02:00
66063f035a feat(ST-507): add code input to Product, Pbi and Story forms
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 20:36:47 +02:00
c45ba1d0c2 feat(ST-509): add description textarea to Todo create and edit cards
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 19:59:55 +02:00
0dc907b75c feat(ST-507): add email input to settings and surface in user menu
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 19:37:51 +02:00
e887f796c7 feat(ST-507): replace navbar roles/settings/logout with avatar user menu
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 19:31:21 +02:00
8a5076a5ed feat(ST-611): add tour screenshots to public/screenshots
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 19:22:52 +02:00
3977b89ca7 feat(ST-611): add tour with screenshots, Solo Paneel and Sprint Board to landing page
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 19:04:57 +02:00
29ed4f2773 feat: show active product name in navbar, links to product page
Sub-layout sets product in Zustand store; NavBar reads it.
getAccessibleProduct wrapped with React cache to avoid double DB call.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 17:56:50 +02:00
d684732ec8 feat: show tasks with priority and status in unassigned stories sheet
Tasks are always visible under each story. Click a task to expand
its description.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 17:49:19 +02:00
1abbd4e5e4 fix: set lastProductId cookie in proxy instead of Server Component
Cookies can only be written in Server Actions or Route Handlers.
Moved the write to proxy.ts where NextResponse.cookies.set is allowed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 17:25:17 +02:00
d27c55c7fc fix: sprint board accessible to product members, not only owners
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 17:25:10 +02:00
af4a357709 fix: product backlog page accessible to members, not only owners
Replaced owner-only query (user_id = session.userId) with
getAccessibleProduct which also accepts product members.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 17:15:26 +02:00
928328b380 fix(ST-102): show products via membership on dashboard, not just owned
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 17:12:42 +02:00
89e5164a28 feat(ST-358): add unassigned stories sheet with claim-on-click
- UnassignedStoriesSheet: slide-in sheet listing unassigned sprint stories
- ClaimStoryRow: form action + ClaimButton with useFormStatus pending state
- Successful claim removes story from local list and shows success toast
- Empty state: "Geen ongeclaimde stories. Lekker bezig!"
- Demo: DemoTooltip wraps Pak op button, claim button disabled
- Page now fetches stories with _count.tasks instead of just count
- claimStoryAction also revalidates /products/[id]/solo path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 16:55:55 +02:00
ca631e71ec feat(ST-355): add /solo route, cookie helper, product picker, and solo product page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 16:29:31 +02:00
358c88a9d9 feat(ST-353): add assignee chip and claim/reassign dropdown to sprint story card
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 16:24:34 +02:00
ef5c7c7675 feat(ST-351): add UserAvatar component and /api/users/[id]/avatar route
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 16:15:56 +02:00
0a27be4886 feat(ST-313): merge sprint board into single three-panel view
- TriplePane component with two resizable dividers, localStorage persistence, mobile tabs
- SprintBoardClient replaces SprintBacklogClient + PlanningRightClient
- Left panel: Product Backlog (PBIs with stories to add to sprint)
- Middle panel: Sprint Backlog (stories in sprint, click to select, sortable)
- Right panel: TaskList for selected story
- /sprint/planning redirects to /sprint
- Remove PlanningLeft, PlanningRightClient, SprintBacklogClient

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 22:53:39 +02:00
4df83dcdbb feat(ST-108/ST-208): replace inline forms with PBI and story dialogs
- PbiDialog: create/edit with priority select and optional description
- StoryDialog: create/edit with priority, description, acceptance criteria, activity log, and delete
- PrioritySelect: reusable controlled select component
- Edit icons always visible on PBI rows and story blocks
- Dialog backdrop uses 40% opacity blur

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 22:53:26 +02:00
02096196ab feat(ST-601): add loading skeletons for dashboard, settings and todos
De drie zware split-pane routes hadden al loading.tsx; dashboard,
settings en todos kregen elk een passende animate-pulse skeleton.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 20:09:48 +02:00
0595a2a5d9 feat(ST-506): toon gebruikersrollen in navigatiebalk
Haalt rollen op in AppLayout en geeft ze door aan NavBar.
NavBar toont afkortingen (PO · SM · Dev) rechts van de navigatie.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 20:09:42 +02:00
e991f4f185 feat(todos): include team-member products in todos page query
Use productAccessFilter so users who are product members (not just
owners) see those products in the todo form and promote dialogs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 19:17:05 +02:00
2deea9e841 Added Beta development banner to the app. This will be removed once we are ready for a public release. 2026-04-25 17:26:35 +02:00
4ec0683f88 Document Prisma ERD generation 2026-04-25 17:08:55 +02:00
b5e967d8d3 Add analytics and documentation updates 2026-04-25 15:11:51 +02:00
e0efb65efb Fix scoped access checks 2026-04-25 14:36:55 +02:00
d90a8fd560 fix: PATCH /api/tasks/:id geeft 403 bij cross-user toegang
Vervang productAccessFilter in de WHERE clause door een expliciete
toegangscheck na het ophalen. findFirst haalt de taak op met product
en members (gefilterd op auth.userId); daarna wordt eigenaarschap of
teamlidmaatschap gecontroleerd en 403 teruggegeven bij geen toegang.

Dit herstelt het onderscheid 404 (taak bestaat niet) vs 403 (taak
bestaat maar geen toegang), zoals de beveiligingstest verwacht.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 13:44:51 +02:00
e94959c5bc feat: PB-overzicht in instellingen + documentatie bijgewerkt
Settings:
- "Mijn teams" vervangen door gecombineerde "Product Backlogs" sectie
- Toont eigen producten (badge Eigenaar) en team-lidmaatschappen (badge Developer)
- Productnaam is klikbaar naar de product backlog
- "Verlaten"-knop met bevestiging alleen voor Developer-lidmaatschappen
- Lege staat met link naar product aanmaken

Docs:
- architecture.md: users tabel aangevuld met bio/bio_detail/avatar_data;
  Prisma schema excerpt bijgewerkt; projectstructuur bijgewerkt (profile route, ProfileEditor)
- functional-spec.md: F-02b gebruikersprofiel en F-02c PB-overzicht toegevoegd;
  datamodel users rij bijgewerkt; settings route bijgewerkt
- backlog.md: ST-507 profiel en ST-508 PB-overzicht toegevoegd als afgerond

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 13:40:47 +02:00
ec9de5a962 fix: header en footer sticky op landingspagina
Zelfde patroon als (app) layout: h-screen overflow-hidden op de wrapper,
flex-1 overflow-y-auto op main, shrink-0 op footer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 13:32:32 +02:00
1ff894a6c0 feat: gebruikersprofiel met avatar, bio en uitgebreide beschrijving
- Schema: bio (160), bio_detail (2000) en avatar_data (bytea) op User
- POST /api/profile/avatar: validatie MIME-type + max 12 MB vóór verwerking,
  Sharp resize naar max 700x700 (fit inside), output WebP q85, opgeslagen als bytea in Neon
- GET /api/profile/avatar: serveert avatar met Cache-Control private 1u
- updateProfileAction: slaat bio en bio_detail op via Server Action + Zod
- ProfileEditor client component: avatar preview, upload met client-side validatie,
  bio-velden met tekenlimieten
- Settings page: profiel-sectie bovenaan, uitgeschakeld voor demo-gebruiker
- next.config: sharp als serverExternalPackage

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 13:30:38 +02:00
357b1e32e8 feat: ProductMember — team management for product backlogs
- Add ProductMember model (many-to-many User ↔ Product)
- Add productAccessFilter helper (owner OR member OR clause)
- Replace all ownership checks across actions and API routes
- Add addProductMemberAction / removeProductMemberAction / leaveProductAction
- Add TeamManager component in product settings (owner adds/removes Developers)
- Add LeaveProductButton in user settings (member leaves a product team)
- Regenerate Prisma Client after schema migration

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 13:09:44 +02:00
fc12e3cc64 feat: landingspagina met app-uitleg, Scrum-samenvatting en gebruikershandleiding
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 12:47:32 +02:00
76d6f0a09d fix: nav en statusbar vast op top/bottom via h-screen layout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 12:40:05 +02:00
cb7eb36fbb feat: Todo altijd gekoppeld aan product backlog
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 12:35:40 +02:00
b4371f5afb chore: documentatie naar docs/, iconen bijgewerkt, theme.css verplaatst
- scrum4me-*.md en MD3_Color_Scheme_Documentation.md verplaatst naar docs/
- Srum4MeIcons.html verplaatst naar docs/icons.html
- theme.css verplaatst van root naar app/styles/theme.css
- Import in globals.css bijgewerkt
- Alle app-iconen vervangen door nieuw logo (icon-master-light.svg)
- AppIcon component bijgewerkt met nieuw SVG
- CLAUDE.md verwijzingen bijgewerkt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 22:51:42 +02:00
71e4ebc22d feat: statusbalk met versie en builddatum
Voegt sticky statusbalk toe aan de onderkant van de app met:
- Copyright melding
- App-versie uit package.json (NEXT_PUBLIC_APP_VERSION)
- Builddatum ingesteld op het moment van de build (NEXT_PUBLIC_BUILD_DATE)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 17:12:20 +02:00
f2698d98d8 fix: function props vanuit server component verplaatst naar client wrapper 2026-04-24 16:51:11 +02:00
088d318e51 fix: ST-609 demo-check toegevoegd aan POST /api/stories/:id/log en POST /api/todos 2026-04-24 16:34:04 +02:00
d9692f908a fix: expliciete type voor tasks.map callback in planning page 2026-04-24 14:46:38 +02:00
567e91493e fix: prisma generate in CI en expliciete types in map/filter callbacks 2026-04-24 14:23:41 +02:00
ecc7a10679 fix: lint errors en warnings opgelost voor CI 2026-04-24 14:09:03 +02:00
d11b114fc1 feat: ST-601-ST-612 M6 polish, beveiliging en launch-ready
- ST-601/602: loading skeletons en error boundary
- ST-603: Sonner toasts op alle CRUD-operaties
- ST-604: DemoTooltip op uitgeschakelde knoppen
- ST-605: KeyboardSensor dnd-kit, Escape sluit modals
- ST-606: min-width banner < 1024px
- ST-607: WCAG AA aria-labels en skip link
- ST-608: rate limiting login (10/min) en registratie (5/uur)
- ST-609: security integratietests cross-user toegang (7 tests)
- ST-610: GitHub Actions CI/CD workflow
- ST-611: README met quickstart, deployment en API-docs
- ST-612: Lars-flow acceptatiechecklist
- fix: settings toont gebruikersnaam i.p.v. interne id
- fix: seed idempotent, testdata altijd gekoppeld aan demo-gebruiker

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 12:36:23 +02:00
8bb8754d01 feat: ST-501-ST-506 M5 todo-lijst en rolbeheer
- Todo-lijst met snelle invoer via Enter (ST-501)
- Todo afvinken met visuele doorstreping (ST-502)
- Archiveer afgeronde todos (ST-503)
- Promoveer todo naar PBI met product en prioriteit keuze (ST-504)
- Promoveer todo naar story met product, PBI en prioriteit keuze (ST-505)
- Rolbeheer in instellingen: Product Owner, Scrum Master, Developer (ST-506)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 11:59:25 +02:00
b71a1a7328 feat: ST-401-ST-410 M4 REST API, tokenbeleer en activiteitenlog
- api-auth.ts was al aanwezig; demo-check toegevoegd per endpoint (ST-401)
- Token aanmaken (SHA-256 hash, eenmalig tonen), intrekken, max 10 (ST-402)
- GET /api/products actieve productenlijst (ST-403)
- GET /api/products/:id/next-story hoogst geprioriteerde open story (ST-404)
- GET /api/sprints/:id/tasks met limit parameter (ST-405)
- PATCH /api/stories/:id/tasks/reorder met ID-validatie (ST-406)
- POST /api/stories/:id/log met discriminatedUnion per type (ST-407)
- PATCH /api/tasks/:id status bijwerken met cross-user bescherming (ST-408)
- POST /api/todos via API aanmaken (ST-409)
- StoryLog component met kleurcodering per type in story slide-over (ST-410)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 11:56:29 +02:00
d92e548f88 feat: ST-301-ST-312 M3 Sprint Backlog en Sprint Planning
- useSprintStore met sprintStoryOrder/taskOrder (ST-301)
- Sprint aanmaken modal met Sprint Goal validatie (ST-302)
- Sprint Backlog pagina SplitPane layout met Sprint Goal header (ST-303)
- Stories toevoegen aan Sprint via knop in rechterpaneel (ST-304)
- Sprint Backlog volgorde aanpassen via dnd-kit (ST-305)
- Story uit Sprint verwijderen met status terug naar OPEN (ST-306)
- Sprint Planning pagina SplitPane met story selectie (ST-307)
- Taken aanmaken inline in rechterpaneel (ST-308)
- Taak drag-and-drop verticaal met optimistische update (ST-309)
- Taakstatus toggle TO_DO/IN_PROGRESS/DONE met voortgangsindicator (ST-310)
- Taak inline bewerken en verwijderen (ST-311)
- Sprint afronden dialoog met per-story Done/Terug keuze (ST-312)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 11:51:27 +02:00
4dd62c199c feat: ST-201-ST-210 M2 stories, drag-and-drop en Zustand stores
- usePlannerStore met pbiOrder/storyOrder init/reorder/rollback (ST-201)
- useSelectionStore uitgebreid met selectedStoryId en clearSelection (ST-202)
- PBI drag-and-drop binnen prioriteitsgroep via dnd-kit (ST-203)
- PBI slepen over prioriteitsgrens wijzigt priority (ST-204)
- Stories als blokken met prioriteit- en statusbadge (ST-205/ST-206)
- Story drag-and-drop horizontaal binnen en tussen groepen (ST-207)
- Story detail slide-over met bewerkformulier (ST-208)
- Story verwijderen met bevestigingsstap (ST-209)
- Filter op status en prioriteit in rechterpaneel (ST-210)
- Fix: infinite loop in useEffect door stabiele string dependency

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 11:46:18 +02:00