/** Validate before launching either companion process; never print key values. */ export function validateRuntime(env, { production = false } = {}) { const missing = [ "NEXT_PUBLIC_SUPABASE_URL", "NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY", "SUPABASE_SECRET_KEY", ].filter((key) => !env[key]); if (missing.length) throw new Error( `Missing configuration: ${missing.join(", ")}. Configure .env.local or your host's environment.`, ); const backend = new URL(env.NEXT_PUBLIC_SUPABASE_URL); if ( !["http:", "https:"].includes(backend.protocol) || backend.username || backend.password ) throw new Error( "NEXT_PUBLIC_SUPABASE_URL must be an HTTP(S) URL without credentials.", ); if ( env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY.startsWith("sb_secret_") || env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY === env.SUPABASE_SECRET_KEY ) throw new Error( "The public Supabase key must not contain the server secret.", ); if (production) { if (env.MINEGEO_ALLOW_ANY_ORIGIN === "true") throw new Error("MINEGEO_ALLOW_ANY_ORIGIN must be false in production."); if (!env.MINEGEO_URL) throw new Error( "Set MINEGEO_URL to the website's public origin before starting production.", ); const website = new URL(env.MINEGEO_URL); const local = ["localhost", "127.0.0.1", "[::1]"].includes( website.hostname, ); if ( (!local && website.protocol !== "https:") || !["https:", "http:"].includes(website.protocol) || website.username || website.password || website.pathname !== "/" || website.search || website.hash ) throw new Error( "MINEGEO_URL must be an HTTPS origin (HTTP is allowed only on loopback).", ); } const workerHeap = Number(env.MINEGEO_WORKER_HEAP_MB || 4096); if (!Number.isInteger(workerHeap) || workerHeap < 512 || workerHeap > 32768) throw new Error( "MINEGEO_WORKER_HEAP_MB must be an integer between 512 and 32768.", ); const faceSize = Number(env.MINEGEO_FACE_SIZE || 1024); if (!Number.isInteger(faceSize) || faceSize < 256 || faceSize > 2048) throw new Error( "MINEGEO_FACE_SIZE must be an integer between 256 and 2048.", ); return { workerHeap }; }