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>
23 KiB
title: "Data Model & Prisma Schema" status: active audience: [maintainer, contributor] language: nl last_updated: 2026-05-08 related: auth-and-sessions.md
Datamodel
Bron van waarheid is
prisma/schema.prisma; dit document samenvat de tabellen en sleutelinvarianten. Bij twijfel wint het schema.
users
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| username | String | unique, not null, min 3 | Inlognaam |
| String? | unique | Optioneel; gebruikt voor wachtwoord-reset-flows | |
| password_hash | String | not null | bcrypt hash (cost factor 12) |
| is_demo | Boolean | default false | Demo-gebruiker heeft read-only rechten |
| bio | String? | max 160 | Korte profielomschrijving |
| bio_detail | String? | max 2000 | Uitgebreide profielbeschrijving |
| must_reset_password | Boolean | default false | Forceert wachtwoord-reset bij volgende login |
| avatar_data | Bytes? | Profielfoto als WebP bytea (max 700×700) | |
| active_product_id | String? | FK → products (SetNull) | Persistente actieve PB-keuze (M9) |
| idea_code_counter | Int | default 0 | Sequentiële teller voor user-scoped idea-codes |
| min_quota_pct | Int | default 20 | Worker stand-by-drempel (M13 quota-check) |
| created_at | DateTime | default now() | |
| updated_at | DateTime | auto-update | Cache-buster voor avatar-URL |
Indexes: username (unique), email (unique), active_product_id
user_roles
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| user_id | String | FK → users (Cascade) | |
| role | Enum | PRODUCT_OWNER | SCRUM_MASTER | DEVELOPER | ADMIN |
Constraint: unique (user_id, role)
api_tokens
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| user_id | String | FK → users (Cascade) | |
| token_hash | String | unique, not null | SHA-256 hash van het token |
| label | String? | Bijv. "Claude Code — laptop" | |
| created_at | DateTime | default now() | |
| revoked_at | DateTime? | Null = actief |
Indexes: token_hash (unique). Eén token kan max. één claude_workers-record hebben.
products
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| user_id | String | FK → users (Cascade) | Eigenaar |
| name | String | not null | Uniek per gebruiker |
| code | String? | max 30 | Optionele afkorting; uniek per gebruiker als gezet |
| description | String? | ||
| repo_url | String? | Gevalideerde URL | |
| definition_of_done | String | not null | Vaste instelling per product |
| auto_pr | Boolean | default false | Automatische PR creëren na sprint-completion |
| pr_strategy | Enum | SPRINT | STORY | SPRINT_BATCH, default SPRINT |
Granulariteit voor auto-PR |
| archived | Boolean | default false | |
| created_at | DateTime | default now() | |
| updated_at | DateTime | auto-update |
Indexes: (user_id, archived) — standaard query filtert op actieve producten
Constraints: unique (user_id, name), unique (user_id, code)
pbis
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| product_id | String | FK → products (Cascade) | |
| code | String | max 30, not null | Verplicht; auto-gegenereerd of handmatig |
| title | String | not null | |
| description | String? | ||
| priority | Int | 1–4 | 1 = Kritiek, 4 = Laag |
| sort_order | Float | not null | Float voor volgorde tussen items zonder renummering |
| status | Enum | READY | BLOCKED | FAILED | DONE, default READY |
Auto-promotie naar DONE bij sprint-close |
| pr_url | String? | URL van de PR die deze PBI dekt (PBI-strategie) | |
| pr_merged_at | DateTime? | Gezet wanneer de PR daadwerkelijk gemerged is | |
| created_at | DateTime | default now() | |
| updated_at | DateTime | auto-update |
Indexes: (product_id, priority, sort_order), (product_id, status)
Constraint: unique (product_id, code)
Cascade-regel (sprint-close): wanneer een Sprint wordt afgerond via completeSprintAction en alle stories van een PBI eindigen op DONE, zet diezelfde transactie de PBI-status op DONE. Promotie alléén — een DONE-PBI wordt nooit automatisch teruggezet. Stories die niet in deze Sprint zaten worden meegerekend op hun huidige DB-status. Een PBI zonder stories blijft READY.
stories
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| pbi_id | String | FK → pbis (Cascade) | |
| product_id | String | FK → products | Denormalisatie voor snellere queries |
| sprint_id | String? | FK → sprints | Null = in Product Backlog |
| assignee_id | String? | FK → users (SetNull) | Story-claim op het Solo-bord |
| code | String | max 30, not null | Auto-gegenereerd of handmatig |
| title | String | not null | |
| description | String? | ||
| acceptance_criteria | String? | ||
| priority | Int | 1–4 | |
| sort_order | Float | not null | |
| status | Enum | OPEN | IN_SPRINT | DONE | FAILED, default OPEN |
|
| created_at | DateTime | default now() | |
| updated_at | DateTime | auto-update |
Indexes: (pbi_id, priority, sort_order), (sprint_id, sort_order), (product_id, status), (sprint_id, assignee_id)
Constraint: unique (product_id, code)
Auto-promotie/demotie via task-status: zodra alle tasks van een story op DONE staan en de story-status nog niet DONE is, promoot dezelfde transactie de story naar DONE. Wordt een task van een DONE-story heropend, dan demoot de story terug naar IN_SPRINT — niet naar OPEN (dat zou "terug in productbacklog" betekenen, een sprint-management-actie). Logica zit in lib/tasks-status-update.ts en wordt aangeroepen door alle drie de task-status-write-paden (updateTaskStatusAction, saveTask edit-mode, REST PATCH /api/tasks/[id]).
story_logs
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| story_id | String | FK → stories (Cascade) | |
| type | Enum | IMPLEMENTATION_PLAN | TEST_RESULT | COMMIT |
|
| content | String | not null | |
| status | Enum | PASSED | FAILED? |
Alleen bij type TEST_RESULT |
| commit_hash | String? | Alleen bij type COMMIT |
|
| commit_message | String? | Alleen bij type COMMIT |
|
| metadata | Json? | Vrije bag voor bron-info (bv. agent, model_id) | |
| created_at | DateTime | default now() |
Indexes: (story_id, created_at)
sprints
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| product_id | String | FK → products (Cascade) | |
| code | String | max 30, not null | Auto-gegenereerd SP-N per product (PBI-59) |
| sprint_goal | String | not null | |
| status | Enum | OPEN | CLOSED | ARCHIVED | FAILED, default OPEN |
|
| start_date | Date? | Optionele planningsmetadata | |
| end_date | Date? | Optionele planningsmetadata | |
| created_at | DateTime | default now() | |
| completed_at | DateTime? | Wordt gezet bij overgang naar CLOSED |
Indexes: (product_id, status)
Constraint: unique (product_id, code)
Eén product, meerdere sprints (PBI-63): een product kan tegelijk meer dan één sprint hebben. OPEN is geen exclusieve status; de sprint-switcher in de product-header laat de gebruiker tussen sprints kiezen. Stories in IN_SPRINT linken via sprint_id naar één specifieke sprint.
sprint_runs
Eén sprint_runs-record per uitvoering van de SPRINT_IMPLEMENTATION-flow (PBI-46/47/50). Houdt status, branch en chained retries bij wanneer een run is gepauzeerd of mislukt.
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| sprint_id | String | FK → sprints (Cascade) | |
| started_by_id | String | FK → users | Wie de run startte |
| status | Enum | QUEUED | RUNNING | PAUSED | DONE | FAILED | CANCELLED |
|
| pr_strategy | Enum | SPRINT | STORY | SPRINT_BATCH |
Snapshot van de strategie bij start |
| branch | String? | Werkbranch voor de run | |
| pr_url | String? | ||
| started_at / finished_at | DateTime? | ||
| failure_reason | String? | Vrij tekstveld bij FAILED/CANCELLED | |
| failed_task_id | String? | FK → tasks (SetNull) | Eerste task die de run brak (cascade-FAIL) |
| pause_context | Json? | Gevalideerd door Zod (lib/sprint-run/pause-context.ts) |
|
| previous_run_id | String? | unique, FK → sprint_runs (SetNull) | Chain naar een eerdere run |
| created_at / updated_at | DateTime |
Indexes: (sprint_id, status), (started_by_id, status)
tasks
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| story_id | String | FK → stories (Cascade) | |
| product_id | String | FK → products (Cascade) | Denormalisatie voor product-scoped queries |
| sprint_id | String? | FK → sprints | Denormalisatie; geërfd van story bij sprint-toevoeging |
| code | String | max 30, not null | Auto-gegenereerd T-N per product |
| title | String | not null | |
| description | String? | ||
| implementation_plan | String? | Opgeslagen via Server Action of PATCH /api/tasks/:id |
|
| priority | Int | 1–4 | |
| sort_order | Float | not null | |
| status | Enum | TO_DO | IN_PROGRESS | REVIEW | DONE | FAILED | EXCLUDED, default TO_DO |
EXCLUDED slaat verify-skip op tijdens een sprint-run |
| verify_only | Boolean | default false | Run-mode: alleen verifiëren, niet implementeren |
| verify_required | Enum | ALIGNED | ALIGNED_OR_PARTIAL | ANY, default ALIGNED_OR_PARTIAL |
Drempel waarop een job's verify_result als acceptabel telt |
| repo_url | String? | Optionele override van product.repo_url voor tasks die in een andere repo wonen |
|
| created_at | DateTime | default now() | |
| updated_at | DateTime | auto-update |
Indexes: (story_id, priority, sort_order), (sprint_id, status), (product_id)
Constraint: unique (product_id, code) — code blijft stabiel bij re-parenting (Jira-stijl)
claude_jobs
Job-queue waarop wait_for_job (MCP) atomisch claimt via FOR UPDATE SKIP LOCKED. Eén rij per task-implementatie, idea-grill, idea-make-plan, plan-chat of sprint-run.
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| user_id | String | FK → users (Cascade) | |
| product_id | String | FK → products (Cascade) | |
| task_id | String? | FK → tasks (Cascade) | Bij TASK_IMPLEMENTATION of SPRINT_IMPLEMENTATION |
| idea_id | String? | FK → ideas (Cascade) | Bij IDEA_GRILL / IDEA_MAKE_PLAN |
| sprint_run_id | String? | FK → sprint_runs (SetNull) | Koppel naar de bovenliggende run |
| kind | Enum | TASK_IMPLEMENTATION | IDEA_GRILL | IDEA_MAKE_PLAN | PLAN_CHAT | SPRINT_IMPLEMENTATION |
|
| status | Enum | QUEUED | CLAIMED | RUNNING | DONE | FAILED | CANCELLED | SKIPPED |
|
| claimed_by_token_id | String? | FK → api_tokens (SetNull) | Auth-koppel voor update_job_status |
| claimed_at / started_at / finished_at / pushed_at | DateTime? | Lifecycle-stempels | |
| verify_result | Enum? | ALIGNED | PARTIAL | EMPTY | DIVERGENT |
Alleen voor task-/sprint-jobs |
| model_id | String? | Anthropic model dat de agent rapporteerde | |
| input_tokens / output_tokens / cache_read_tokens / cache_write_tokens | Int? | Token-usage voor billing-overzicht | |
| plan_snapshot | String? | Bevroren plan op claim-moment | |
| base_sha / head_sha / branch / pr_url | String? | Git-context | |
| summary | String? | Vrije agent-samenvatting bij DONE | |
| error | String? | Reden bij FAILED | |
| retry_count | Int | default 0 | |
| lease_until | DateTime? | Stale-CLAIMED → terug naar QUEUED na 30 min | |
| created_at / updated_at | DateTime |
Indexes: (user_id, status), (task_id, status), (idea_id, status), (sprint_run_id, status), (status, claimed_at), (status, finished_at), (status, lease_until)
sprint_task_executions
Bevroren scope-snapshot per SPRINT_IMPLEMENTATION-claim (PBI-50). Bij claim wordt voor elke TO_DO-task in scope één PENDING-record gemaakt met implementation_plan + verify_required gesnapshot. Worker en gate werken uitsluitend op deze rows; latere wijzigingen aan Task hebben geen invloed op de lopende batch.
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| sprint_job_id | String | FK → claude_jobs (Cascade) | De parent SPRINT_IMPLEMENTATION-job |
| task_id | String | FK → tasks (Cascade) | |
| order | Int | not null | Volgorde binnen de batch |
| plan_snapshot | String (Text) | not null | Het bevroren implementation_plan |
| verify_required_snapshot | Enum | ALIGNED | ALIGNED_OR_PARTIAL | ANY |
|
| verify_only_snapshot | Boolean | default false | |
| base_sha / head_sha | String? | ||
| status | Enum | PENDING | RUNNING | DONE | FAILED | SKIPPED |
|
| verify_result | Enum? | ALIGNED | PARTIAL | EMPTY | DIVERGENT |
|
| verify_summary / skip_reason | String? (Text) | ||
| started_at / finished_at | DateTime? | ||
| created_at / updated_at | DateTime |
Constraint: unique (sprint_job_id, task_id)
Indexes: (sprint_job_id, order)
model_prices
Prijslookup voor Anthropic-modellen, gebruikt door de jobs-pagina om kosten te berekenen.
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| model_id | String | unique | Anthropic model-id (bv. claude-opus-4-7) |
| input_price_per_1m | Decimal(12,6) | USD per 1M tokens (default) | |
| output_price_per_1m | Decimal(12,6) | ||
| cache_read_price_per_1m | Decimal(12,6) | ||
| cache_write_price_per_1m | Decimal(12,6) | ||
| currency | String | default USD |
|
| created_at / updated_at | DateTime |
claude_workers
Live-presence-record per actieve agent worker. Ingevoegd bij MCP-startup, geüpdatet via worker_heartbeat (5s), opgeruimd bij SIGTERM. NavBar telt actieve workers op last_seen_at < now() - 15s.
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| user_id | String | FK → users (Cascade) | |
| token_id | String | unique, FK → api_tokens (Cascade) | Eén worker per token |
| product_id | String? | Optioneel; gerapporteerd door de agent | |
| started_at / last_seen_at | DateTime | default now() | |
| last_quota_pct | Int? | M13 pre-flight quota-check | |
| last_quota_check_at | DateTime? |
Indexes: (user_id, last_seen_at)
product_members
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 hier opgeslagen — dat doet user_roles. Een gebruiker kan alleen worden toegevoegd als hij/zij de rol DEVELOPER heeft.
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| product_id | String | FK → products (Cascade) | |
| user_id | String | FK → users (Cascade) | |
| created_at | DateTime | default now() |
Constraint: unique (product_id, user_id)
Indexes: (user_id)
ideas
Idea-entity (M12) tussen losse notitie en PBI. Een idea wordt eerst gegrilled (interactieve Q&A → grill_md), daarna gemateriaaliseerd tot een plan (plan_md) dat deterministisch geparseerd wordt naar PBI + stories + tasks. Vervangt de oude todos-tabel volledig (atomische migratie ST-1239 — todos zijn gedropt).
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| user_id | String | FK → users (Cascade) | |
| product_id | String? | FK → products (SetNull) | Primaire scope; null = unscoped capture |
| code | String | max 30, not null | Sequentieel per gebruiker via idea_code_counter |
| title | String | not null | |
| description | String? | max 4000 | Initiële tekst |
| grill_md | String? (Text) | Output van IDEA_GRILL | |
| plan_md | String? (Text) | Output van IDEA_MAKE_PLAN | |
| pbi_id | String? | unique, FK → pbis (SetNull) | Wordt gevuld na materialisatie |
| status | Enum | DRAFT | GRILLING | GRILL_FAILED | GRILLED | PLANNING | PLAN_FAILED | PLAN_READY | PLANNED, default DRAFT |
|
| archived | Boolean | default false | |
| created_at / updated_at | DateTime |
Constraint: unique (user_id, code)
Indexes: (user_id, archived, status), (user_id, product_id)
idea_products
Optionele secundaire producten waar een idea ook impact heeft.
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| idea_id | String | FK → ideas (Cascade) | |
| product_id | String | FK → products (Cascade) | |
| created_at | DateTime | default now() |
Constraint: unique (idea_id, product_id)
Indexes: (product_id)
idea_logs
Activiteitenlog per idea — soortgelijke rol als story_logs voor stories.
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| idea_id | String | FK → ideas (Cascade) | |
| type | Enum | DECISION | NOTE | GRILL_RESULT | PLAN_RESULT | STATUS_CHANGE | JOB_EVENT |
|
| content | String (Text) | not null | |
| metadata | Json? | ||
| created_at | DateTime | default now() |
Indexes: (idea_id, created_at)
user_questions
Vrije vragen die een gebruiker aan zichzelf stelt op een idea (M12). Wordt door de Idea-detail-UI ingelezen om te helpen bij het grillen.
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| idea_id | String | FK → ideas (Cascade) | |
| user_id | String | not null | Eigenaar |
| question | String (Text) | not null | |
| answer | String? (Text) | ||
| status | Enum (lowercase) | pending | answered, default pending |
|
| created_at / updated_at | DateTime |
Indexes: (idea_id, status), (user_id)
claude_questions
Persistent vraag-antwoord-kanaal van een agent (via mcp__scrum4me__ask_user_question) richting de actieve gebruiker (M11). LISTEN/NOTIFY pusht het antwoord terug naar de wachtende agent. Zie architecture/claude-question-channel.md.
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| story_id | String? | FK → stories (Cascade) | Eén van story/task/idea is verplicht |
| task_id | String? | FK → tasks (SetNull) | |
| idea_id | String? | FK → ideas (Cascade) | |
| product_id | String | FK → products (Cascade) | Gedenormaliseerd voor het SSE-filter |
| asked_by | String | FK → users | Token-houder = Claude |
| question | String (Text) | not null | |
| options | Json? | string[] voor multi-choice; null voor free-text |
|
| status | String | not null | open | answered | cancelled | expired |
| answer | String? (Text) | ||
| answered_by | String? | FK → users | |
| answered_at | DateTime? | ||
| created_at | DateTime | default now() | |
| expires_at | DateTime | not null | Default now() + 24h, ingesteld door MCP-tool |
Indexes: (story_id, status), (idea_id, status), (product_id, status), (status, expires_at)
login_pairings
QR-pairing-flow (M10). Desktop start een pairing, telefoon scant en bevestigt; daarna kan de desktop ruilen voor een sessie.
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| secret_hash | String | not null | Hash van het pairing-secret |
| desktop_token_hash | String | not null | Hash van het pre-auth desktop-token |
| status | String | not null | pending | approved | consumed | expired |
| user_id | String? | FK → users (SetNull) | Gezet bij approval |
| desktop_ua | String? | max 255 | UA-string van de desktop-aanvraag |
| desktop_ip | String? | max 45 | IP voor audit |
| created_at | DateTime | default now() | |
| expires_at | DateTime | not null | TTL voor afhandeling |
| approved_at / consumed_at | DateTime? |
Indexes: (expires_at), (status, expires_at)
push_subscriptions
Web Push subscriptions per gebruiker, voor notificaties.
| Kolom | Type | Constraints | Noten |
|---|---|---|---|
| id | String (cuid) | PK | |
| user_id | String | FK → users (Cascade) | |
| endpoint | String | unique, not null | Push-service endpoint |
| p256dh / auth | String | not null | VAPID keys |
| user_agent | String? | UA bij subscribe | |
| created_at / last_used_at | DateTime | default now() |
Indexes: (user_id)
Toegangsmodel en schrijfbeveiliging
Producttoegang is centraal gedefinieerd als:
- eigenaar:
products.user_id === gebruiker.id - teamlid:
product_membersbevat(product_id, user_id)
Code gebruikt hiervoor productAccessFilter(userId) uit lib/product-access.ts. Route Handlers en Server Actions mogen geen eigenaar-only filter (user_id) gebruiken voor product-scoped resources tenzij het expliciet om eigenaarsbeheer gaat (archiveren, teamleden beheren).
Schrijfoperaties volgen deze invarianten:
- Controleer eerst authenticatie en
session.isDemo. - Valideer input met Zod, maar behandel TypeScript types niet als runtime-beveiliging.
- Controleer de parent-resource met
productAccessFilter. - Vertrouw bulk-ID's nooit los: haal de records eerst op met
id in (...)plus de parent-scope (product_id,pbi_id,sprint_idofstory_id) en weiger de operatie als aantallen niet exact overeenkomen. - Weiger dubbele IDs in reorder- en beslissingslijsten.
- Leid denormalized foreign keys af van de database-parent (
pbi.product_id,sprint.product_id) en niet van form-data of JSON body. - Delete of update alleen nadat de resource scoped is gevonden; gebruik scoped
deleteMany/updateManywanneer een uniquedeleteanders onveilig zou zijn.
Enums (overzicht)
| Enum | Waarden |
|---|---|
Role |
PRODUCT_OWNER, SCRUM_MASTER, DEVELOPER, ADMIN |
PbiStatus |
READY, BLOCKED, FAILED, DONE |
StoryStatus |
OPEN, IN_SPRINT, DONE, FAILED |
TaskStatus |
TO_DO, IN_PROGRESS, REVIEW, DONE, FAILED, EXCLUDED |
SprintStatus |
OPEN, CLOSED, ARCHIVED, FAILED |
SprintRunStatus |
QUEUED, RUNNING, PAUSED, DONE, FAILED, CANCELLED |
PrStrategy |
SPRINT, STORY, SPRINT_BATCH |
LogType |
IMPLEMENTATION_PLAN, TEST_RESULT, COMMIT |
TestStatus |
PASSED, FAILED |
ClaudeJobStatus |
QUEUED, CLAIMED, RUNNING, DONE, FAILED, CANCELLED, SKIPPED |
ClaudeJobKind |
TASK_IMPLEMENTATION, IDEA_GRILL, IDEA_MAKE_PLAN, PLAN_CHAT, SPRINT_IMPLEMENTATION |
VerifyResult |
ALIGNED, PARTIAL, EMPTY, DIVERGENT |
VerifyRequired |
ALIGNED, ALIGNED_OR_PARTIAL, ANY |
SprintTaskExecutionStatus |
PENDING, RUNNING, DONE, FAILED, SKIPPED |
IdeaStatus |
DRAFT, GRILLING, GRILL_FAILED, GRILLED, PLANNING, PLAN_FAILED, PLAN_READY, PLANNED |
IdeaLogType |
DECISION, NOTE, GRILL_RESULT, PLAN_RESULT, STATUS_CHANGE, JOB_EVENT |
UserQuestionStatus |
pending, answered (lowercase, niet UPPER_SNAKE) |
API-grens:
TaskStatusenStoryStatusworden tussen DB (UPPER_SNAKE) en API (lowercase) vertaald vialib/task-status.ts(zie ADR-0004).
Prisma Schema
De volledige, levende definitie staat in prisma/schema.prisma. Genereer de ERD lokaal met npm run db:erd (zie README — Database). Het ERD-diagram zelf staat in docs/assets/erd.svg.