import { NextResponse } from 'next/server'; import { db } from "@/drizzle/db"; import { networkTelemetry, quantumLogs, liveKillSwitches } from "@/drizzle/schema"; import { cookies } from 'next/headers'; import jwt from 'jsonwebtoken'; import { desc, count, sql, eq } from 'drizzle-orm'; export const dynamic = 'force-dynamic'; interface DecodedToken { userId: string; email: string; role: string; tenantId: string; } // PANOPTICON: Tenant Admin Telemetry API (Sandboxed View) // Returns ONLY data scoped to the caller's tenant_id. 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; if (decoded.role !== 'admin' && decoded.role !== 'superadmin') { return NextResponse.json({ error: 'Admin Access Required' }, { status: 403 }); } const tenantId = decoded.tenantId; // 1. Telemetry scoped to tenant (last 50) const recentTelemetry = await db.select().from(networkTelemetry) .where(eq(networkTelemetry.tenantId, tenantId)) .orderBy(desc(networkTelemetry.timestamp)) .limit(50); // 2. Quantum logs scoped to tenant (last 100) const recentLogs = await db.select().from(quantumLogs) .where(eq(quantumLogs.tenantId, tenantId)) .orderBy(desc(quantumLogs.nanoTimestamp)) .limit(100); // 3. Kill switches scoped to tenant const activeKills = await db.select().from(liveKillSwitches) .where(eq(liveKillSwitches.tenantId, tenantId)); // 4. Aggregated stats (tenant-scoped) const [telemetryCount] = await db.select({ total: count() }).from(networkTelemetry) .where(eq(networkTelemetry.tenantId, tenantId)); const [logsCount] = await db.select({ total: count() }).from(quantumLogs) .where(eq(quantumLogs.tenantId, tenantId)); // 5. Bandwidth aggregate (tenant-scoped) const bandwidthAgg = await db.select({ totalBytes: sql`COALESCE(SUM(CAST(traffic_bytes AS BIGINT)), 0)`, avgResponseMs: sql`COALESCE(AVG(CAST(response_time_ms AS NUMERIC)), 0)`, }).from(networkTelemetry) .where(eq(networkTelemetry.tenantId, tenantId)); return NextResponse.json({ telemetry: recentTelemetry, logs: recentLogs, kills: activeKills, stats: { totalTelemetryRecords: telemetryCount?.total || 0, totalLogRecords: logsCount?.total || 0, activeKillSwitches: activeKills.length, totalBandwidthBytes: bandwidthAgg[0]?.totalBytes || '0', avgResponseTimeMs: parseFloat(String(bandwidthAgg[0]?.avgResponseMs || '0')).toFixed(2), }, }); } catch (error: unknown) { console.error('[TENANT TELEMETRY ERROR]', error); return NextResponse.json({ error: 'Telemetry Sync Failed' }, { status: 500 }); } }