docs: sync data-model, glossary en specs met huidig schema
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:
parent
a4a7ef9b8b
commit
3ad85d0167
12 changed files with 544 additions and 424 deletions
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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')`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue