1// Callback policy shared by configuration and delivery. The host's trusted2// origins and the relay owner's origins intersect; neither list is a URL proxy.3export function callbackOrigin(raw: unknown): string {4 if (typeof raw !== "string" || raw.length > 2048) return "";5 try {6 const u = new URL(raw);7 if (u.protocol !== "https:" || u.username || u.password || u.hash || u.port) return "";8 const h = u.hostname;9 // Only ordinary public DNS names. DNS ownership is trusted explicitly10 // by the host operator, not delegated to relay members or tenants.11 if (!/^(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z][a-z0-9-]*$/.test(h)) return "";12 if (/\.(?:localhost|local|internal|lan|home|test|invalid|onion)$/.test(h)) return "";13 return u.origin;14 } catch { return ""; }15}1617export function callbackOrigins(raw: unknown): string[] | null {18 if (!Array.isArray(raw) || raw.length > 16) return null;19 const out: string[] = [];20 for (const value of raw) {21 const origin = callbackOrigin(value);22 if (!origin || (value !== origin && value !== origin + "/")) return null;23 if (!out.includes(origin)) out.push(origin);24 }25 return out;26}