// [TSM.ID].[11031972] — All Rights Reserved. Proprietary & Confidential. import { NextResponse } from 'next/server'; import { db } from "@/drizzle/db"; import { tenants, users } from "@/drizzle/schema"; import { eq } from 'drizzle-orm'; import { cookies } from 'next/headers'; import jwt from 'jsonwebtoken'; import { QuantumOrchestrator } from "@/lib/quantum-orchestrator"; export const dynamic = 'force-dynamic'; interface DecodedToken { userId: string; email: string; role: string; tenantId: string; } export async function GET() { try { const cookieStore = await cookies(); const token = cookieStore.get('jumpa_token')?.value; if (!token) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); const decoded = jwt.verify(token, process.env.JWT_SECRET as string) as DecodedToken; // Fetch tenant data to get BYOK settings and licenses const tenantData = await db.select().from(tenants).where(eq(tenants.id, decoded.tenantId)).limit(1); const userData = await db.select().from(users).where(eq(users.id, decoded.userId)).limit(1); if (tenantData.length === 0) { return NextResponse.json({ error: 'Tenant not found' }, { status: 404 }); } const tenant = tenantData[0]; const user = userData[0]; // Parse licenses const rawLicenses = tenant.licenses || '{}'; const tenantLicParsed = JSON.parse(rawLicenses); let tenantLicNormalized: Record = {}; if (Array.isArray(tenantLicParsed)) { tenantLicParsed.forEach((k: string) => tenantLicNormalized[k] = 'GRANTED'); } else { tenantLicNormalized = tenantLicParsed || {}; } const userLicParsed = JSON.parse(user?.licenses || '{}'); let userLicNormalized: Record = {}; if (Array.isArray(userLicParsed)) { userLicParsed.forEach((k: string) => userLicNormalized[k] = 'GRANTED'); } else { userLicNormalized = userLicParsed || {}; } // Resolve 101-Module Matrix Capabilities const capabilities = QuantumOrchestrator.resolve( tenantLicNormalized, userLicNormalized, !!tenant.isActive ); // Parse legacy modules string list let modules: string[] = []; try { if (Array.isArray(tenantLicParsed)) { modules = tenantLicParsed; } else { modules = Object.keys(tenantLicParsed).filter(k => (tenantLicParsed as Record)[k] === 'GRANTED'); } } catch (_e) { modules = []; } // Determine the active BYOK Key // Priority: User > Tenant let activeByokKey = 'none'; let byokLevel = 'SYSTEM'; if (user?.byokEnabled && user?.byokKey) { activeByokKey = user.byokKey; byokLevel = 'USER'; } else if (tenant.byokEnabled && tenant.byokKey) { activeByokKey = tenant.byokKey; byokLevel = 'TENANT'; } // Secret WAJIB sama dengan XCU_QCG_SECRET di XCU Core (PKX Rule #4) const xcuSecret = process.env.XCU_QCG_SECRET || process.env.XCU_TOKEN_SECRET; if (!xcuSecret) { throw new Error('HUKUM MUTLAK: XCU_QCG_SECRET tidak ditemukan! Gerbang Anti-Jumping menolak akses.'); } const quantumToken = jwt.sign({ sub: decoded.email, tenantId: decoded.tenantId, modules: modules, capabilities: capabilities, byok: activeByokKey, byokLevel: byokLevel, iat: Math.floor(Date.now() / 1000), exp: Math.floor(Date.now() / 1000) + (60 * 60 * 12) }, xcuSecret); return NextResponse.json({ token: quantumToken, modules: modules, capabilities: capabilities, byokActive: activeByokKey !== 'none', byokLevel: byokLevel }); } catch (error: unknown) { console.error('[QUANTUM TOKEN ERROR]', error); return NextResponse.json({ error: 'Quantum Sync Failed' }, { status: 500 }); } }