From ee9cb2a570abf78cd825f5aac970125698f2d2ad Mon Sep 17 00:00:00 2001 From: Madhura68 Date: Sun, 26 Apr 2026 21:58:53 +0200 Subject: [PATCH] feat(ST-513): add GET /api/products/:id/claude-context bundled endpoint Co-Authored-By: Claude Opus 4.7 (1M context) --- app/api/products/[id]/claude-context/route.ts | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 app/api/products/[id]/claude-context/route.ts diff --git a/app/api/products/[id]/claude-context/route.ts b/app/api/products/[id]/claude-context/route.ts new file mode 100644 index 0000000..5387a0f --- /dev/null +++ b/app/api/products/[id]/claude-context/route.ts @@ -0,0 +1,94 @@ +import { authenticateApiRequest } from '@/lib/api-auth' +import { prisma } from '@/lib/prisma' +import { productAccessFilter } from '@/lib/product-access' +import { storyStatusToApi, taskStatusToApi } from '@/lib/task-status' + +export async function GET( + request: Request, + { params }: { params: Promise<{ id: string }> }, +) { + const auth = await authenticateApiRequest(request) + if ('error' in auth) { + return Response.json({ error: auth.error }, { status: auth.status }) + } + + const { id } = await params + + const product = await prisma.product.findFirst({ + where: { id, ...productAccessFilter(auth.userId) }, + select: { + id: true, + code: true, + name: true, + description: true, + repo_url: true, + definition_of_done: true, + }, + }) + if (!product) { + return Response.json({ error: 'Product niet gevonden' }, { status: 404 }) + } + + const [activeSprint, openTodos] = await Promise.all([ + prisma.sprint.findFirst({ + where: { product_id: id, status: 'ACTIVE' }, + select: { id: true, sprint_goal: true, status: true }, + }), + prisma.todo.findMany({ + where: { user_id: auth.userId, product_id: id, done: false, archived: false }, + select: { id: true, title: true, description: true, created_at: true }, + orderBy: { created_at: 'asc' }, + take: 50, + }), + ]) + + let nextStoryPayload: unknown = null + if (activeSprint) { + const story = await prisma.story.findFirst({ + where: { sprint_id: activeSprint.id, status: 'IN_SPRINT' }, + orderBy: [{ priority: 'asc' }, { sort_order: 'asc' }], + include: { + tasks: { + orderBy: { sort_order: 'asc' }, + select: { + id: true, + title: true, + description: true, + implementation_plan: true, + priority: true, + sort_order: true, + status: true, + }, + }, + }, + }) + if (story) { + nextStoryPayload = { + id: story.id, + code: story.code, + title: story.title, + description: story.description, + acceptance_criteria: story.acceptance_criteria, + priority: story.priority, + status: storyStatusToApi(story.status), + tasks: story.tasks.map((t, idx) => ({ + id: t.id, + code: story.code ? `${story.code}.${idx + 1}` : null, + title: t.title, + description: t.description, + implementation_plan: t.implementation_plan, + priority: t.priority, + sort_order: t.sort_order, + status: taskStatusToApi(t.status), + })), + } + } + } + + return Response.json({ + product, + active_sprint: activeSprint, + next_story: nextStoryPayload, + open_todos: openTodos, + }) +}