/** * GET /api/workspaces/[slug]/apps — list Coolify apps in this workspace * * Auth: session OR `Bearer vibn_sk_...`. The workspace's * `coolify_project_uuid` acts as the tenant boundary — any app whose * Coolify project uuid doesn't match is filtered out even if the * token issuer accidentally had wider reach. */ import { NextResponse } from 'next/server'; import { requireWorkspacePrincipal } from '@/lib/auth/workspace-auth'; import { listApplicationsInProject, projectUuidOf } from '@/lib/coolify'; export async function GET( request: Request, { params }: { params: Promise<{ slug: string }> } ) { const { slug } = await params; const principal = await requireWorkspacePrincipal(request, { targetSlug: slug }); if (principal instanceof NextResponse) return principal; const ws = principal.workspace; if (!ws.coolify_project_uuid) { return NextResponse.json( { error: 'Workspace has no Coolify project yet', apps: [] }, { status: 503 } ); } try { const apps = await listApplicationsInProject(ws.coolify_project_uuid); return NextResponse.json({ workspace: { slug: ws.slug, coolifyProjectUuid: ws.coolify_project_uuid }, apps: apps.map(a => ({ uuid: a.uuid, name: a.name, status: a.status, fqdn: a.fqdn ?? null, gitRepository: a.git_repository ?? null, gitBranch: a.git_branch ?? null, projectUuid: projectUuidOf(a), })), }); } catch (err) { return NextResponse.json( { error: 'Coolify request failed', details: err instanceof Error ? err.message : String(err) }, { status: 502 } ); } }