import { cookies } from 'next/headers'; import { OperationsShell } from '../../components/ops/operations-shell'; import { OperationsErrorState } from '../../components/ops/operations-error-state'; import { normalizeHealthResponse, sanitizeAuditEvent } from '../../lib/ops-data'; import { OperatorSession, OperationsHealth, SafeAuditEvent, OperationsNavId, } from '../../components/ops/types'; interface AdminPageProps { searchParams?: Promise<{ nav?: string; case?: string; }>; } function parseNavParam(nav?: string): OperationsNavId { if (nav === 'incidents' || nav === 'audit' || nav === 'operators' || nav === 'session') { return nav; } return 'overview'; } export default async function AdminPage({ searchParams }: AdminPageProps) { const resolvedParams = searchParams ? await searchParams : {}; const initialNav = parseNavParam(resolvedParams.nav); const initialCaseRef = typeof resolvedParams.case === 'string' ? resolvedParams.case : null; const cookieStore = await cookies(); const isProduction = process.env.NODE_ENV === 'production' && process.env.NEXT_PUBLIC_APP_ENV === 'production'; const opsToken = isProduction ? cookieStore.get('__Host-motorsignal_ops')?.value : cookieStore.get('__Host-motorsignal_ops')?.value ?? cookieStore.get('motorsignal_ops')?.value; // Unauthenticated - prompt for login (Zero query parameter preview/bypass) if (!opsToken) { return (
); } const baseUrl = process.env.MOTORSIGNAL_API_BASE_URL ?? 'https://api.motorsignal.app'; const headers = { authorization: `Bearer ${opsToken}`, accept: 'application/json', }; try { // STEP 1: Verify Operations identity & role first const meResponse = await fetch(`${baseUrl}/api/v1/ops/me`, { headers, cache: 'no-store' }); if (meResponse.status === 401) { return (
); } if (meResponse.status === 403) { return (
); } if (!meResponse.ok) { return (
); } const meData = await meResponse.json(); const session: OperatorSession = { identity: meData.identity ?? meData.email ?? 'operator', role: meData.role === 'owner' ? 'owner' : 'operator', status: meData.status === 'expired' || meData.status === 'revoked' ? meData.status : 'active', createdAt: meData.created_at ?? meData.createdAt, lastActivityAt: meData.last_activity_at ?? meData.lastActivityAt, expiresAt: meData.expires_at ?? meData.expiresAt, environment: process.env.NODE_ENV === 'production' ? 'production' : 'development', }; // STEP 2: After successful verified session, fetch health, and ONLY fetch audit if role == 'owner' const isOwner = session.role === 'owner'; const [healthResponse, auditResponse] = await Promise.all([ fetch(`${baseUrl}/api/v1/ops/health`, { headers, cache: 'no-store' }), isOwner ? fetch(`${baseUrl}/api/v1/ops/audit-events`, { headers, cache: 'no-store' }).catch(() => null) : Promise.resolve(null), ]); let health: OperationsHealth; if (healthResponse.ok) { const healthData = await healthResponse.json(); health = normalizeHealthResponse(healthData); } else { health = normalizeHealthResponse({ status: 'unavailable', checked_at: new Date().toISOString() }); } let initialAuditEvents: SafeAuditEvent[] = []; let nextCursor: string | null = null; let auditTotal: number | undefined = undefined; if (auditResponse && auditResponse.ok) { const auditData = await auditResponse.json(); const rawEvents = Array.isArray(auditData) ? auditData : Array.isArray(auditData?.events) ? auditData.events : Array.isArray(auditData?.items) ? auditData.items : []; initialAuditEvents = rawEvents .map(sanitizeAuditEvent) .filter((e: SafeAuditEvent | null): e is SafeAuditEvent => e !== null); nextCursor = auditData?.next_cursor ?? auditData?.cursor ?? null; if (typeof auditData?.total === 'number') { auditTotal = auditData.total; } } return ( ); } catch { return (
); } }