feat(backfill): support ops-secret bootstrap auth for backfill-isolation

Made-with: Cursor
This commit is contained in:
2026-04-27 19:39:04 -07:00
parent 769fbdcba2
commit a83cc45f6a

View File

@@ -14,9 +14,9 @@
*/
import { NextResponse } from 'next/server';
import { authSession } from '@/lib/auth/session-server';
import { query } from '@/lib/db-postgres';
import { getOrCreateProvisionedWorkspace } from '@/lib/workspaces';
import { requireWorkspacePrincipal } from '@/lib/auth/workspace-auth';
import { getOrCreateProvisionedWorkspace, type VibnWorkspace } from '@/lib/workspaces';
import {
ensureProjectCoolifyProject,
ensureProjectResourcesTable,
@@ -39,28 +39,42 @@ interface BackfillReport {
warnings: string[];
}
export async function POST() {
const session = await authSession();
if (!session?.user?.email) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const email = session.user.email;
export async function POST(request: Request) {
// Three accepted auth modes:
// 1. NextAuth session (browser)
// 2. Bearer vibn_sk_... workspace API key (matches /api/mcp)
// 3. Bearer <NEXTAUTH_SECRET> + ?email=<owner> (ops bootstrap so the
// maintainer can curl the backfill from a workstation without
// needing a session cookie or pre-minted API key)
let ws: VibnWorkspace | null = null;
// Resolve workspace + load all of the user's projects.
const users = await query<{ id: string }>(
`SELECT id FROM fs_users WHERE data->>'email' = $1 LIMIT 1`,
[email],
);
if (users.length === 0) {
return NextResponse.json({ error: 'User not found' }, { status: 404 });
}
const firebaseUserId = users[0].id;
const authHeader = request.headers.get('authorization') ?? '';
const bearer = authHeader.toLowerCase().startsWith('bearer ')
? authHeader.slice(7).trim()
: '';
const opsSecret = process.env.NEXTAUTH_SECRET;
const url = new URL(request.url);
const opsEmail = url.searchParams.get('email');
if (bearer && opsSecret && bearer === opsSecret && opsEmail) {
const users = await query<{ id: string }>(
`SELECT id FROM fs_users WHERE data->>'email' = $1 LIMIT 1`,
[opsEmail],
);
if (users.length === 0) {
return NextResponse.json({ error: `No fs_users row for ${opsEmail}` }, { status: 404 });
}
ws = await getOrCreateProvisionedWorkspace({
userId: users[0].id,
email: opsEmail,
displayName: opsEmail,
});
} else {
const principal = await requireWorkspacePrincipal(request);
if (principal instanceof NextResponse) return principal;
ws = principal.workspace;
}
const ws = await getOrCreateProvisionedWorkspace({
userId: firebaseUserId,
email,
displayName: session.user.name ?? email,
});
if (!ws) {
return NextResponse.json({ error: 'Workspace not provisioned' }, { status: 503 });
}