export const SERVER_JOB_NETWORK_POLICY_SCHEMA = 1; function normalizeOrigin(value) { if (typeof value !== "string" || value.length > 2048) throw new Error("SERVER_NETWORK_POLICY_INVALID: origin is invalid"); let url; try { url = new URL(value); } catch { throw new Error("SERVER_NETWORK_POLICY_INVALID: origin is invalid"); } if (url.username || url.password || url.pathname !== "/" || url.search || url.hash) throw new Error("SERVER_NETWORK_POLICY_INVALID: origin is not canonical"); if (url.protocol !== "https:" && !(url.protocol === "http:" && ["127.0.0.1", "localhost", "::1"].includes(url.hostname))) throw new Error("SERVER_NETWORK_POLICY_DENIED: origin must be HTTPS or loopback"); return url.origin; } export function parseServerJobNetworkPolicy(value) { if (!value || typeof value !== "object" || value.schemaVersion !== SERVER_JOB_NETWORK_POLICY_SCHEMA || !Array.isArray(value.allowedOrigins)) throw new Error("SERVER_NETWORK_POLICY_INVALID: schema is unsupported"); const origins = [...new Set(value.allowedOrigins.map(normalizeOrigin))].sort(); if (origins.length > 64) throw new Error("SERVER_NETWORK_POLICY_INVALID: origin count exceeds budget"); return Object.freeze({ schemaVersion: SERVER_JOB_NETWORK_POLICY_SCHEMA, defaultNetwork: "DENY", allowedOrigins: origins }); } export function resolveServerJobNetwork(policyValue, requestedOrigin) { const policy = parseServerJobNetworkPolicy(policyValue); if (requestedOrigin === undefined || requestedOrigin === null) return Object.freeze({ status: "DENIED", code: "SERVER_NETWORK_DENIED", origin: null, network: "DISABLED" }); const origin = normalizeOrigin(requestedOrigin); if (!policy.allowedOrigins.includes(origin)) return Object.freeze({ status: "DENIED", code: "SERVER_NETWORK_DENIED", origin, network: "DISABLED" }); return Object.freeze({ status: "ALLOWED", code: "SERVER_NETWORK_ALLOWED_ORIGIN", origin, network: "DECLARED_ORIGIN" }); }