diff --git a/CLAUDE.md b/CLAUDE.md index 3cd4d1b..d9e4572 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -21,6 +21,7 @@ Lees het relevante document voordat je aan een feature begint. Nooit gokken over | `docs/scrum4me-backlog.md` | Welke task bouwen, volgorde, "done when"-criteria | | `docs/scrum4me-personas.md` | Lars (primair), Dina, Remi — gebruik bij UI-beslissingen | | `docs/scrum4me-product-backlog.md` | Historische domein-backlog (referentie); seed wordt sinds ST-004 gegenereerd uit `scrum4me-backlog.md` via `prisma/seed-data/parse-backlog.ts` | +| `docs/API.md` | REST-API contract voor Claude Code — endpoints, status-enums, foutcodes, voorbeeld-curls | | `docs/scrum4me-styling.md` | **Lees dit voor elk component** — MD3-kleuren, shadcn patronen | | `docs/agent-instruction-audit.md` | Waarom de agent-instructies zijn aangescherpt; checklist voor toekomstige wijzigingen | diff --git a/docs/API.md b/docs/API.md new file mode 100644 index 0000000..26b6c79 --- /dev/null +++ b/docs/API.md @@ -0,0 +1,282 @@ +# Scrum4Me REST API + +REST-API contract voor Claude Code en andere clients. + +## Authenticatie + +Alle endpoints behalve `GET /api/health` vereisen een Bearer-token: + +``` +Authorization: Bearer +``` + +Tokens beheer je via Instellingen → Tokens (`/settings/tokens`). Een token is gekoppeld aan één gebruiker; een demo-account-token kan lezen maar niet schrijven (`403`). + +## Status-enums + +De API gebruikt **lowercase** statussen. De database gebruikt UPPER_SNAKE; de vertaling gebeurt op de boundary. + +| Entiteit | Waarden | +|---|---| +| Task status | `todo`, `in_progress`, `review`, `done` | +| Story status | `open`, `in_sprint`, `done` | + +## Foutcodes + +| Code | Betekenis | +|---|---| +| `200` | OK | +| `201` | Created | +| `400` | Malformed body (bv. ongeldige JSON) | +| `401` | Token ontbreekt of ongeldig | +| `403` | Token heeft geen toegang (demo-account, geen lid van product) | +| `404` | Resource niet gevonden | +| `422` | Validatiefout — body is wel-gevormd maar niet acceptabel | +| `500` | Onverwachte serverfout | + +--- + +## Endpoints + +### `GET /api/health` + +Health-probe. Geen authenticatie vereist. + +**Query params:** `?db=1` voegt een DB-ping toe. + +**Response (200):** +```json +{ "status": "ok", "version": "0.3.x", "time": "2026-04-26T20:00:00Z" } +``` + +Met `?db=1`: +```json +{ "status": "ok", "version": "0.3.x", "time": "...", "database": "ok" } +``` + +`database` is `"ok"` of `"down"`. De endpoint zelf retourneert altijd `200`. + +```bash +curl https://scrum4me.app/api/health?db=1 +``` + +--- + +### `GET /api/products` + +Lijst van actieve producten waar de tokengebruiker eigenaar of lid van is. + +**Response (200):** +```json +[ + { + "id": "cmofu...", + "code": "SCRUM4ME", + "name": "Scrum4Me", + "description": "...", + "repo_url": "https://github.com/...", + "definition_of_done": "..." + } +] +``` + +```bash +curl -H "Authorization: Bearer $TOKEN" https://scrum4me.app/api/products +``` + +--- + +### `GET /api/products/:id/claude-context` + +Bundled context voor Claude Code: product, actieve sprint, volgende story (met tasks) en open todos van de tokengebruiker — in één call. + +**Response (200):** +```json +{ + "product": { "id", "code", "name", "description", "repo_url", "definition_of_done" }, + "active_sprint": { "id": "...", "sprint_goal": "...", "status": "ACTIVE" } | null, + "next_story": { + "id", "code", "title", "description", "acceptance_criteria", + "priority", "status", + "tasks": [ + { "id", "code", "title", "description", "implementation_plan", + "priority", "sort_order", "status" } + ] + } | null, + "open_todos": [ + { "id", "title", "description", "created_at" } + ] +} +``` + +`open_todos` is gelimiteerd op 50 items, gesorteerd op `created_at` asc. Demo-tokens kunnen dit endpoint lezen. + +```bash +curl -H "Authorization: Bearer $TOKEN" \ + https://scrum4me.app/api/products/$PRODUCT_ID/claude-context +``` + +--- + +### `GET /api/products/:id/next-story` + +Hoogst geprioriteerde open story in de actieve sprint. + +**Response (200):** +```json +{ + "id": "...", + "code": "ST-356", + "title": "Solo Kanban-bord met DnD en Zustand", + "description": "...", + "acceptance_criteria": "...", + "status": "in_sprint", + "tasks": [ + { + "id": "...", + "code": "ST-356.1", + "title": "Store stores/solo-store.ts", + "description": "...", + "implementation_plan": null, + "priority": 2, + "sort_order": 1, + "status": "todo" + } + ] +} +``` + +**Foutcodes:** `404` als geen actieve sprint of geen open stories. + +--- + +### `GET /api/sprints/:id/tasks` + +Lijst taken van de sprint, geordend op `(story.sort_order, task.priority, task.sort_order)`. + +**Query params:** `?limit=N` (default 10, max 50) + +**Response (200):** +```json +[ + { + "id": "...", + "code": "ST-356.1", + "title": "...", + "description": "...", + "implementation_plan": null, + "story_id": "...", + "story_code": "ST-356", + "priority": 2, + "sort_order": 1, + "status": "todo" + } +] +``` + +--- + +### `PATCH /api/stories/:id/tasks/reorder` + +Volgorde van taken binnen een story aanpassen. + +**Body:** +```json +{ "task_ids": ["task-id-a", "task-id-b", "task-id-c"] } +``` + +Alle IDs moeten bij de story horen. **Foutcodes:** `422` bij Zod-fouten of als een task_id niet tot de story behoort. + +--- + +### `PATCH /api/tasks/:id` + +Status of implementation_plan bijwerken. Minstens één van beide is verplicht. + +**Body:** +```json +{ "status": "in_progress", "implementation_plan": "..." } +``` + +**Response (200):** +```json +{ + "id": "...", + "status": "in_progress", + "implementation_plan": "..." +} +``` + +**Foutcodes:** `422` bij ongeldige body of onbekende status. `403` bij demo-token. + +--- + +### `POST /api/stories/:id/log` + +Activiteit vastleggen op een story. + +**Body — IMPLEMENTATION_PLAN:** +```json +{ + "type": "IMPLEMENTATION_PLAN", + "content": "Plan: ...", + "metadata": { "branch": "feat/x" } +} +``` + +**Body — TEST_RESULT:** +```json +{ + "type": "TEST_RESULT", + "content": "Alle tests groen", + "status": "PASSED", + "metadata": { "ci_run": "..." } +} +``` + +**Body — COMMIT:** +```json +{ + "type": "COMMIT", + "content": "Werk afgerond", + "commit_hash": "abc123", + "commit_message": "feat(ST-XXX): ...", + "metadata": { "branch": "feat/x" } +} +``` + +`metadata` is optioneel, vrij JSON-object. **Response (201):** +```json +{ "id": "...", "created_at": "..." } +``` + +--- + +### `POST /api/todos` + +Nieuwe todo voor de tokengebruiker. + +**Body:** +```json +{ + "title": "Een ding doen", + "description": "Optionele uitleg, max 2000 tekens", + "product_id": "cmof..." +} +``` + +**Response (201):** +```json +{ "id": "...", "title": "...", "description": "...", "created_at": "..." } +``` + +--- + +## Voorbeeldworkflow voor Claude Code + +1. **Probe:** `GET /api/health?db=1` — bevestig dat de service en DB bereikbaar zijn. +2. **Context:** `GET /api/products/$ID/claude-context` — haal product, sprint, volgende story en todos op in één call. +3. **Plan vastleggen:** `POST /api/stories/$STORY_ID/log` met `type: IMPLEMENTATION_PLAN`. +4. **Per task:** `PATCH /api/tasks/$TASK_ID` met `status: "in_progress"`, daarna met `status: "done"` plus eventueel `implementation_plan`. +5. **Test:** `POST /api/stories/$STORY_ID/log` met `type: TEST_RESULT` en `status: PASSED|FAILED`. +6. **Commit:** `POST /api/stories/$STORY_ID/log` met `type: COMMIT`, `commit_hash`, `commit_message`, optioneel `metadata: { branch }`.