import { NextResponse, type NextRequest } from "next/server"; const isProduction = process.env.NODE_ENV === "production" && process.env.ALLOW_FRAME_EMBEDDING !== "true"; const configuredApiUrl = process.env.NEXT_PUBLIC_API_URL || ""; const externalApiOrigin = configuredApiUrl.startsWith("http") ? configuredApiUrl.replace(/\/+$/, "") : ""; export function middleware(_request: NextRequest) { const response = NextResponse.next(); const scriptSrc = isProduction ? "script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval'" : "script-src 'self' 'unsafe-inline' 'unsafe-eval' 'wasm-unsafe-eval'"; const connectSources = ["'self'", "ws:", "wss:", "blob:", "data:"]; if (externalApiOrigin) { connectSources.push(externalApiOrigin); } const directives = [ "default-src 'self'", scriptSrc, "style-src 'self' 'unsafe-inline'", "img-src 'self' blob: data: https:", "media-src 'self' blob: data:", "font-src 'self' data:", `connect-src ${connectSources.join(" ")}`, "worker-src 'self' blob:", isProduction ? "frame-ancestors 'none'" : "frame-ancestors *", ]; response.headers.set("Content-Security-Policy", directives.join("; ")); response.headers.set("X-Content-Type-Options", "nosniff"); response.headers.set("Referrer-Policy", "strict-origin-when-cross-origin"); response.headers.set( "Permissions-Policy", isProduction ? "camera=(self), microphone=(self), geolocation=()" : "camera=*, microphone=*, geolocation=()" ); if (isProduction) { response.headers.set("X-Frame-Options", "DENY"); } return response; } export const config = { matcher: ["/((?!api/backend|_next/static|_next/image|favicon.ico).*)"], };