* feat(tooling): extend backlog parser to support PBI-x milestone headers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore(backlog): mark ST-801–806 as done
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* 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>
* feat(ST-901): add user.active_product_id with FK to Product
- Nullable relation User → Product with onDelete: SetNull
- Index on active_product_id for join performance
- Migration: 20260427165329_add_user_active_product_id
- Install @tanstack/react-table (was missing from node_modules)
- Fix PRIORITY_COLORS ref removed in earlier refactor
- Note: User schema change affects vendor/scrum4me-mcp submodule — run prisma generate + tsc --noEmit there after merge
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: restore priority color on PBI filter pill
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(ST-902): add setActiveProduct + clearActiveProduct server actions
- actions/active-product.ts: setActiveProductAction validates access via
productAccessFilter, rejects archived products and demo users
- archiveProductAction: clears active_product_id for all affected users in transaction
- removeProductMemberAction: clears active_product_id for removed member
- leaveProductAction: clears active_product_id for leaving user
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(ST-903): load active product in layout, replace cookie with DB lookup in solo
- layout.tsx: fetch active_product_id, resolve product, clear stale ref server-side
- NavBar: add activeProduct prop (rendering changes in ST-904)
- solo/page.tsx: redirect via user.active_product_id instead of lastProductId cookie
- proxy.ts: remove lastProductId cookie logic
- lib/cookies.ts: deleted (no longer used)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(ST-904): split NavBar into 5 tabs with disabled-states and product-switcher dropdown
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(ST-905): add Activeer button per product row in dashboard and product header
* feat(ST-906): redirect to dashboard with toast when active product becomes inaccessible
* feat(ST-907): tests for active-product actions and functional spec update for M9
* docs(M9): add implementation plan document and link from backlog
* feat: active PB indicator, Maak actief button and new product link in settings
* feat: apply priority-color card style to sprint story rows
* fix: move add-to-sprint click from entire card to + Toevoegen button
* feat: apply priority-color card style to sprint task rows
* fix(sprint-backlog): prevent text selection on PBI collapse button
* chore: bump version to 0.4.0 (M9 active product backlog)
* fix(landing): align logged-in nav left to match app NavBar
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* 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>
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>
* 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>
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>
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>
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>
- 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>
- 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>
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>
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>
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>
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>
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>
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>
- 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>
- 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>
- 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>
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>
- 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>
- 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>
- 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>
- 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>