docs: sync data-model, glossary en specs met huidig schema (#164)

Brengt de docs gelijk met de werkelijkheid na PBI-46/47/50/58/59/61/63
en M12. Belangrijkste fixes:

- data-model.md herschreven naar prisma/schema.prisma: nieuwe entiteiten
  (Idea, IdeaLog, IdeaProduct, UserQuestion, ClaudeQuestion, ClaudeJob,
  SprintRun, SprintTaskExecution, ClaudeWorker, LoginPairing,
  PushSubscription, ModelPrice, ProductMember), nieuwe enums
  (FAILED/EXCLUDED, OPEN/CLOSED/ARCHIVED, ADMIN, etc.) en codes
  (PBI/ST/T/SP-N) toegevoegd; verwijderde todos-tabel verwijderd.
- glossary.md: Sprint zonder "max 1 actief" (PBI-63), Story/Task incl.
  FAILED/EXCLUDED, Todo verwijderd, Idea/SprintRun/ClaudeJob/
  verify_result toegevoegd.
- project-structure.md: app/(app)/todos vervangen door
  ideas/insights/jobs/manual/admin/solo; api-tree volledig.
- overview.md: "geen realtime in v1" en Docker-rationale herschreven —
  Postgres LISTEN/NOTIFY + SSE, claude_jobs als queue, opt-in
  Docker-deploy-flow.
- functional.md: F-08 Todo-lijst -> Ideeen-laag, F-09 multi-sprint,
  F-10 Task-status incl. FAILED/EXCLUDED, F-11 endpoint-lijst,
  navigatiestructuur, datamodel-schets en Flow 3 bijgewerkt.
- README.md API-tabel: /api/todos weg, ideas/jobs/users/profile/health
  toegevoegd, kort over realtime/auth-pair/internal/cron.
- patterns + mcp-integration runbook: Todo-/ACTIVE-references vervangen
  door Idea/OPEN; create_todo MCP-tool note over verwijdering.

Linkcheck groen (105 files), INDEX hergegenereerd (98 docs).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Janpeter Visser 2026-05-08 08:16:44 +02:00 committed by GitHub
parent 3842c05ae9
commit f7464db837
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 544 additions and 424 deletions

View file

@ -3,13 +3,13 @@ title: "Entity Dialog"
status: active
audience: [ai-agent, contributor]
language: nl
last_updated: 2026-05-03
last_updated: 2026-05-08
when_to_read: "Before building any create/edit/detail dialog component."
---
# Pattern — Entity Dialog
Deze pagina is **bindend** voor elke create/edit/detail-dialog in Scrum4Me, ongeacht het achterliggende dataobject (PBI, Story, Task, Todo, Sprint, Product, User, of toekomstige entiteiten). Een nieuwe dialog die hier niet aan voldoet, hoort niet gemerged te worden.
Deze pagina is **bindend** voor elke create/edit/detail-dialog in Scrum4Me, ongeacht het achterliggende dataobject (PBI, Story, Task, Idea, Sprint, Product, User, of toekomstige entiteiten). Een nieuwe dialog die hier niet aan voldoet, hoort niet gemerged te worden.
> **Doel:** elke dialog voelt identiek aan voor de gebruiker, hergebruikt dezelfde primitives, en heeft de drielaagse demo-policy + auth-scoping standaard ingebakken.

View file

@ -3,7 +3,7 @@ title: "Proxy (route protection)"
status: active
audience: [ai-agent, contributor]
language: nl
last_updated: 2026-05-03
last_updated: 2026-05-08
when_to_read: "When adding or modifying route-level access control in proxy.ts."
---
@ -17,7 +17,16 @@ import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { sessionOptions } from '@/lib/session'
const protectedRoutes = ['/dashboard', '/products', '/todos', '/settings']
const protectedRoutes = [
'/dashboard',
'/products',
'/ideas',
'/solo',
'/jobs',
'/insights',
'/manual',
'/settings',
]
const authRoutes = ['/login', '/register']
export function proxy(request: NextRequest) {

View file

@ -3,7 +3,7 @@ title: "Route Handler (REST API)"
status: active
audience: [ai-agent, contributor]
language: nl
last_updated: 2026-05-03
last_updated: 2026-05-08
when_to_read: "When writing a new Next.js route handler (GET/POST/PATCH/DELETE)."
---
@ -59,7 +59,7 @@ export async function GET(
const { id } = await params
const sprint = await prisma.sprint.findFirst({
where: { product_id: id, status: 'ACTIVE', product: productAccessFilter(auth.userId) },
where: { product_id: id, status: 'OPEN', product: productAccessFilter(auth.userId) },
})
if (!sprint) {
return Response.json({ error: 'Geen actieve Sprint gevonden' }, { status: 404 })
@ -91,13 +91,16 @@ export async function GET(
| Methode | Endpoint | Doel |
|---|---|---|
| GET | `/api/health` | Liveness; `?db=1` voor DB-ping (geen auth) |
| GET | `/api/products` | Actieve producten ophalen |
| GET | `/api/products/:id/next-story` | Hoogst geprioriteerde open story |
| GET | `/api/products/:id/claude-context` | Bundled MCP-context |
| GET | `/api/sprints/:id/tasks?limit=10` | Eerste N taken van de Sprint |
| PATCH | `/api/stories/:id/tasks/reorder` | Taakvolgorde aanpassen |
| POST | `/api/stories/:id/log` | Plan / testresultaat / commit vastleggen |
| PATCH | `/api/tasks/:id` | Taakstatus bijwerken |
| POST | `/api/todos` | Todo aanmaken |
| PATCH | `/api/tasks/:id` | Taakstatus / `implementation_plan` bijwerken |
| GET / POST | `/api/ideas`, `GET / PATCH /api/ideas/:id` | Idea CRUD (vervangt voormalig `/api/todos`) |
| GET | `/api/jobs/:id/sub-tasks` | `sprint_task_executions` van een SPRINT_IMPLEMENTATION-job |
## Security-invarianten

View file

@ -3,7 +3,7 @@ title: "Server Action"
status: active
audience: [ai-agent, contributor]
language: nl
last_updated: 2026-05-03
last_updated: 2026-05-08
when_to_read: "When writing a new server action with auth and Zod validation."
---
@ -66,7 +66,7 @@ export async function createPbi(formData: FormData) {
- Controleer auth en `session.isDemo` voordat er geschreven wordt.
- Gebruik `productAccessFilter(userId)` voor resources waar eigenaar en gekoppelde Developer beide toegang hebben.
- Gebruik eigenaar-only filters (`user_id: session.userId`) alleen voor eigenaarsacties zoals product archiveren, teamleden beheren of persoonlijke todos.
- Gebruik eigenaar-only filters (`user_id: session.userId`) alleen voor eigenaarsacties zoals product archiveren, teamleden beheren of persoonlijke ideas.
- Vertrouw nooit losse client-ID's. Als een action meerdere IDs ontvangt, haal ze eerst op met `id in (...)` plus de parent-scope en weiger de operatie als het aantal gevonden records niet exact gelijk is.
- Weiger dubbele IDs in reorder-lijsten of beslissingsobjecten.
- Leid denormalized foreign keys af uit de database-parent. Voorbeeld: gebruik `pbi.product_id` bij story creation, niet `formData.get('productId')`.