import { NextResponse } from 'next/server'; import { z } from 'zod'; import { withAuth, withPermission } from '@/lib/api/helpers'; import { parseBody } from '@/lib/api/route-helpers'; import { errorResponse, ForbiddenError } from '@/lib/errors'; import { createCrmInvite, listCrmInvites } from '@/lib/services/crm-invite.service'; export const GET = withAuth( withPermission('admin', 'manage_users', async (_req, _ctx) => { try { const data = await listCrmInvites(); return NextResponse.json({ data }); } catch (error) { return errorResponse(error); } }), ); const createInviteSchema = z.object({ email: z.string().email(), name: z.string().min(1).max(200).optional(), isSuperAdmin: z.boolean().optional().default(false), }); export const POST = withAuth( withPermission('admin', 'manage_users', async (req, ctx) => { try { const body = await parseBody(req, createInviteSchema); // Only existing super-admins can mint super-admin invitations. The // manage_users permission is granted to port-scoped director roles, // which must not be able to elevate themselves cross-tenant by // inviting a fresh super_admin. if (body.isSuperAdmin && !ctx.isSuperAdmin) { throw new ForbiddenError('Only super admins can mint super-admin invitations'); } const result = await createCrmInvite({ ...body, invitedBy: ctx }); return NextResponse.json({ data: result }, { status: 201 }); } catch (error) { return errorResponse(error); } }), );