diff --git a/docs/scrum4me-architecture.md b/docs/scrum4me-architecture.md index 9d74aec..03f1f06 100644 --- a/docs/scrum4me-architecture.md +++ b/docs/scrum4me-architecture.md @@ -7,7 +7,7 @@ ## Architectuursamenvatting -Scrum4Me is een desktop-first Next.js 15 webapplicatie die server-side wordt gerenderd en gedeployed op Vercel. De database is PostgreSQL via Neon, aangestuurd via Prisma v7. Authenticatie is custom username/password via iron-session — geen externe auth-provider, geen e-mail. De REST API voor Claude Code-integratie loopt via Next.js Route Handlers, beveiligd met API-tokens. Drag-and-drop in de planningsschermen wordt afgehandeld door dnd-kit. +Scrum4Me is een desktop-first Next.js 16 webapplicatie die server-side wordt gerenderd en gedeployed op Vercel. De database is PostgreSQL via Neon, aangestuurd via Prisma v7. Authenticatie is custom username/password via iron-session — geen externe auth-provider, geen e-mail. De REST API voor Claude Code-integratie loopt via Next.js Route Handlers, beveiligd met API-tokens. Drag-and-drop in de planningsschermen wordt afgehandeld door dnd-kit. --- @@ -15,10 +15,10 @@ Scrum4Me is een desktop-first Next.js 15 webapplicatie die server-side wordt ger | Laag | Technologie | Rationale | |---|---|---| -| Frontend framework | Next.js 15 (App Router) | Stabiel, wijdverbreid, naadloze Vercel-deployment; SSR vereist voor auth-cookie-management | -| UI runtime | React 19 | Standaard bij Next.js 15; brengt `useActionState`, `useFormStatus` en de React Compiler (experimenteel) mee — minder boilerplate bij Server Actions | +| Frontend framework | Next.js 16 (App Router) | Stabiel, wijdverbreid, naadloze Vercel-deployment; SSR vereist voor auth-cookie-management | +| UI runtime | React 19 | Standaard bij Next.js 16; brengt `useActionState`, `useFormStatus` en de React Compiler (experimenteel) mee — minder boilerplate bij Server Actions | | Taal | TypeScript (strict) | Type-veiligheid is essentieel voor een solo developer zonder reviewlaag; vangt datamodel-mismatches vroeg | -| Client state | Zustand | Minimale boilerplate voor ephemere UI-staat (selectie, optimistische drag-and-drop volgorde); leeft naast Server Components zonder conflict; eenvoudig uitbreidbaar naar v2 teamgebruik | +| Client state | Zustand | Minimale boilerplate voor ephemere UI-staat (selectie, optimistische drag-and-drop volgorde); leeft naast Server Components zonder conflict | | Styling | Tailwind CSS + shadcn/ui | Snelle iteratie; toegankelijke componentprimitieven; desktop-first layouts goed ondersteund | | Database (cloud) | PostgreSQL via Neon | Serverless Postgres, gratis tier voldoende voor MVP; native PostgreSQL zonder vendor lock-in | | ORM | Prisma v7 | Type-safe queries; PostgreSQL via adapter; migraties zijn deterministisch | @@ -192,6 +192,7 @@ Scrum4Me is een desktop-first Next.js 15 webapplicatie die server-side wordt ger | sprint_id | String | FK → sprints, nullable | Denormalisatie voor snellere queries | | title | String | not null, max 200 | | | description | String | nullable, max 1000 | | +| implementation_plan | String | nullable | Opgeslagen door Claude Code MCP via `PATCH /api/tasks/:id` | | priority | Int | 1–4, not null | | | sort_order | Float | not null | | | status | Enum | TO_DO \| IN_PROGRESS \| DONE | | @@ -219,6 +220,22 @@ Scrum4Me is een desktop-first Next.js 15 webapplicatie die server-side wordt ger --- +### `product_members` + +| Kolom | Type | Constraints | Noten | +|---|---|---|---| +| id | String (cuid) | PK | | +| product_id | String | FK → products (cascade delete) | | +| user_id | String | FK → users (cascade delete) | | +| created_at | DateTime | default now() | | + +**Indexes:** `(user_id)` — opzoeken van producten waarbij een gebruiker lid is +**Constraint:** unique `(product_id, user_id)` — één lidmaatschap per gebruiker per product + +Koppelt Developer-gebruikers aan een product backlog. De eigenaar (`products.user_id`) heeft altijd volledige toegang; via `product_members` kunnen aanvullende Developers leesrechten en schrijfrechten op stories, taken en sprints van dat product krijgen. Rollen worden niet opgeslagen in deze tabel — dat doet `user_roles`. Een gebruiker kan alleen worden toegevoegd als hij/zij de rol `DEVELOPER` heeft. + +--- + ## Prisma Schema (excerpt) ```prisma @@ -265,16 +282,17 @@ enum SprintStatus { } model User { - id String @id @default(cuid()) - username String @unique - password_hash String - is_demo Boolean @default(false) - created_at DateTime @default(now()) - updated_at DateTime @updatedAt - roles UserRole[] - api_tokens ApiToken[] - products Product[] - todos Todo[] + id String @id @default(cuid()) + username String @unique + password_hash String + is_demo Boolean @default(false) + created_at DateTime @default(now()) + updated_at DateTime @updatedAt + roles UserRole[] + api_tokens ApiToken[] + products Product[] + todos Todo[] + product_members ProductMember[] } model UserRole { @@ -299,19 +317,21 @@ model ApiToken { } model Product { - id String @id @default(cuid()) - user User @relation(fields: [user_id], references: [id], onDelete: Cascade) + id String @id @default(cuid()) + user User @relation(fields: [user_id], references: [id], onDelete: Cascade) user_id String name String description String? repo_url String? definition_of_done String - archived Boolean @default(false) - created_at DateTime @default(now()) - updated_at DateTime @updatedAt + archived Boolean @default(false) + created_at DateTime @default(now()) + updated_at DateTime @updatedAt pbis Pbi[] sprints Sprint[] stories Story[] + todos Todo[] + members ProductMember[] @@unique([user_id, name]) @@index([user_id, archived]) @@ -385,18 +405,19 @@ model Sprint { } model Task { - id String @id @default(cuid()) - story Story @relation(fields: [story_id], references: [id], onDelete: Cascade) - story_id String - sprint Sprint? @relation(fields: [sprint_id], references: [id]) - sprint_id String? - title String - description String? - priority Int - sort_order Float - status TaskStatus @default(TO_DO) - created_at DateTime @default(now()) - updated_at DateTime @updatedAt + id String @id @default(cuid()) + story Story @relation(fields: [story_id], references: [id], onDelete: Cascade) + story_id String + sprint Sprint? @relation(fields: [sprint_id], references: [id]) + sprint_id String? + title String + description String? + implementation_plan String? + priority Int + sort_order Float + status TaskStatus @default(TO_DO) + created_at DateTime @default(now()) + updated_at DateTime @updatedAt @@index([story_id, priority, sort_order]) @@index([sprint_id, status]) @@ -417,6 +438,19 @@ model Todo { @@index([user_id, done, archived]) @@index([user_id, product_id]) } + +model ProductMember { + id String @id @default(cuid()) + product Product @relation(fields: [product_id], references: [id], onDelete: Cascade) + product_id String + user User @relation(fields: [user_id], references: [id], onDelete: Cascade) + user_id String + created_at DateTime @default(now()) + + @@unique([product_id, user_id]) + @@index([user_id]) + @@map("product_members") +} ``` --- @@ -488,12 +522,15 @@ scrum4me/ │ ├── split-pane/ # Gesplitst scherm component │ ├── backlog/ # PBI- en story-componenten │ ├── sprint/ # Sprint-componenten +│ ├── products/ # ProductForm, TeamManager, ArchiveProductButton +│ ├── settings/ # RoleManager, LeaveProductButton │ └── dnd/ # dnd-kit wrappers ├── lib/ │ ├── prisma.ts # Prisma Client singleton │ ├── session.ts # iron-session configuratie │ ├── auth.ts # login/register/token helpers │ ├── api-auth.ts # Bearer token middleware voor API +│ ├── product-access.ts # productAccessFilter helper (eigenaar of teamlid) │ └── env.ts # Zod-gevalideerde env vars ├── stores/ # Zustand stores │ ├── planner-store.ts # Optimistische drag-and-drop volgorde diff --git a/docs/scrum4me-backlog.md b/docs/scrum4me-backlog.md index f04d89a..cecd8a3 100644 --- a/docs/scrum4me-backlog.md +++ b/docs/scrum4me-backlog.md @@ -330,7 +330,7 @@ De MVP is klaar wanneer Lars — de primaire persona — de volledige cyclus kan ## v2 Backlog (na MVP) -- [ ] Meerdere gebruikers per Scrum Team — uitgebreide auth, rol-gebaseerde permissies, uitnodigingsflow +- [ ] 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 diff --git a/docs/scrum4me-functional-spec.md b/docs/scrum4me-functional-spec.md index 4b0e714..7605ae2 100644 --- a/docs/scrum4me-functional-spec.md +++ b/docs/scrum4me-functional-spec.md @@ -7,13 +7,13 @@ ## MVP-scopeverklaring -v1 is een single-user desktop-first fullstack webapplicatie waarmee een solo developer of klein Scrum Team meerdere softwareprojecten hiërarchisch kan plannen (product → PBI → story → taak), Sprints kan beheren via gesplitste schermen met drag-and-drop, en Claude Code kan integreren voor geautomatiseerde implementatieflows waarbij elk resultaat wordt vastgelegd in de story. De app is deployable op Vercel + Neon én volledig lokaal draaibaar. +v1 is een desktop-first fullstack webapplicatie waarmee een solo developer of klein Scrum Team meerdere softwareprojecten hiërarchisch kan plannen (product → PBI → story → taak), Sprints kan beheren via gesplitste schermen met drag-and-drop, en Claude Code kan integreren voor geautomatiseerde implementatieflows waarbij elk resultaat wordt vastgelegd in de story. Een Product Owner kan Developers (via gebruikersnaam) aan een product backlog koppelen; zij krijgen dan schrijfrechten op stories, taken en sprints van dat product. De app is deployable op Vercel + Neon én volledig lokaal draaibaar. ## Expliciet buiten scope voor v1 -- Meerdere gebruikers per Scrum Team — datastructuur is voorbereid, UI en permissies komen in v2 +- Uitnodigingsflow voor teams — Developers toevoegen via gebruikersnaam is beschikbaar; e-mailuitnodiging of link-gebaseerde onboarding komt in v2 - E-mailverificatie bij registratie — gebruikersnaam/wachtwoord volstaat voor v1 -- Daily Scrum, Sprint Review en Sprint Retrospective schermen — v2 zodra teamgebruik mogelijk is +- Daily Scrum, Sprint Review en Sprint Retrospective schermen — v2 - Automatische statusupdate van stories na commit — handmatige update via UI in v1 - Tijdregistratie, urenverantwoording en burndown-charts — buiten positionering - Integratie met externe tools (GitHub Issues, Linear, Jira) — v2 @@ -60,14 +60,14 @@ Gebruikers kunnen een account aanmaken en inloggen met gebruikersnaam en wachtwo **Persona:** Remi (v2), Lars en Dina (impliciet) **Omschrijving:** -Een gebruiker kan bij registratie of in instellingen één of meerdere Scrum-rollen aannemen: Product Owner, Scrum Master, Developer. In v1 heeft dit geen effect op zichtbare functionaliteit maar de datastructuur ondersteunt rolscheiding voor v2-teamgebruik. +Een gebruiker kan bij registratie of in instellingen één of meerdere Scrum-rollen aannemen: Product Owner, Scrum Master, Developer. De rol Developer is relevant voor teambeheer: alleen gebruikers met de rol Developer kunnen aan een product backlog worden gekoppeld door de eigenaar. **Acceptatiecriteria:** - [ ] Gebruiker kan bij registratie of achteraf in instellingen rollen selecteren - [ ] Minimaal één rol is verplicht - [ ] Alle drie de rollen tegelijk zijn toegestaan - [ ] Geselecteerde rollen zijn zichtbaar in de profielbalk -- [ ] Rolkeuze heeft in v1 geen effect op zichtbare functionaliteit +- [ ] Alleen gebruikers met de rol Developer kunnen als teamlid aan een product backlog worden gekoppeld - [ ] Demo-gebruiker heeft een vaste rol (Developer) die niet gewijzigd kan worden **Data:** @@ -386,7 +386,7 @@ De app is deployable op Vercel + Neon PostgreSQL en lokaal draaibaar met een Neo /products/:id/sprint (Sprint Backlog — gesplitst scherm) /products/:id/sprint/planning (Sprint Planning — gesplitst scherm) /todos (todo-lijst) -/settings (profiel, rollen, API-tokens) +/settings (profiel, rollen, mijn teams, API-tokens) /settings/tokens (API-tokenbeheer) ``` @@ -406,6 +406,7 @@ De app is deployable op Vercel + Neon PostgreSQL en lokaal draaibaar met een Neo | `sprints` | id, product_id, sprint_goal, status (ACTIVE / COMPLETED), created_at, completed_at? | Max. 1 actieve Sprint per product | | `tasks` | id, story_id, sprint_id, title, description, implementation_plan?, priority, sort_order, status | Status: TO_DO / IN_PROGRESS / DONE; implementation_plan door MCP | | `todos` | id, user_id, product_id, title, done, archived, created_at | Gekoppeld aan product backlog; verplicht in UI en API | +| `product_members` | id, product_id, user_id, created_at | Many-to-many; alleen Developers; eigenaar via products.user_id | ---