@void/platform 0.20.2 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +3 -2
- package/dist/index.mjs +4 -2
- package/dist/installer.d.mts +8 -1
- package/dist/installer.mjs +18 -2
- package/dist/runtime/api/README.md +1 -1
- package/dist/runtime/api/assets/admin/client.js +64 -0
- package/dist/runtime/api/assets/admin/style.css +2 -0
- package/dist/runtime/api/index.js +137274 -57153
- package/dist/runtime/api/index.js.map +4 -4
- package/dist/runtime/dispatch/README.md +1 -1
- package/dist/runtime/dispatch/index.js +42 -13
- package/dist/runtime/dispatch/index.js.map +2 -2
- package/dist/runtime/drizzle/0049_invitation_delivery_status.sql +2 -0
- package/dist/runtime/drizzle/0050_project_member_direct_grants.sql +2 -0
- package/dist/runtime/drizzle/compatibility.json +12 -0
- package/dist/runtime/drizzle/meta/_journal.json +14 -0
- package/dist/runtime/emailGateway/README.md +1 -1
- package/dist/runtime/manifest.json +47 -11
- package/dist/runtime/proxy/README.md +1 -1
- package/dist/runtime/proxy/index.js +23 -4
- package/dist/runtime/proxy/index.js.map +2 -2
- package/dist/runtime/tail/README.md +1 -1
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../index.mjs", "../../../../../platform/packages/dispatch/src/error-page.ts", "../../../../edge/src/pattern.ts", "../../../../edge/src/headers.ts", "../../../../edge/src/routing-rules.ts", "../../../../edge/src/static.ts", "../../../../isr/src/index.ts", "../../../../isr/src/core.ts", "../../../../../platform/packages/dispatch/src/isr.ts", "../../../../../platform/packages/api/src/usage-auth.ts", "../../../../../platform/packages/dispatch/src/metering.ts", "../../../../../platform/packages/dispatch/src/platform-lifecycle.ts", "../../../../../platform/packages/dispatch/src/constants.ts", "../../../../../platform/packages/dispatch/src/hostname.ts", "../../../../../platform/packages/dispatch/src/project-hostname.ts", "../../../../../platform/packages/dispatch/src/request-type.ts", "../../../../../platform/packages/dispatch/src/with-timeout.ts", "../../../../../platform/packages/dispatch/src/index.ts"],
|
|
4
4
|
"sourceRoot": "/home/runner/work/void/void/packages/platform/dist/runtime/dispatch",
|
|
5
|
-
"sourcesContent": ["//#region src/authentication-recovery.ts\nfunction platformAuthenticationRecoveryMessage(value) {\n\treturn JSON.stringify([\n\t\t\"void-platform-auth-recovery-v1\",\n\t\tvalue.installationId,\n\t\tvalue.administratorUserId,\n\t\tvalue.connectionId,\n\t\tvalue.revision,\n\t\tvalue.generation,\n\t\tvalue.testId,\n\t\tvalue.expiresAt\n\t]);\n}\n//#endregion\n//#region src/authentication.ts\n/** Platform login and perimeter configuration are independent of app authentication. */\nconst PLATFORM_LOGIN_KINDS = [\n\t\"github\",\n\t\"google\",\n\t\"oidc\",\n\t\"cloudflare-access\"\n];\n/** Operator-side coverage verification, bound to one administrator and settings revision. */\nfunction platformProtectionProofMessage(input) {\n\treturn `void-platform-protection-v1\\n${JSON.stringify({\n\t\tinstallationId: input.installationId,\n\t\torigin: input.origin,\n\t\tuserId: input.userId,\n\t\tsessionId: input.sessionId,\n\t\trevision: input.revision,\n\t\tlifecycleVersion: input.lifecycleVersion,\n\t\tprotection: parsePlatformAccessProtection(input.protection),\n\t\texpiresAt: input.expiresAt\n\t})}`;\n}\nfunction parsePlatformSignupAllowlistEntry(value) {\n\tconst entry = record(value, \"Signup allowlist entry\");\n\tconst note = entry.note;\n\tif (note !== void 0 && (typeof note !== \"string\" || note.length > 1e3)) throw new Error(\"Signup allowlist notes must be strings of at most 1000 characters.\");\n\tconst optionalNote = note === void 0 ? {} : { note };\n\tif (entry.type === \"identity\") {\n\t\tconst connectionId = parsePlatformLoginId(entry.connectionId);\n\t\tif (typeof entry.subject !== \"string\" || entry.subject.length === 0 || entry.subject.length > 255) throw new Error(\"Identity subjects must be nonempty strings of at most 255 characters.\");\n\t\treturn {\n\t\t\ttype: \"identity\",\n\t\t\tconnectionId,\n\t\t\tsubject: entry.subject,\n\t\t\t...optionalNote\n\t\t};\n\t}\n\tif (entry.type !== \"github\" && entry.type !== \"email\") throw new Error(\"Signup allowlist entry type must be github, email, or identity.\");\n\tif (typeof entry.pattern !== \"string\" || !entry.pattern || entry.pattern.length > 320 || /[\\s,]/.test(entry.pattern)) throw new Error(\"Signup allowlist patterns must be nonempty strings of at most 320 characters.\");\n\treturn {\n\t\ttype: entry.type,\n\t\tpattern: entry.pattern,\n\t\t...optionalNote\n\t};\n}\n/** Match one verified login identity against persisted signup grants. */\nfunction isPlatformSignupAllowed(identity, entries) {\n\treturn entries.some((entry) => {\n\t\tif (entry.type === \"identity\") return entry.connectionId === identity.connectionId && entry.subject === identity.subject;\n\t\tif (entry.type === \"github\") return identity.provider === \"github\" && entry.pattern.toLowerCase() === identity.login.toLowerCase();\n\t\tif (!identity.email) return false;\n\t\tif (entry.pattern.startsWith(\"*@\")) return identity.email.toLowerCase().endsWith(entry.pattern.slice(1).toLowerCase());\n\t\treturn entry.pattern.toLowerCase() === identity.email.toLowerCase();\n\t});\n}\nfunction parsePlatformAuthenticationSetup(value) {\n\tconst input = record(value, \"Authentication setup\");\n\tif (!Array.isArray(input.connections) || input.connections.length === 0 || input.connections.length > 32) throw new Error(\"Authentication setup requires between 1 and 32 connections.\");\n\tconst connections = input.connections.map((value) => {\n\t\tconst entry = record(value, \"Login connection\");\n\t\tstring(entry.clientSecret, \"Client secret\", 8192);\n\t\treturn {\n\t\t\tconfiguration: parsePlatformLoginConfiguration(entry.configuration),\n\t\t\tclientSecret: entry.clientSecret\n\t\t};\n\t});\n\tif (new Set(connections.map((entry) => entry.configuration.id)).size !== connections.length) throw new Error(\"Authentication setup connection IDs must be unique.\");\n\tconst administratorConnectionId = parsePlatformLoginId(input.administratorConnectionId);\n\tif (!connections.some((entry) => entry.configuration.id === administratorConnectionId)) throw new Error(\"The administrator login method must be included in setup.\");\n\tif (typeof input.bootstrapCredentialHash !== \"string\" || !/^[a-f0-9]{64}$/.test(input.bootstrapCredentialHash)) throw new Error(\"A SHA-256 bootstrap credential hash is required.\");\n\tconst admission = parsePlatformAdmissionPolicy(input.admission);\n\tconst protection = parsePlatformAccessProtection(input.protection ?? null);\n\tvalidatePlatformAdmissionPolicy(admission, connections.map((entry) => entry.configuration), protection);\n\tif (input.resetPending !== void 0 && typeof input.resetPending !== \"boolean\") throw new Error(\"resetPending must be a boolean.\");\n\treturn {\n\t\tconnections,\n\t\tadministratorConnectionId,\n\t\tbootstrapCredentialHash: input.bootstrapCredentialHash,\n\t\tadmission,\n\t\tprotection,\n\t\t...input.resetPending === true ? { resetPending: true } : {}\n\t};\n}\nconst DEFAULT_PLATFORM_SESSION_SECONDS = 2592e3;\nconst GOOGLE_OIDC_ISSUER = \"https://accounts.google.com\";\nconst PLATFORM_AUTH_SETUP_PROOF_PREFIX = \"void.platform.auth.setup.v1\";\nfunction record(value, name) {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(`${name} must be an object.`);\n\treturn value;\n}\nfunction string(value, name, maximum = 512) {\n\tif (typeof value !== \"string\" || !value.trim() || value.length > maximum || Array.from(value).some((character) => character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127)) throw new Error(`${name} must be a nonempty string of at most ${maximum} characters.`);\n\treturn value.trim();\n}\nfunction strings(value, name, maximum = 100) {\n\tif (!Array.isArray(value) || value.length > maximum) throw new Error(`${name} must be an array of at most ${maximum} strings.`);\n\tconst result = value.map((entry) => string(entry, name));\n\tif (new Set(result).size !== result.length) throw new Error(`${name} must not contain duplicates.`);\n\treturn result;\n}\nfunction parsePlatformLoginId(value) {\n\tif (typeof value !== \"string\" || !/^[a-z][a-z0-9-]{0,63}$/.test(value)) throw new Error(\"Login connection IDs must start with a letter and use 1\u201364 lowercase letters, digits, or hyphens.\");\n\treturn value;\n}\n/** HTTPS syntax validation; outbound network policy must additionally validate resolved endpoints. */\nfunction parsePlatformIdentityUrl(value, name, originOnly = false) {\n\tconst input = string(value, name, 2048);\n\tlet url;\n\ttry {\n\t\turl = new URL(input);\n\t} catch {\n\t\tthrow new Error(`${name} must be a credential-free HTTPS URL.`);\n\t}\n\tif (url.protocol !== \"https:\" || url.username || url.password || url.search || url.hash || originOnly && url.pathname !== \"/\") throw new Error(`${name} must be a credential-free HTTPS ${originOnly ? \"origin\" : \"URL\"} without query or fragment.`);\n\treturn originOnly ? url.origin : input;\n}\nfunction parsePlatformLoginDescriptor(value) {\n\tconst entry = record(value, \"Login connection\");\n\tconst id = parsePlatformLoginId(entry.id);\n\tif (!PLATFORM_LOGIN_KINDS.includes(entry.kind)) throw new Error(\"Login kind must be github, google, oidc, or cloudflare-access.\");\n\tconst kind = entry.kind;\n\tif ((id === \"github\" || id === \"google\") && id !== kind) throw new Error(`Connection ID ${id} is reserved for ${id} login.`);\n\tif ((kind === \"github\" || kind === \"google\") && id !== kind) throw new Error(`${kind} uses the fixed connection ID ${kind}.`);\n\treturn {\n\t\tid,\n\t\tkind,\n\t\tlabel: string(entry.label, \"Login label\", 100)\n\t};\n}\nfunction parsePlatformLoginConfiguration(value) {\n\tconst entry = record(value, \"Login configuration\");\n\tconst descriptor = parsePlatformLoginDescriptor(entry);\n\tconst clientId = string(entry.clientId, \"Client ID\");\n\tconst allowedDomains = strings(entry.allowedDomains ?? [], \"Allowed domains\").map((domain) => {\n\t\tconst normalized = domain.toLowerCase();\n\t\tif (!/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z]{2,63}$/.test(normalized)) throw new Error(\"Allowed domains must be exact domain names, without wildcards.\");\n\t\treturn normalized;\n\t});\n\tif (new Set(allowedDomains).size !== allowedDomains.length) throw new Error(\"Allowed domains must not contain duplicates.\");\n\tconst requiredGroups = strings(entry.requiredGroups ?? [], \"Required groups\");\n\tif (descriptor.kind !== \"google\" && allowedDomains.length > 0) throw new Error(\"Workspace domain restrictions are only supported by Google login.\");\n\tif ((descriptor.kind === \"github\" || descriptor.kind === \"google\") && requiredGroups.length > 0) throw new Error(\"Group restrictions require an OIDC or Cloudflare Access connection.\");\n\tlet issuer;\n\tif (descriptor.kind === \"google\") {\n\t\tif (entry.issuer !== void 0 && entry.issuer !== \"https://accounts.google.com\") throw new Error(\"Google login uses the Google issuer.\");\n\t\tissuer = GOOGLE_OIDC_ISSUER;\n\t} else if (descriptor.kind === \"github\") {\n\t\tif (entry.issuer !== void 0) throw new Error(\"GitHub login does not accept an OIDC issuer.\");\n\t} else {\n\t\tissuer = parsePlatformIdentityUrl(entry.issuer, \"OIDC issuer\");\n\t\tif (descriptor.kind === \"cloudflare-access\") {\n\t\t\tconst url = new URL(issuer);\n\t\t\tif (!/^[a-z0-9-]+\\.cloudflareaccess\\.com$/.test(url.hostname) || url.port || !url.pathname.startsWith(\"/cdn-cgi/access/sso/oidc/\") || decodeURIComponent(url.pathname.slice(25).replace(/\\/$/, \"\")) !== clientId) throw new Error(\"Cloudflare Access login requires its application issuer URL and matching client ID. Use generic OIDC for another issuer.\");\n\t\t}\n\t}\n\treturn {\n\t\t...descriptor,\n\t\tclientId,\n\t\t...issuer ? { issuer } : {},\n\t\tallowedDomains,\n\t\trequiredGroups\n\t};\n}\nfunction parsePlatformAccessProtection(value) {\n\tif (value === null) return null;\n\tconst entry = record(value, \"Access protection\");\n\tconst teamDomain = parsePlatformIdentityUrl(entry.teamDomain, \"Access team domain\", true);\n\tconst host = new URL(teamDomain).hostname;\n\tif (!/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.cloudflareaccess\\.com$/.test(host) || new URL(teamDomain).port) throw new Error(\"Access team domain must be an HTTPS cloudflareaccess.com team origin.\");\n\tif (!Array.isArray(entry.applications) || entry.applications.length === 0 || entry.applications.length > 20) throw new Error(\"Access protection requires between 1 and 20 protected origins.\");\n\tconst applications = entry.applications.map((value) => {\n\t\tconst application = record(value, \"Access application\");\n\t\treturn {\n\t\t\torigin: parsePlatformIdentityUrl(application.origin, \"Protected origin\", true),\n\t\t\taudience: string(application.audience, \"Access application audience\")\n\t\t};\n\t});\n\tif (new Set(applications.map((app) => app.origin)).size !== applications.length) throw new Error(\"Each protected origin must have exactly one Access application.\");\n\treturn {\n\t\tteamDomain,\n\t\tapplications\n\t};\n}\nfunction parsePlatformAdmissionPolicy(value) {\n\tconst entry = record(value, \"Admission policy\");\n\tif (entry.mode === \"restricted\" || entry.mode === \"public\") return { mode: entry.mode };\n\tif (entry.mode !== \"company\" || typeof entry.access !== \"boolean\") throw new Error(\"Admission policy must select restricted, company, or public signup.\");\n\tconst connections = strings(entry.connections, \"Company connections\").map(parsePlatformLoginId);\n\tif (!entry.access && connections.length === 0) throw new Error(\"Company admission requires a trusted connection or Access protection.\");\n\treturn {\n\t\tmode: \"company\",\n\t\tconnections,\n\t\taccess: entry.access\n\t};\n}\n/** Run inside the settings mutation transaction, using the resulting enabled connections. */\nfunction validatePlatformAdmissionPolicy(policy, enabledConnections, protection) {\n\tif (policy.mode !== \"company\") return;\n\tif (policy.access && !protection) throw new Error(\"Company admission through Access requires enabled protection.\");\n\tfor (const id of policy.connections) {\n\t\tconst connection = enabledConnections.find((entry) => entry.id === id);\n\t\tif (!connection) throw new Error(`Company admission requires enabled connection ${id}.`);\n\t\tif (connection.kind === \"github\" || connection.kind === \"google\" && connection.allowedDomains.length === 0) throw new Error(\"Unrestricted social login does not establish company membership.\");\n\t}\n}\n//#endregion\n//#region src/manifest.ts\nconst PLATFORM_DEPLOYMENT_SCHEMA_VERSION = 1;\nconst CORE_CAPABILITIES = {\n\tai: true,\n\tcustomDomains: false,\n\temail: false,\n\tgithubActions: false,\n\tgithubOAuth: true,\n\tgoogleOAuth: false,\n\tmanagedBuilds: false,\n\tsandbox: false\n};\nconst CONTROL_PLANE_DEFAULTS = {\n\tapiHostname: null,\n\tdashboardHostname: null,\n\tproxyHostname: null\n};\nfunction assertRecord$1(value, label) {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(`${label} must be an object.`);\n}\nfunction requiredString$1(value, label) {\n\tif (typeof value !== \"string\" || value.trim() === \"\") throw new Error(`${label} must be a non-empty string.`);\n\treturn value;\n}\nfunction normalizeInstallationSlug(value) {\n\tconst slug = value.trim().toLowerCase().replaceAll(/[^a-z0-9-]+/g, \"-\").replaceAll(/^-+|-+$/g, \"\").replaceAll(/-{2,}/g, \"-\");\n\tif (!slug) throw new Error(\"The installation name must contain a letter or number.\");\n\tif (slug.length > 40) throw new Error(\"The installation name must be 40 characters or fewer after normalization.\");\n\treturn slug;\n}\nfunction normalizeApplicationDomain(value) {\n\tlet domain = value.trim().toLowerCase();\n\tif (domain.endsWith(\".\")) domain = domain.slice(0, -1);\n\tif (domain.length > 253 || !domain.includes(\".\") || domain.split(\".\").some((label) => !/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(label))) throw new Error(`Invalid domain: ${JSON.stringify(value)}.`);\n\treturn domain;\n}\nfunction createPlatformResourceNames(installationSlug) {\n\tconst prefix = `void-${normalizeInstallationSlug(installationSlug)}`;\n\tconst datasetPrefix = prefix.replaceAll(\"-\", \"_\");\n\treturn {\n\t\taiGateway: prefix,\n\t\tapiWorker: `${prefix}-api`,\n\t\tassetsBucket: `${prefix}-assets`,\n\t\tcronQueue: `${prefix}-cron-fires`,\n\t\tdashboardWorker: `${prefix}-dashboard`,\n\t\tdispatchNamespace: `${prefix}-users`,\n\t\tdispatchWorker: `${prefix}-dispatch`,\n\t\temailGatewayWorker: `${prefix}-email-gateway`,\n\t\thyperdrive: `${prefix}-database`,\n\t\tisrCacheKv: `${prefix}-isr-cache`,\n\t\tlegacyAssetsKv: `${prefix}-legacy-assets`,\n\t\tlogsDataset: `${datasetPrefix}_logs`,\n\t\tproxyWorker: `${prefix}-proxy`,\n\t\trequestsDataset: `${datasetPrefix}_requests`,\n\t\troutingKv: `${prefix}-routing`,\n\t\ttailWorker: `${prefix}-tail`,\n\t\tusageQueue: `${prefix}-usage-events`\n\t};\n}\nfunction createApplicationRoutes(application) {\n\tif (!application.zoneName && application.workersDev) {\n\t\tif (application.dedicatedZone) throw new Error(\"workers.dev cannot use a dedicated-zone catch-all.\");\n\t\treturn [];\n\t}\n\tconst baseDomain = normalizeApplicationDomain(application.baseDomain);\n\tconst zoneName = normalizeApplicationDomain(application.zoneName);\n\tif (baseDomain !== zoneName && !baseDomain.endsWith(`.${zoneName}`)) throw new Error(`Application domain ${baseDomain} is not inside zone ${zoneName}.`);\n\tconst routes = [{\n\t\tpattern: `*.${baseDomain}/*`,\n\t\tzoneName\n\t}, {\n\t\tpattern: `*.${baseDomain}`,\n\t\tzoneName\n\t}];\n\tif (application.dedicatedZone) {\n\t\tif (baseDomain !== zoneName) throw new Error(\"A dedicated-zone catch-all requires the application domain to be the zone.\");\n\t\troutes.push({\n\t\t\tpattern: \"*/*\",\n\t\t\tzoneName\n\t\t}, {\n\t\t\tpattern: \"*\",\n\t\t\tzoneName\n\t\t});\n\t}\n\treturn routes;\n}\nfunction createPlatformDeploymentManifest(input) {\n\tif (input.emailSharedZoneId === void 0 !== (input.emailSenderDomain === void 0)) throw new Error(\"Shared email configuration requires both emailSenderDomain and emailSharedZoneId.\");\n\tconst installationSlug = normalizeInstallationSlug(input.installationSlug);\n\tconst baseDomain = normalizeApplicationDomain(input.application.baseDomain);\n\tconst workersDev = input.application.workersDev;\n\tif (workersDev && (!/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(workersDev.subdomain) || !/^[a-z0-9][a-z0-9-]{0,80}$/.test(workersDev.installationId))) throw new Error(\"Invalid workers.dev installation identity.\");\n\tconst zoneName = workersDev && input.application.zoneName === \"\" ? \"\" : normalizeApplicationDomain(input.application.zoneName);\n\tif (!zoneName && baseDomain !== `${workersDev.subdomain}.workers.dev`) throw new Error(\"workers.dev application domain must match its account subdomain.\");\n\tconst resources = {\n\t\t...createPlatformResourceNames(installationSlug),\n\t\t...input.resources\n\t};\n\tconst capabilities = {\n\t\t...CORE_CAPABILITIES,\n\t\t...input.capabilities\n\t};\n\tif (capabilities.managedBuilds && !capabilities.githubActions) throw new Error(\"Managed builds require the GitHub Actions capability.\");\n\tconst providers = input.authentication?.providers ?? [\"github\"];\n\tif (providers.some((provider) => !PLATFORM_LOGIN_KINDS.includes(provider)) || new Set(providers).size !== providers.length) throw new Error(\"Authentication providers must be unique supported login kinds.\");\n\tconst configurable = input.authentication?.configurable === true || input.authentication?.accessProtection === true || providers.some((provider) => provider === \"oidc\" || provider === \"cloudflare-access\");\n\tif (providers.length === 0) throw new Error(\"At least one authentication provider is required.\");\n\tif (providers.includes(\"github\") !== capabilities.githubOAuth) throw new Error(\"The GitHub provider and githubOAuth capability must agree.\");\n\tif (providers.includes(\"google\") !== capabilities.googleOAuth) throw new Error(\"The Google provider and googleOAuth capability must agree.\");\n\tconst manifest = {\n\t\tapplication: {\n\t\t\tbaseDomain,\n\t\t\tdedicatedZone: input.application.dedicatedZone ?? false,\n\t\t\tzoneName,\n\t\t\t...workersDev ? { workersDev: { ...workersDev } } : {},\n\t\t\t...input.application.zoneId ? { zoneId: requiredString$1(input.application.zoneId, \"application.zoneId\") } : {}\n\t\t},\n\t\tauthentication: {\n\t\t\tproviders: [...providers],\n\t\t\t...configurable ? { configurable: true } : {},\n\t\t\t...input.authentication?.accessProtection ? { accessProtection: true } : {}\n\t\t},\n\t\tcapabilities,\n\t\t...input.emailSharedZoneId !== void 0 ? { emailSharedZoneId: requiredString$1(input.emailSharedZoneId, \"emailSharedZoneId\") } : {},\n\t\t...input.emailSenderDomain !== void 0 ? { emailSenderDomain: normalizeApplicationDomain(input.emailSenderDomain) } : {},\n\t\tcontrolPlane: {\n\t\t\t...CONTROL_PLANE_DEFAULTS,\n\t\t\t...input.controlPlane\n\t\t},\n\t\tdisplayName: requiredString$1(input.displayName, \"displayName\").trim(),\n\t\tinstallationSlug,\n\t\tresources,\n\t\tschemaVersion: configurable ? 3 : workersDev ? 2 : 1\n\t};\n\tcreateApplicationRoutes(manifest.application);\n\tfor (const [key, value] of Object.entries(manifest.controlPlane)) {\n\t\tif (value !== null) normalizeApplicationDomain(value);\n\t\tif (value === \"\") throw new Error(`controlPlane.${key} must be a hostname or null.`);\n\t}\n\tfor (const [key, value] of Object.entries(manifest.resources)) requiredString$1(value, `resources.${key}`);\n\treturn manifest;\n}\nfunction parsePlatformDeploymentManifest(value) {\n\tassertRecord$1(value, \"Platform deployment manifest\");\n\tif (value.schemaVersion !== 1 && value.schemaVersion !== 2 && value.schemaVersion !== 3) throw new Error(`Unsupported platform deployment schema version: ${String(value.schemaVersion)}.`);\n\tconst application = value.application;\n\tconst authentication = value.authentication;\n\tconst rawCapabilities = value.capabilities;\n\tconst controlPlane = value.controlPlane;\n\tconst rawResources = value.resources;\n\tassertRecord$1(application, \"application\");\n\tlet workersDev;\n\tif (value.schemaVersion === 2 || value.schemaVersion === 3 && application.workersDev !== void 0) {\n\t\tassertRecord$1(application.workersDev, \"application.workersDev\");\n\t\tworkersDev = {\n\t\t\tsubdomain: requiredString$1(application.workersDev.subdomain, \"workersDev.subdomain\"),\n\t\t\tinstallationId: requiredString$1(application.workersDev.installationId, \"workersDev.installationId\")\n\t\t};\n\t} else if (application.workersDev !== void 0) throw new Error(\"workers.dev requires platform deployment schema version 2.\");\n\tassertRecord$1(rawCapabilities, \"capabilities\");\n\tassertRecord$1(controlPlane, \"controlPlane\");\n\tassertRecord$1(authentication, \"authentication\");\n\tassertRecord$1(rawResources, \"resources\");\n\tconst capabilityKeys = Object.keys(CORE_CAPABILITIES);\n\tconst capabilities = {};\n\tfor (const key of capabilityKeys) {\n\t\tconst entry = rawCapabilities[key];\n\t\tif (typeof entry !== \"boolean\") throw new Error(`capabilities.${key} must be a boolean.`);\n\t\tcapabilities[key] = entry;\n\t}\n\tconst providers = authentication.providers;\n\tif (!Array.isArray(providers) || providers.some((provider) => !PLATFORM_LOGIN_KINDS.includes(provider) || value.schemaVersion !== 3 && provider !== \"github\" && provider !== \"google\")) throw new Error(\"authentication.providers must contain only github or google.\");\n\tif (value.schemaVersion === 3 && authentication.configurable !== true || value.schemaVersion !== 3 && (authentication.configurable !== void 0 || authentication.accessProtection !== void 0) || authentication.accessProtection !== void 0 && authentication.accessProtection !== true) throw new Error(\"Configurable authentication requires deployment schema version 3.\");\n\tconst resourceDefaults = createPlatformResourceNames(requiredString$1(value.installationSlug, \"installationSlug\"));\n\tconst resources = {};\n\tfor (const key of Object.keys(resourceDefaults)) resources[key] = requiredString$1(rawResources[key] ?? (key === \"emailGatewayWorker\" ? resourceDefaults[key] : void 0), `resources.${key}`);\n\tconst readHostname = (key) => {\n\t\tconst hostname = controlPlane[key];\n\t\treturn hostname === null ? null : requiredString$1(hostname, `controlPlane.${key}`);\n\t};\n\treturn createPlatformDeploymentManifest({\n\t\tapplication: {\n\t\t\tbaseDomain: requiredString$1(application.baseDomain, \"application.baseDomain\"),\n\t\t\tdedicatedZone: application.dedicatedZone === true,\n\t\t\tzoneName: workersDev && application.zoneName === \"\" ? \"\" : requiredString$1(application.zoneName, \"application.zoneName\"),\n\t\t\t...workersDev ? { workersDev } : {},\n\t\t\t...typeof application.zoneId === \"string\" ? { zoneId: application.zoneId } : {}\n\t\t},\n\t\tauthentication: {\n\t\t\tproviders,\n\t\t\t...authentication.configurable === true ? { configurable: true } : {},\n\t\t\t...authentication.accessProtection === true ? { accessProtection: true } : {}\n\t\t},\n\t\tcapabilities,\n\t\t...value.emailSharedZoneId !== void 0 ? { emailSharedZoneId: requiredString$1(value.emailSharedZoneId, \"emailSharedZoneId\") } : {},\n\t\t...value.emailSenderDomain !== void 0 ? { emailSenderDomain: normalizeApplicationDomain(requiredString$1(value.emailSenderDomain, \"emailSenderDomain\")) } : {},\n\t\tcontrolPlane: {\n\t\t\tapiHostname: readHostname(\"apiHostname\"),\n\t\t\tdashboardHostname: readHostname(\"dashboardHostname\"),\n\t\t\tproxyHostname: readHostname(\"proxyHostname\")\n\t\t},\n\t\tdisplayName: requiredString$1(value.displayName, \"displayName\"),\n\t\tinstallationSlug: requiredString$1(value.installationSlug, \"installationSlug\"),\n\t\tresources\n\t});\n}\n//#endregion\n//#region src/installation.ts\nconst PLATFORM_INSTALLATION_SCHEMA_VERSION = 1;\nconst PLATFORM_DISABLED_KEY = \"__void/platform/disabled/v1\";\nconst PLATFORM_DISABLED_VALUE = \"disabled\";\nconst PLATFORM_REMOTE_INSTALLATION_MANIFEST_KEY = \"__void/platform/installation/v1\";\nconst PLATFORM_SANDBOX_DRAIN_KEY = \"__void/platform/sandbox-drain/v1\";\nconst PLATFORM_R2_OWNERSHIP_MARKER_KEY = \"__void/platform/ownership/v1\";\nconst PLATFORM_RESOURCE_OWNERSHIP_SCHEMA_VERSION = 1;\nconst PLATFORM_USAGE_PROTOCOL_VERSION = 2;\nconst STATUS_TRANSITIONS = {\n\tdraft: [\n\t\t\"planned\",\n\t\t\"failed\",\n\t\t\"uninstalling\"\n\t],\n\tplanned: [\n\t\t\"provisioning\",\n\t\t\"failed\",\n\t\t\"uninstalling\"\n\t],\n\tprovisioning: [\n\t\t\"waiting-for-dns\",\n\t\t\"waiting-for-oauth\",\n\t\t\"deploying\",\n\t\t\"disabling\",\n\t\t\"failed\",\n\t\t\"uninstalling\"\n\t],\n\t\"waiting-for-dns\": [\n\t\t\"provisioning\",\n\t\t\"disabling\",\n\t\t\"failed\",\n\t\t\"uninstalling\"\n\t],\n\t\"waiting-for-oauth\": [\n\t\t\"provisioning\",\n\t\t\"deploying\",\n\t\t\"disabling\",\n\t\t\"failed\",\n\t\t\"uninstalling\"\n\t],\n\tdeploying: [\n\t\t\"provisioning\",\n\t\t\"verifying\",\n\t\t\"disabling\",\n\t\t\"disabled\",\n\t\t\"failed\",\n\t\t\"uninstalling\"\n\t],\n\tverifying: [\n\t\t\"provisioning\",\n\t\t\"installed\",\n\t\t\"disabling\",\n\t\t\"failed\",\n\t\t\"uninstalling\"\n\t],\n\tinstalled: [\n\t\t\"provisioning\",\n\t\t\"disabling\",\n\t\t\"uninstalling\",\n\t\t\"failed\"\n\t],\n\tdisabling: [\n\t\t\"disabled\",\n\t\t\"failed\",\n\t\t\"uninstalling\"\n\t],\n\tdisabled: [\n\t\t\"provisioning\",\n\t\t\"uninstalling\",\n\t\t\"failed\"\n\t],\n\tuninstalling: [\"uninstalled\", \"failed\"],\n\tuninstalled: [],\n\tfailed: [\n\t\t\"planned\",\n\t\t\"provisioning\",\n\t\t\"deploying\",\n\t\t\"verifying\",\n\t\t\"disabling\",\n\t\t\"uninstalling\"\n\t]\n};\nfunction assertRecord(value, label) {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(`${label} must be an object.`);\n}\nfunction requiredString(value, label) {\n\tif (typeof value !== \"string\" || value.trim() === \"\") throw new Error(`${label} must be a non-empty string.`);\n\treturn value;\n}\nfunction isInstallationStatus(value) {\n\treturn typeof value === \"string\" && Object.hasOwn(STATUS_TRANSITIONS, value);\n}\nfunction isResourceKind(value) {\n\treturn value === \"ai-gateway\" || value === \"analytics-dataset\" || value === \"dispatch-namespace\" || value === \"dns-record\" || value === \"hyperdrive\" || value === \"kv-namespace\" || value === \"queue\" || value === \"r2-bucket\" || value === \"worker\" || value === \"worker-custom-domain\" || value === \"worker-route\" || value === \"zone\";\n}\nfunction isOwnership(value) {\n\treturn value === \"created\" || value === \"adopted\" || value === \"external\";\n}\nfunction isResourceState(value) {\n\treturn value === \"ready\" || value === \"retained\" || value === \"deleted\";\n}\nfunction assertTimestamp(value, label) {\n\tif (!Number.isFinite(Date.parse(value))) throw new Error(`${label} must be an ISO timestamp.`);\n\treturn value;\n}\nfunction createPlatformResourceOwnershipMarker(input) {\n\tif (!isResourceKind(input.resourceKind)) throw new Error(\"Invalid ownership marker resource kind.\");\n\treturn {\n\t\taccountId: requiredString(input.accountId, \"ownership accountId\"),\n\t\tinstallationId: requiredString(input.installationId, \"ownership installationId\"),\n\t\townershipNonce: requiredString(input.ownershipNonce, \"ownership ownershipNonce\"),\n\t\tresourceId: requiredString(input.resourceId, \"ownership resourceId\"),\n\t\tresourceKey: requiredString(input.resourceKey, \"ownership resourceKey\"),\n\t\tresourceKind: input.resourceKind,\n\t\tresourceName: requiredString(input.resourceName, \"ownership resourceName\"),\n\t\tschemaVersion: 1\n\t};\n}\nfunction parsePlatformResourceOwnershipMarker(value) {\n\tassertRecord(value, \"Platform resource ownership marker\");\n\tif (value.schemaVersion !== 1) throw new Error(`Unsupported platform resource ownership schema version: ${String(value.schemaVersion)}.`);\n\tif (!isResourceKind(value.resourceKind)) throw new Error(\"Invalid ownership marker resource kind.\");\n\treturn createPlatformResourceOwnershipMarker({\n\t\taccountId: requiredString(value.accountId, \"ownership accountId\"),\n\t\tinstallationId: requiredString(value.installationId, \"ownership installationId\"),\n\t\townershipNonce: requiredString(value.ownershipNonce, \"ownership ownershipNonce\"),\n\t\tresourceId: requiredString(value.resourceId, \"ownership resourceId\"),\n\t\tresourceKey: requiredString(value.resourceKey, \"ownership resourceKey\"),\n\t\tresourceKind: value.resourceKind,\n\t\tresourceName: requiredString(value.resourceName, \"ownership resourceName\")\n\t});\n}\nfunction createPlatformInstallationManifest(input) {\n\tconst createdAt = assertTimestamp(input.createdAt, \"createdAt\");\n\tif (!/^[a-z0-9][a-z0-9-]{7,79}$/.test(input.id)) throw new Error(\"Installation id must be a lowercase identifier between 8 and 80 characters.\");\n\tif (!/^[A-Za-z0-9_-]{32,128}$/.test(input.ownershipNonce)) throw new Error(\"Ownership nonce must contain 32 to 128 URL-safe characters.\");\n\treturn {\n\t\taccount: {\n\t\t\tid: requiredString(input.account.id, \"account.id\"),\n\t\t\tname: requiredString(input.account.name, \"account.name\")\n\t\t},\n\t\tcreatedAt,\n\t\tdatabaseSchemaDigest: null,\n\t\tdeployment: parsePlatformDeploymentManifest(JSON.parse(JSON.stringify(input.deployment))),\n\t\tdesiredState: \"enabled\",\n\t\tendpoints: {\n\t\t\tapiUrl: null,\n\t\t\tdashboardUrl: null,\n\t\t\tproxyUrl: null\n\t\t},\n\t\tid: input.id,\n\t\townershipNonce: input.ownershipNonce,\n\t\tplatformVersion: requiredString(input.platformVersion, \"platformVersion\"),\n\t\tresources: [],\n\t\truntime: null,\n\t\tsafetyProtocols: input.safetyProtocols ?? { sandboxDrain: 0 },\n\t\tschemaVersion: 1,\n\t\tstatus: \"draft\",\n\t\tsteps: [],\n\t\tupdatedAt: createdAt,\n\t\tusageProtocolVersion: input.usageProtocolVersion ?? 0\n\t};\n}\nfunction setInstallationDesiredState(manifest, desiredState, updatedAt) {\n\treturn {\n\t\t...manifest,\n\t\tdesiredState,\n\t\tupdatedAt: assertTimestamp(updatedAt, \"updatedAt\")\n\t};\n}\nfunction normalizeEndpoint(value, label) {\n\tif (value === null) return null;\n\tlet url;\n\ttry {\n\t\turl = new URL(value);\n\t} catch {\n\t\tthrow new Error(`${label} must be an absolute URL or null.`);\n\t}\n\tif (url.protocol !== \"https:\" || url.username || url.password || url.search || url.hash) throw new Error(`${label} must be a credential-free HTTPS URL.`);\n\turl.pathname = url.pathname.replace(/\\/+$/, \"\") || \"/\";\n\treturn url.href.replace(/\\/$/, \"\");\n}\nfunction setInstallationEndpoints(manifest, endpoints, updatedAt) {\n\treturn {\n\t\t...manifest,\n\t\tendpoints: {\n\t\t\tapiUrl: normalizeEndpoint(endpoints.apiUrl, \"endpoints.apiUrl\"),\n\t\t\tdashboardUrl: normalizeEndpoint(endpoints.dashboardUrl, \"endpoints.dashboardUrl\"),\n\t\t\tproxyUrl: normalizeEndpoint(endpoints.proxyUrl, \"endpoints.proxyUrl\")\n\t\t},\n\t\tupdatedAt: assertTimestamp(updatedAt, \"updatedAt\")\n\t};\n}\nfunction transitionInstallation(manifest, status, updatedAt) {\n\tif (status !== manifest.status && !STATUS_TRANSITIONS[manifest.status].includes(status)) throw new Error(`Invalid installation transition: ${manifest.status} -> ${status}.`);\n\treturn {\n\t\t...manifest,\n\t\tstatus,\n\t\tupdatedAt: assertTimestamp(updatedAt, \"updatedAt\")\n\t};\n}\nfunction recordInstallationResource(manifest, resource, updatedAt) {\n\trequiredString(resource.key, \"resource.key\");\n\trequiredString(resource.id, \"resource.id\");\n\trequiredString(resource.name, \"resource.name\");\n\trequiredString(resource.configHash, \"resource.configHash\");\n\tconst collision = manifest.resources.find((entry) => entry.key !== resource.key && entry.kind === resource.kind && entry.id === resource.id);\n\tif (collision) throw new Error(`Resource id ${resource.id} is already owned by ${collision.key}.`);\n\tconst resources = manifest.resources.filter((entry) => entry.key !== resource.key);\n\tresources.push({ ...resource });\n\tresources.sort((left, right) => left.key.localeCompare(right.key));\n\treturn {\n\t\t...manifest,\n\t\tresources,\n\t\tupdatedAt: assertTimestamp(updatedAt, \"updatedAt\")\n\t};\n}\nfunction recordInstallationStep(manifest, step, updatedAt) {\n\trequiredString(step.key, \"step.key\");\n\trequiredString(step.resultHash, \"step.resultHash\");\n\tassertTimestamp(step.completedAt, \"step.completedAt\");\n\tconst existing = manifest.steps.find((entry) => entry.key === step.key);\n\tif (existing && existing.resultHash !== step.resultHash) throw new Error(`Completed installation step ${step.key} has a different result.`);\n\tconst steps = existing ? manifest.steps : [...manifest.steps, { ...step }];\n\treturn {\n\t\t...manifest,\n\t\tsteps,\n\t\tupdatedAt: assertTimestamp(updatedAt, \"updatedAt\")\n\t};\n}\nfunction parsePlatformInstallationManifest(value) {\n\tassertRecord(value, \"Platform installation manifest\");\n\tif (value.schemaVersion !== 1) throw new Error(`Unsupported platform installation schema version: ${String(value.schemaVersion)}.`);\n\tconst account = value.account;\n\tconst endpoints = value.endpoints;\n\tassertRecord(account, \"account\");\n\tassertRecord(endpoints, \"endpoints\");\n\tif (!isInstallationStatus(value.status)) throw new Error(`Invalid installation status: ${String(value.status)}.`);\n\tif (!Array.isArray(value.resources)) throw new Error(\"resources must be an array.\");\n\tif (!Array.isArray(value.steps)) throw new Error(\"steps must be an array.\");\n\tconst manifest = createPlatformInstallationManifest({\n\t\taccount: {\n\t\t\tid: requiredString(account.id, \"account.id\"),\n\t\t\tname: requiredString(account.name, \"account.name\")\n\t\t},\n\t\tcreatedAt: requiredString(value.createdAt, \"createdAt\"),\n\t\tdeployment: parsePlatformDeploymentManifest(value.deployment),\n\t\tid: requiredString(value.id, \"id\"),\n\t\townershipNonce: requiredString(value.ownershipNonce, \"ownershipNonce\"),\n\t\tplatformVersion: requiredString(value.platformVersion, \"platformVersion\"),\n\t\tsafetyProtocols: parseSafetyProtocols(value.safetyProtocols),\n\t\tusageProtocolVersion: parseUsageProtocolVersion$1(value.usageProtocolVersion)\n\t});\n\tconst runtime = parsePlatformRuntimeProvenance(value.runtime);\n\tlet pendingDomain;\n\tif (value.pendingDomain !== void 0) {\n\t\tassertRecord(value.pendingDomain, \"pendingDomain\");\n\t\tpendingDomain = createPlatformDeploymentManifest({\n\t\t\t...manifest.deployment,\n\t\t\tapplication: value.pendingDomain\n\t\t}).application;\n\t\tif (!manifest.deployment.application.workersDev || !pendingDomain.zoneName || JSON.stringify(pendingDomain.workersDev) !== JSON.stringify(manifest.deployment.application.workersDev)) throw new Error(\"Pending domain must retain the installation workers.dev identity.\");\n\t}\n\tconst updatedAt = assertTimestamp(requiredString(value.updatedAt, \"updatedAt\"), \"updatedAt\");\n\tlet next = setInstallationEndpoints({\n\t\t...manifest,\n\t\tdesiredState: value.desiredState === \"disabled\" || value.desiredState === \"enabled\" ? value.desiredState : value.status === \"disabled\" || value.status === \"disabling\" ? \"disabled\" : \"enabled\",\n\t\tstatus: value.status,\n\t\truntime,\n\t\t...pendingDomain ? { pendingDomain } : {},\n\t\t...value.authenticationResources !== void 0 ? { authenticationResources: parseAuthenticationResources(value.authenticationResources) } : {},\n\t\tupdatedAt\n\t}, {\n\t\tapiUrl: endpoints.apiUrl === null ? null : requiredString(endpoints.apiUrl, \"endpoints.apiUrl\"),\n\t\tdashboardUrl: endpoints.dashboardUrl === null ? null : requiredString(endpoints.dashboardUrl, \"endpoints.dashboardUrl\"),\n\t\tproxyUrl: endpoints.proxyUrl === null ? null : requiredString(endpoints.proxyUrl, \"endpoints.proxyUrl\")\n\t}, updatedAt);\n\tfor (const [index, entry] of value.resources.entries()) {\n\t\tassertRecord(entry, `resources[${index}]`);\n\t\tif (!isResourceKind(entry.kind)) throw new Error(`Invalid resources[${index}].kind.`);\n\t\tif (!isOwnership(entry.ownership)) throw new Error(`Invalid resources[${index}].ownership.`);\n\t\tif (!isResourceState(entry.state)) throw new Error(`Invalid resources[${index}].state.`);\n\t\tnext = recordInstallationResource(next, {\n\t\t\tconfigHash: requiredString(entry.configHash, `resources[${index}].configHash`),\n\t\t\tid: requiredString(entry.id, `resources[${index}].id`),\n\t\t\tkey: requiredString(entry.key, `resources[${index}].key`),\n\t\t\tkind: entry.kind,\n\t\t\tname: requiredString(entry.name, `resources[${index}].name`),\n\t\t\townership: entry.ownership,\n\t\t\tstate: entry.state\n\t\t}, next.updatedAt);\n\t}\n\tfor (const [index, entry] of value.steps.entries()) {\n\t\tassertRecord(entry, `steps[${index}]`);\n\t\tnext = recordInstallationStep(next, {\n\t\t\tcompletedAt: requiredString(entry.completedAt, `steps[${index}].completedAt`),\n\t\t\tkey: requiredString(entry.key, `steps[${index}].key`),\n\t\t\tresultHash: requiredString(entry.resultHash, `steps[${index}].resultHash`)\n\t\t}, next.updatedAt);\n\t}\n\tconst recordedDatabaseSchemaDigest = value.databaseSchemaDigest === void 0 || value.databaseSchemaDigest === null ? [...next.steps].reverse().find((step) => step.key.startsWith(\"database-schema:\"))?.resultHash ?? null : requiredString(value.databaseSchemaDigest, \"databaseSchemaDigest\");\n\treturn {\n\t\t...next,\n\t\tdatabaseSchemaDigest: recordedDatabaseSchemaDigest,\n\t\tupdatedAt\n\t};\n}\nfunction parseAuthenticationResources(value) {\n\tif (!Array.isArray(value) || value.length > 100) throw new Error(\"Invalid authentication resource inventory.\");\n\tconst resources = value.map((entry) => {\n\t\tassertRecord(entry, \"Authentication resource\");\n\t\tif (entry.kind !== \"application\" && entry.kind !== \"service-token\" || entry.ownership !== \"created\" && entry.ownership !== \"adopted\") throw new Error(\"Invalid authentication resource kind or ownership.\");\n\t\treturn {\n\t\t\tkey: requiredString(entry.key, \"authentication resource key\"),\n\t\t\tkind: entry.kind,\n\t\t\taccountId: requiredString(entry.accountId, \"authentication resource account\"),\n\t\t\tid: requiredString(entry.id, \"authentication resource ID\"),\n\t\t\tname: requiredString(entry.name, \"authentication resource name\"),\n\t\t\townership: entry.ownership\n\t\t};\n\t});\n\tif (new Set(resources.map((resource) => `${resource.accountId}:${resource.kind}:${resource.id}`)).size !== resources.length) throw new Error(\"Duplicate authentication resource identity.\");\n\treturn resources;\n}\nfunction parseUsageProtocolVersion$1(value) {\n\tif (value === void 0 || value === 0) return 0;\n\tif (value === 1) return 1;\n\tif (value === 2) return 2;\n\tthrow new Error(\"usageProtocolVersion must be 0, 1, or 2.\");\n}\nfunction parseSafetyProtocols(value) {\n\tif (value === void 0) return { sandboxDrain: 0 };\n\tassertRecord(value, \"safetyProtocols\");\n\tif (value.sandboxDrain !== 0 && value.sandboxDrain !== 1 && value.sandboxDrain !== 2) throw new Error(\"safetyProtocols.sandboxDrain must be 0, 1, or 2.\");\n\treturn { sandboxDrain: value.sandboxDrain };\n}\nfunction parsePlatformRuntimeProvenance(value) {\n\tif (value === void 0 || value === null) return null;\n\tassertRecord(value, \"runtime\");\n\tif (value.source !== \"custom\" && value.source !== \"package\") throw new Error(\"runtime.source must be custom or package.\");\n\tconst manifestSha256 = requiredString(value.manifestSha256, \"runtime.manifestSha256\");\n\tif (!/^[0-9a-f]{64}$/.test(manifestSha256)) throw new Error(\"runtime.manifestSha256 must be a SHA-256 digest.\");\n\tconst sourceRevision = value.sourceRevision === null || value.sourceRevision === void 0 ? null : requiredString(value.sourceRevision, \"runtime.sourceRevision\");\n\tif (sourceRevision !== null && (sourceRevision.length > 200 || !/^[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(sourceRevision))) throw new Error(\"runtime.sourceRevision is invalid.\");\n\treturn {\n\t\tmanifestSha256,\n\t\tsource: value.source,\n\t\tsourceRevision\n\t};\n}\n//#endregion\n//#region src/application.ts\n/** Minimal public-origin adapter; request policy remains in the service-bound dispatcher. */\nconst PLATFORM_PROJECT_INGRESS_SOURCE = `export default {\n fetch(request, env) {\n if (new URL(request.url).hostname !== env.VOID_APP_HOSTNAME) {\n return new Response('Not Found', {status: 404});\n }\n return env.PLATFORM_DISPATCH.fetch(request);\n }\n};`;\nfunction readPlatformApplication(env) {\n\tconst baseDomain = env.SITE_DOMAIN ?? env.BASE_HOSTNAME ?? \"void.app\";\n\tif (!env.PLATFORM_APPLICATION) return {\n\t\tbaseDomain,\n\t\tzoneName: baseDomain,\n\t\tdedicatedZone: false\n\t};\n\treturn createPlatformDeploymentManifest({\n\t\tinstallationSlug: \"runtime\",\n\t\tdisplayName: \"Runtime\",\n\t\tapplication: JSON.parse(env.PLATFORM_APPLICATION)\n\t}).application;\n}\nfunction platformWorkersDevAliasKey(hostname) {\n\treturn `workers-dev:${hostname}`;\n}\nconst PLATFORM_APPLICATION_KEY = \"__void/platform/application/v1\";\nasync function resolvePlatformApplicationEnvironment(env) {\n\tif (!env.PLATFORM_APPLICATION) return env;\n\tconst raw = await env.ROUTING.get(PLATFORM_APPLICATION_KEY);\n\tif (!raw) return env;\n\tconst previous = readPlatformApplication(env);\n\tconst next = readPlatformApplication({ PLATFORM_APPLICATION: raw });\n\tif (!previous.workersDev || !next.workersDev || previous.workersDev.installationId !== next.workersDev.installationId || previous.workersDev.subdomain !== next.workersDev.subdomain) throw new Error(\"Application routing belongs to another platform installation.\");\n\treturn {\n\t\t...env,\n\t\tPLATFORM_APPLICATION: raw,\n\t\tSITE_DOMAIN: next.baseDomain,\n\t\tBASE_HOSTNAME: next.baseDomain,\n\t\t...next.zoneId ? { CF_ZONE_ID: next.zoneId } : {}\n\t};\n}\nfunction platformProjectIngressName(project, workersDev) {\n\tif (!/^proj_[a-z0-9]{1,32}$/.test(project.id) || !/^[a-z0-9][a-z0-9-]*$/.test(project.slug)) throw new Error(\"Invalid platform project identity.\");\n\tconst prefix = `void-${workersDev.installationId.slice(-12)}-`;\n\tconst suffix = `-${project.id.slice(5)}`;\n\treturn `${prefix}${project.slug.slice(0, 63 - prefix.length - suffix.length).replace(/-+$/, \"\")}${suffix}`;\n}\nfunction platformProjectWorkersDevHostname(project, workersDev) {\n\treturn `${platformProjectIngressName(project, workersDev)}.${workersDev.subdomain}.workers.dev`;\n}\nfunction platformProjectHostname(project, application) {\n\tif (!application.zoneName && application.workersDev) return platformProjectWorkersDevHostname(project, application.workersDev);\n\treturn `${project.slug}.${application.baseDomain}`;\n}\nfunction platformProjectHostnames(project, application) {\n\treturn [.../* @__PURE__ */ new Set([platformProjectHostname(project, application), ...application.workersDev ? [platformProjectWorkersDevHostname(project, application.workersDev)] : []])];\n}\n//#endregion\n//#region src/discovery.ts\nconst PLATFORM_DISCOVERY_SCHEMA_VERSION = 1;\nfunction normalizeOrigin(value, name) {\n\tlet url;\n\ttry {\n\t\turl = new URL(value);\n\t} catch {\n\t\tthrow new Error(`${name} must be an absolute URL.`);\n\t}\n\tif (!(url.protocol === \"http:\" && (url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\" || url.hostname === \"::1\")) && url.protocol !== \"https:\" || url.username || url.password) throw new Error(`${name} must be a credential-free HTTPS URL.`);\n\tif (url.pathname !== \"\" && url.pathname !== \"/\" || url.search || url.hash) throw new Error(`${name} must be an origin without a path, query, or fragment.`);\n\treturn url.origin;\n}\nfunction createPlatformDiscoveryDocument(input) {\n\tif (!input.displayName.trim()) throw new Error(\"displayName must not be empty.\");\n\tif (!input.platformVersion.trim()) throw new Error(\"platformVersion must not be empty.\");\n\tif (input.applicationRouting) {\n\t\tconst application = readPlatformApplication({ PLATFORM_APPLICATION: JSON.stringify(input.applicationRouting) });\n\t\tif (!application.workersDev || application.baseDomain !== input.applicationDomain || application.workersDev.installationId !== input.installationId) throw new Error(\"Application routing must match the discovery domain and installation identity.\");\n\t}\n\tif (input.usageProtocolVersion !== void 0 && input.usageProtocolVersion !== 0 && input.usageProtocolVersion !== 1 && input.usageProtocolVersion !== 2) throw new Error(\"usageProtocolVersion must be 0, 1, or 2.\");\n\tconst authentication = input.authentication ? parseAuthentication(input.authentication) : void 0;\n\tif (!authentication && input.authenticationProviders.some((provider) => provider !== \"github\" && provider !== \"google\")) throw new Error(\"Named login methods require authentication discovery descriptors.\");\n\tif (new Set(input.authenticationProviders).size !== input.authenticationProviders.length) throw new Error(\"Authentication provider IDs must be unique.\");\n\tif (input.authenticationProviders.length === 0 && !authentication?.setupPending) throw new Error(\"At least one authentication provider is required.\");\n\tif (authentication && (authentication.methods.length !== input.authenticationProviders.length || authentication.methods.some((method, index) => method.id !== input.authenticationProviders[index]))) throw new Error(\"Authentication method descriptors must match the advertised provider IDs.\");\n\tif (input.authenticationProviders.includes(\"github\") !== input.capabilities.githubOAuth || input.authenticationProviders.includes(\"google\") !== input.capabilities.googleOAuth) throw new Error(\"Authentication providers and capabilities must agree.\");\n\treturn {\n\t\t...input,\n\t\tapiUrl: normalizeOrigin(input.apiUrl, \"apiUrl\"),\n\t\tapplicationDomain: normalizeApplicationDomain(input.applicationDomain),\n\t\tauthenticationProviders: [...input.authenticationProviders],\n\t\t...authentication ? { authentication } : {},\n\t\tdisplayName: input.displayName.trim(),\n\t\tinstallationId: input.installationId?.trim() || null,\n\t\tplatformVersion: input.platformVersion.trim(),\n\t\tproxyUrl: normalizeOrigin(input.proxyUrl, \"proxyUrl\"),\n\t\tschemaVersion: authentication ? 3 : input.applicationRouting?.workersDev ? 2 : 1,\n\t\tusageProtocolVersion: input.usageProtocolVersion ?? 0\n\t};\n}\nfunction parsePlatformDiscoveryDocument(value) {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"Platform discovery document must be an object.\");\n\tconst document = value;\n\tif (document.schemaVersion !== 1 && document.schemaVersion !== 2 && document.schemaVersion !== 3) throw new Error(`Unsupported platform discovery schema version: ${String(document.schemaVersion)}.`);\n\tconst capabilities = document.capabilities;\n\tif (document.schemaVersion === 1 && document.applicationRouting !== void 0) throw new Error(\"Application routing requires discovery schema version 2.\");\n\tif (document.schemaVersion === 2 && document.applicationRouting === void 0) throw new Error(\"Discovery schema version 2 requires application routing.\");\n\tif (!capabilities || typeof capabilities !== \"object\" || Array.isArray(capabilities)) throw new Error(\"capabilities must be an object.\");\n\tconst capabilityNames = [\n\t\t\"ai\",\n\t\t\"customDomains\",\n\t\t\"email\",\n\t\t\"githubActions\",\n\t\t\"githubOAuth\",\n\t\t\"googleOAuth\",\n\t\t\"managedBuilds\",\n\t\t\"sandbox\"\n\t];\n\tconst parsedCapabilities = {};\n\tfor (const name of capabilityNames) {\n\t\tconst enabled = capabilities[name];\n\t\tif (typeof enabled !== \"boolean\") throw new Error(`capabilities.${name} must be a boolean.`);\n\t\tparsedCapabilities[name] = enabled;\n\t}\n\tconst providers = document.authenticationProviders;\n\tif (!Array.isArray(providers) || providers.some((provider) => typeof provider !== \"string\" || document.schemaVersion !== 3 && provider !== \"github\" && provider !== \"google\")) throw new Error(\"authenticationProviders must contain only github or google.\");\n\tif (document.schemaVersion !== 3 && document.authentication !== void 0) throw new Error(\"Configurable authentication requires discovery schema version 3.\");\n\tconst authentication = document.schemaVersion === 3 ? parseAuthentication(document.authentication) : void 0;\n\tif (authentication) providers.forEach(parsePlatformLoginId);\n\tconst string = (name) => {\n\t\tconst entry = document[name];\n\t\tif (typeof entry !== \"string\" || !entry.trim()) throw new Error(`${name} must be a non-empty string.`);\n\t\treturn entry;\n\t};\n\tconst apiUrl = string(\"apiUrl\");\n\tconst proxyUrl = typeof document.proxyUrl === \"string\" && document.proxyUrl.trim() ? document.proxyUrl : apiUrl === \"https://api.void.cloud\" ? \"https://proxy.void.cloud\" : apiUrl === \"https://api.staging.void.cloud\" ? \"https://proxy.staging.void.cloud\" : string(\"proxyUrl\");\n\treturn createPlatformDiscoveryDocument({\n\t\tapiUrl,\n\t\tapplicationDomain: string(\"applicationDomain\"),\n\t\t...document.applicationRouting !== void 0 ? { applicationRouting: readPlatformApplication({ PLATFORM_APPLICATION: JSON.stringify(document.applicationRouting ?? null) }) } : {},\n\t\tauthenticationProviders: providers,\n\t\t...authentication ? { authentication } : {},\n\t\tcapabilities: parsedCapabilities,\n\t\tdisplayName: string(\"displayName\"),\n\t\tinstallationId: document.installationId === null ? null : string(\"installationId\"),\n\t\tplatformVersion: string(\"platformVersion\"),\n\t\tproxyUrl,\n\t\tusageProtocolVersion: parseUsageProtocolVersion(document.usageProtocolVersion)\n\t});\n}\nfunction parseAuthentication(value) {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"Authentication discovery must be an object.\");\n\tconst authentication = value;\n\tif (!Array.isArray(authentication.methods) || authentication.methods.length > 32 || typeof authentication.protectedByAccess !== \"boolean\" || authentication.setupPending !== void 0 && typeof authentication.setupPending !== \"boolean\") throw new Error(\"Authentication discovery requires login methods and a protection flag.\");\n\tconst methods = authentication.methods.map(parsePlatformLoginDescriptor);\n\tif (new Set(methods.map((method) => method.id)).size !== methods.length) throw new Error(\"Authentication connection IDs must be unique.\");\n\treturn {\n\t\tmethods,\n\t\tprotectedByAccess: authentication.protectedByAccess,\n\t\t...authentication.setupPending === true ? { setupPending: true } : {}\n\t};\n}\nfunction parseUsageProtocolVersion(value) {\n\tif (value === void 0 || value === 0) return 0;\n\tif (value === 1) return 1;\n\tif (value === 2) return 2;\n\tthrow new Error(\"usageProtocolVersion must be 0, 1, or 2.\");\n}\n//#endregion\n//#region src/worker-config.ts\nfunction createPlatformWorkerConfigs(input) {\n\tconst { accountId, apiUrl, deployment, healthProbeToken, installationId, ownershipNonce, platformVersion, proxyUrl, emailGatewayUrl, resources, runtimeEntrypoints } = input;\n\tconst publicEndpoints = input.publicEndpoints ?? true;\n\tconst trafficState = input.trafficState ?? \"enabled\";\n\tconst names = deployment.resources;\n\tconst sharedEmailIngress = deployment.emailSharedZoneId ? {\n\t\tEMAIL_SHARED_ACCOUNT_ID: accountId,\n\t\tEMAIL_SHARED_ZONE_ID: deployment.emailSharedZoneId,\n\t\tEMAIL_SHARED_INGRESS_NAME: names.emailGatewayWorker\n\t} : {};\n\tconst senderDomain = deployment.emailSenderDomain ? { EMAIL_SENDER_DOMAIN: deployment.emailSenderDomain } : {};\n\tconst ownershipVars = (resourceKey, resourceName) => ({ PLATFORM_OWNERSHIP_MARKER: JSON.stringify(createPlatformResourceOwnershipMarker({\n\t\taccountId,\n\t\tinstallationId,\n\t\townershipNonce,\n\t\tresourceId: resourceName,\n\t\tresourceKey,\n\t\tresourceKind: \"worker\",\n\t\tresourceName\n\t})) });\n\tconst common = {\n\t\taccount_id: accountId,\n\t\tcompatibility_date: \"2026-02-24\",\n\t\tobservability: { enabled: true },\n\t\tpreview_urls: publicEndpoints && !deployment.authentication.accessProtection,\n\t\tworkers_dev: publicEndpoints\n\t};\n\tconst kv = [\n\t\t{\n\t\t\tbinding: \"ROUTING\",\n\t\t\tid: resources.routingKv\n\t\t},\n\t\t{\n\t\t\tbinding: \"ISR_CACHE\",\n\t\t\tid: resources.isrCacheKv\n\t\t},\n\t\t{\n\t\t\tbinding: \"STATIC_ASSETS\",\n\t\t\tid: resources.legacyAssetsKv\n\t\t}\n\t];\n\tconst dispatchNamespace = [{\n\t\tbinding: \"DISPATCH\",\n\t\tnamespace: names.dispatchNamespace\n\t}];\n\tconst r2 = [{\n\t\tbinding: \"STATIC_ASSETS_R2\",\n\t\tbucket_name: names.assetsBucket\n\t}];\n\tconst fetchWorkersDev = Boolean(deployment.application.workersDev) || [\n\t\tapiUrl,\n\t\tproxyUrl,\n\t\t...deployment.capabilities.email ? [emailGatewayUrl] : []\n\t].some((url) => new URL(url).hostname.endsWith(\".workers.dev\"));\n\tconst api = {\n\t\t...common,\n\t\tversion_metadata: { binding: \"VERSION_METADATA\" },\n\t\tworkers_dev: publicEndpoints && (!deployment.authentication.accessProtection || new URL(apiUrl).hostname.endsWith(\".workers.dev\")),\n\t\tname: names.apiWorker,\n\t\tmain: runtimeEntrypoints.api,\n\t\tno_bundle: true,\n\t\tcompatibility_flags: [\"nodejs_compat\", ...fetchWorkersDev ? [\"global_fetch_strictly_public\"] : []],\n\t\tplacement: { mode: \"smart\" },\n\t\thyperdrive: [{\n\t\t\tbinding: \"HYPERDRIVE\",\n\t\t\tid: resources.hyperdrive\n\t\t}],\n\t\tkv_namespaces: kv,\n\t\t...deployment.capabilities.email ? { send_email: [{ name: \"EMAIL\" }] } : {},\n\t\tr2_buckets: r2,\n\t\tdispatch_namespaces: dispatchNamespace,\n\t\tdurable_objects: { bindings: [\n\t\t\t{\n\t\t\t\tname: \"USAGE_COUNTER\",\n\t\t\t\tclass_name: \"UsageCounter\"\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"CRON_SCHEDULER\",\n\t\t\t\tclass_name: \"CronScheduler\"\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"ERROR_ALERT_MONITOR\",\n\t\t\t\tclass_name: \"ErrorAlertMonitor\"\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"SANDBOX_CONCURRENCY_COUNTER\",\n\t\t\t\tclass_name: \"SandboxConcurrencyCounter\"\n\t\t\t}\n\t\t] },\n\t\tmigrations: [\n\t\t\t{\n\t\t\t\ttag: \"v1\",\n\t\t\t\tnew_sqlite_classes: [\"UsageCounter\"]\n\t\t\t},\n\t\t\t{\n\t\t\t\ttag: \"v2\",\n\t\t\t\tnew_sqlite_classes: [\"CronScheduler\"]\n\t\t\t},\n\t\t\t{\n\t\t\t\ttag: \"v3\",\n\t\t\t\tnew_sqlite_classes: [\"ErrorAlertMonitor\"]\n\t\t\t},\n\t\t\t{\n\t\t\t\ttag: \"v4\",\n\t\t\t\tnew_sqlite_classes: [\"SandboxConcurrencyCounter\"]\n\t\t\t}\n\t\t],\n\t\tqueues: {\n\t\t\tproducers: [{\n\t\t\t\tbinding: \"CRON_FIRES_QUEUE\",\n\t\t\t\tqueue: names.cronQueue\n\t\t\t}, {\n\t\t\t\tbinding: \"USAGE_EVENTS_QUEUE\",\n\t\t\t\tqueue: names.usageQueue\n\t\t\t}],\n\t\t\tconsumers: [{\n\t\t\t\tqueue: names.usageQueue,\n\t\t\t\tmax_batch_size: 100,\n\t\t\t\tmax_batch_timeout: 5\n\t\t\t}, {\n\t\t\t\tqueue: names.cronQueue,\n\t\t\t\tmax_batch_size: 50,\n\t\t\t\tmax_batch_timeout: 1,\n\t\t\t\tmax_retries: 3\n\t\t\t}]\n\t\t},\n\t\ttriggers: { crons: [\"0 * * * *\"] },\n\t\tvars: {\n\t\t\tAUTH_REDIRECT_URI: `${apiUrl}/auth/callback`,\n\t\t\tAI_GATEWAY_ID: names.aiGateway,\n\t\t\tCRON_FIRES_QUEUE_NAME: names.cronQueue,\n\t\t\tDISPATCH_NAMESPACE: names.dispatchNamespace,\n\t\t\tDISPATCH_WORKER_NAME: names.dispatchWorker,\n\t\t\tLOGS_DATASET: names.logsDataset,\n\t\t\tPLATFORM_CAPABILITIES: JSON.stringify(deployment.capabilities),\n\t\t\t...input.authenticationDatabaseUncached ? { PLATFORM_AUTH_DATABASE_UNCACHED: \"true\" } : {},\n\t\t\tPLATFORM_DISPLAY_NAME: deployment.displayName,\n\t\t\tPLATFORM_ENV: \"production\",\n\t\t\tPLATFORM_HEALTH_PROBE_TOKEN: healthProbeToken,\n\t\t\tPLATFORM_INSTALLATION_ID: installationId,\n\t\t\tPLATFORM_TRAFFIC_STATE: trafficState,\n\t\t\t...ownershipVars(\"api-worker\", names.apiWorker),\n\t\t\tPLATFORM_VERSION: platformVersion,\n\t\t\tPROXY_URL: proxyUrl,\n\t\t\tEMAIL_GATEWAY_ORIGIN: emailGatewayUrl,\n\t\t\t...sharedEmailIngress,\n\t\t\t...senderDomain,\n\t\t\tR2_STATIC_ASSETS_BUCKET: names.assetsBucket,\n\t\t\tREQUESTS_DATASET: names.requestsDataset,\n\t\t\tSITE_DOMAIN: deployment.application.baseDomain,\n\t\t\t...deployment.application.workersDev ? { PLATFORM_APPLICATION: JSON.stringify(deployment.application) } : {},\n\t\t\tTAIL_SERVICE_NAME: names.tailWorker,\n\t\t\tVOID_PROXY_SERVICE: names.proxyWorker\n\t\t}\n\t};\n\tif (publicEndpoints && deployment.controlPlane.apiHostname) api.routes = [{\n\t\tpattern: deployment.controlPlane.apiHostname,\n\t\tcustom_domain: true\n\t}];\n\tconst proxy = {\n\t\t...common,\n\t\tworkers_dev: publicEndpoints && (!deployment.authentication.accessProtection || new URL(proxyUrl).hostname.endsWith(\".workers.dev\")),\n\t\tname: names.proxyWorker,\n\t\tmain: runtimeEntrypoints.proxy,\n\t\tno_bundle: true,\n\t\tcompatibility_flags: [\"nodejs_compat\"],\n\t\tai: { binding: \"AI\" },\n\t\tkv_namespaces: [{\n\t\t\tbinding: \"ROUTING\",\n\t\t\tid: resources.routingKv\n\t\t}],\n\t\tservices: [{\n\t\t\tbinding: \"API\",\n\t\t\tservice: names.apiWorker\n\t\t}],\n\t\tdispatch_namespaces: dispatchNamespace,\n\t\t...deployment.capabilities.email ? { send_email: [{ name: \"SEND_EMAIL\" }] } : {},\n\t\tvars: {\n\t\t\tAI_GATEWAY_ID: names.aiGateway,\n\t\t\tPLATFORM_CAPABILITIES: JSON.stringify(deployment.capabilities),\n\t\t\tPLATFORM_HEALTH_PROBE_TOKEN: healthProbeToken,\n\t\t\tPLATFORM_INSTALLATION_ID: installationId,\n\t\t\tPLATFORM_TRAFFIC_STATE: trafficState,\n\t\t\t...senderDomain,\n\t\t\t...ownershipVars(\"proxy-worker\", names.proxyWorker)\n\t\t}\n\t};\n\tif (publicEndpoints && deployment.controlPlane.proxyHostname) proxy.routes = [{\n\t\tpattern: deployment.controlPlane.proxyHostname,\n\t\tcustom_domain: true\n\t}];\n\treturn {\n\t\tapi,\n\t\tproxy,\n\t\temailGateway: {\n\t\t\t...common,\n\t\t\tworkers_dev: publicEndpoints,\n\t\t\tpreview_urls: false,\n\t\t\tname: names.emailGatewayWorker,\n\t\t\tmain: runtimeEntrypoints.emailGateway,\n\t\t\tno_bundle: true,\n\t\t\tcompatibility_flags: [\"nodejs_compat\"],\n\t\t\tkv_namespaces: [{\n\t\t\t\tbinding: \"ROUTING\",\n\t\t\t\tid: resources.routingKv\n\t\t\t}],\n\t\t\tservices: [{\n\t\t\t\tbinding: \"API\",\n\t\t\t\tservice: names.apiWorker\n\t\t\t}],\n\t\t\tdispatch_namespaces: dispatchNamespace,\n\t\t\t...deployment.capabilities.email ? { send_email: [{ name: \"SEND_EMAIL\" }] } : {},\n\t\t\tvars: {\n\t\t\t\tPLATFORM_CAPABILITIES: JSON.stringify(deployment.capabilities),\n\t\t\t\tPLATFORM_INSTALLATION_ID: installationId,\n\t\t\t\tPLATFORM_VERSION: platformVersion,\n\t\t\t\tPLATFORM_TRAFFIC_STATE: trafficState,\n\t\t\t\t...sharedEmailIngress,\n\t\t\t\t...senderDomain,\n\t\t\t\t...ownershipVars(\"email-gateway-worker\", names.emailGatewayWorker)\n\t\t\t}\n\t\t},\n\t\ttail: {\n\t\t\t...common,\n\t\t\tname: names.tailWorker,\n\t\t\tmain: runtimeEntrypoints.tail,\n\t\t\tno_bundle: true,\n\t\t\tanalytics_engine_datasets: [{\n\t\t\t\tbinding: \"ANALYTICS\",\n\t\t\t\tdataset: names.logsDataset\n\t\t\t}],\n\t\t\tvars: {\n\t\t\t\tPLATFORM_DISPATCH_WORKER_NAME: names.dispatchWorker,\n\t\t\t\t...ownershipVars(\"tail-worker\", names.tailWorker)\n\t\t\t}\n\t\t},\n\t\tdispatch: {\n\t\t\t...common,\n\t\t\tname: names.dispatchWorker,\n\t\t\tmain: runtimeEntrypoints.dispatch,\n\t\t\tno_bundle: true,\n\t\t\t...publicEndpoints ? { routes: createApplicationRoutes(deployment.application).map((route) => ({\n\t\t\t\tpattern: route.pattern,\n\t\t\t\tzone_name: route.zoneName\n\t\t\t})) } : {},\n\t\t\tdispatch_namespaces: dispatchNamespace,\n\t\t\tkv_namespaces: kv,\n\t\t\tr2_buckets: r2,\n\t\t\tanalytics_engine_datasets: [{\n\t\t\t\tbinding: \"ANALYTICS\",\n\t\t\t\tdataset: names.requestsDataset\n\t\t\t}, {\n\t\t\t\tbinding: \"LOGS\",\n\t\t\t\tdataset: names.logsDataset\n\t\t\t}],\n\t\t\tqueues: { producers: [{\n\t\t\t\tbinding: \"USAGE_QUEUE\",\n\t\t\t\tqueue: names.usageQueue\n\t\t\t}] },\n\t\t\ttail_consumers: [{ service: names.tailWorker }],\n\t\t\tvars: {\n\t\t\t\tBASE_HOSTNAME: deployment.application.baseDomain,\n\t\t\t\t...deployment.application.workersDev ? { PLATFORM_APPLICATION: JSON.stringify(deployment.application) } : {},\n\t\t\t\tPLATFORM_HEALTH_PROBE_TOKEN: healthProbeToken,\n\t\t\t\tPLATFORM_INSTALLATION_ID: installationId,\n\t\t\t\tPLATFORM_TRAFFIC_STATE: trafficState,\n\t\t\t\t...ownershipVars(\"dispatch-worker\", names.dispatchWorker)\n\t\t\t}\n\t\t}\n\t};\n}\n//#endregion\nexport { DEFAULT_PLATFORM_SESSION_SECONDS, GOOGLE_OIDC_ISSUER, PLATFORM_APPLICATION_KEY, PLATFORM_AUTH_SETUP_PROOF_PREFIX, PLATFORM_DEPLOYMENT_SCHEMA_VERSION, PLATFORM_DISABLED_KEY, PLATFORM_DISABLED_VALUE, PLATFORM_DISCOVERY_SCHEMA_VERSION, PLATFORM_INSTALLATION_SCHEMA_VERSION, PLATFORM_LOGIN_KINDS, PLATFORM_PROJECT_INGRESS_SOURCE, PLATFORM_R2_OWNERSHIP_MARKER_KEY, PLATFORM_REMOTE_INSTALLATION_MANIFEST_KEY, PLATFORM_RESOURCE_OWNERSHIP_SCHEMA_VERSION, PLATFORM_SANDBOX_DRAIN_KEY, PLATFORM_USAGE_PROTOCOL_VERSION, createApplicationRoutes, createPlatformDeploymentManifest, createPlatformDiscoveryDocument, createPlatformInstallationManifest, createPlatformResourceNames, createPlatformResourceOwnershipMarker, createPlatformWorkerConfigs, isPlatformSignupAllowed, normalizeApplicationDomain, normalizeInstallationSlug, parsePlatformAccessProtection, parsePlatformAdmissionPolicy, parsePlatformAuthenticationSetup, parsePlatformDeploymentManifest, parsePlatformDiscoveryDocument, parsePlatformIdentityUrl, parsePlatformInstallationManifest, parsePlatformLoginConfiguration, parsePlatformLoginDescriptor, parsePlatformLoginId, parsePlatformResourceOwnershipMarker, parsePlatformSignupAllowlistEntry, platformAuthenticationRecoveryMessage, platformProjectHostname, platformProjectHostnames, platformProjectIngressName, platformProjectWorkersDevHostname, platformProtectionProofMessage, platformWorkersDevAliasKey, readPlatformApplication, recordInstallationResource, recordInstallationStep, resolvePlatformApplicationEnvironment, setInstallationDesiredState, setInstallationEndpoints, transitionInstallation, validatePlatformAdmissionPolicy };\n", "const DEFAULT_FONT_STACK =\n 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif';\n\nfunction escapeHtml(value: string): string {\n return value\n .replaceAll('&', '&')\n .replaceAll('<', '<')\n .replaceAll('>', '>')\n .replaceAll('\"', '"');\n}\n\nfunction renderDefaultErrorPage(status: number, title: string): string {\n const heading = `${status}: ${title}`;\n const prefix = `${status}: `;\n\n return `<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <title>${escapeHtml(heading)}</title>\n <style>\n :root {\n color-scheme: light;\n font-family: ${DEFAULT_FONT_STACK};\n background: #f5f5f5;\n color: #171717;\n }\n\n * {\n box-sizing: border-box;\n }\n\n body {\n margin: 0;\n min-block-size: 100dvh;\n display: grid;\n place-items: center;\n padding: 24px;\n background:\n radial-gradient(circle at top, rgba(255, 255, 255, 0.96), rgba(245, 245, 245, 0.96) 52%),\n linear-gradient(180deg, #fafafa 0%, #f1f1f1 100%);\n font: 500 16px/1.5 ${DEFAULT_FONT_STACK};\n }\n\n main {\n inline-size: min(100%, 560px);\n padding: 32px 36px;\n border: 1px solid #d4d4d8;\n border-radius: 32px;\n corner-shape: squircle;\n background: rgba(255, 255, 255, 0.88);\n text-align: center;\n backdrop-filter: blur(12px);\n }\n\n h1 {\n margin: 0;\n font: 400 clamp(1.5rem, 1.2rem + 1vw, 2rem) / 1.1 ${DEFAULT_FONT_STACK};\n letter-spacing: -0.03em;\n }\n\n strong {\n font-weight: 600;\n }\n </style>\n </head>\n <body>\n <main>\n <h1><strong>${escapeHtml(prefix)}</strong>${escapeHtml(title)}</h1>\n </main>\n </body>\n</html>`;\n}\n\nexport function shouldServeHtmlErrorPage(request: Request): boolean {\n if (request.method !== 'GET' && request.method !== 'HEAD') {\n return false;\n }\n\n const url = new URL(request.url);\n if (url.pathname === '/api' || url.pathname.startsWith('/api/')) {\n return false;\n }\n if (/\\/[^/]+\\.[^/]+$/.test(url.pathname)) {\n return false;\n }\n\n const destination = request.headers.get('sec-fetch-dest');\n if (destination && destination !== 'document' && destination !== 'empty') {\n return false;\n }\n\n const accept = request.headers.get('accept');\n return !accept || accept.includes('text/html') || accept.includes('*/*');\n}\n\nexport function createErrorResponse(\n request: Request,\n status: number,\n title: string,\n headers?: HeadersInit,\n): Response {\n if (!shouldServeHtmlErrorPage(request)) {\n return new Response(title, { status, headers });\n }\n\n const responseHeaders = new Headers(headers);\n responseHeaders.set('content-type', 'text/html; charset=utf-8');\n return new Response(request.method === 'HEAD' ? null : renderDefaultErrorPage(status, title), {\n status,\n headers: responseHeaders,\n });\n}\n", "/**\n * Shared path-pattern compiler used by header rules and routing rules.\n *\n * Syntax:\n * `:name` \u2014 single path segment, captured as `name`\n * `:name*` \u2014 zero or more path segments, captured as `name`\n * `*` \u2014 zero or more path segments, captured as `splat` (legacy)\n *\n * When a legacy pattern contains multiple anonymous `*`, the first captures\n * as `splat` and later wildcards are non-capturing. Boolean matching remains\n * backward compatible for existing header/revalidate patterns.\n */\n\nconst MAX_CACHE = 256;\n\nexport type CompiledPattern = Readonly<{\n regex: RegExp;\n paramNames: ReadonlyArray<string>;\n}>;\n\nconst compileCache = new Map<string, CompiledPattern>();\n\nconst REGEX_SPECIAL = /[.+?^${}()|[\\]\\\\]/;\nconst PARAM_CHAR = /[A-Za-z0-9_]/;\n\nexport function compilePattern(source: string): CompiledPattern {\n const cached = compileCache.get(source);\n if (cached) {\n // LRU touch: re-inserting moves the entry to the most-recently-used end\n // of Map iteration order, so eviction below removes the true LRU.\n compileCache.delete(source);\n compileCache.set(source, cached);\n return cached;\n }\n\n const paramNames: Array<string> = [];\n let legacySplatCaptured = false;\n let pattern = '';\n let index = 0;\n while (index < source.length) {\n const character = source[index]!;\n if (character === ':') {\n let nameEnd = index + 1;\n while (nameEnd < source.length && PARAM_CHAR.test(source[nameEnd]!)) {\n nameEnd++;\n }\n const name = source.slice(index + 1, nameEnd);\n if (!name) {\n pattern += '\\\\:';\n index++;\n continue;\n }\n if (source[nameEnd] === '*') {\n paramNames.push(name);\n pattern += `(?<${name}>.*)`;\n index = nameEnd + 1;\n } else {\n paramNames.push(name);\n pattern += `(?<${name}>[^/]+)`;\n index = nameEnd;\n }\n } else if (character === '*') {\n if (legacySplatCaptured) {\n pattern += `.*`;\n } else {\n paramNames.push('splat');\n pattern += `(?<splat>.*)`;\n legacySplatCaptured = true;\n }\n index++;\n } else {\n if (REGEX_SPECIAL.test(character)) {\n pattern += '\\\\';\n }\n pattern += character;\n index++;\n }\n }\n\n const compiled: CompiledPattern = { regex: new RegExp(`^${pattern}$`), paramNames };\n if (compileCache.size >= MAX_CACHE) {\n const first = compileCache.keys().next();\n if (!first.done) {\n compileCache.delete(first.value);\n }\n }\n compileCache.set(source, compiled);\n return compiled;\n}\n\n/**\n * Match a pattern against a pathname. Returns captured params, or null.\n *\n * Returns null (rather than throwing) when the pattern itself is malformed \u2014\n * e.g. multiple `*` producing duplicate `splat` capture names. Framework and\n * API ingest both reject those, but a hand-crafted manifest could still reach\n * the edge, and a single bad rule shouldn't 500 unrelated traffic.\n */\nexport function matchPatternCaptures(\n pattern: string,\n pathname: string,\n): Record<string, string> | null {\n let compiled: CompiledPattern;\n try {\n compiled = compilePattern(pattern);\n } catch {\n return null;\n }\n const match = compiled.regex.exec(pathname);\n if (!match) {\n return null;\n }\n return match.groups ?? {};\n}\n\n/**\n * Match a pattern against a pathname (boolean form). Header-rule callers only\n * need a yes/no \u2014 they don't care about captures. Malformed patterns yield\n * `false` rather than throwing (see `matchPatternCaptures`).\n */\nexport function matchPattern(pattern: string, pathname: string): boolean {\n try {\n return compilePattern(pattern).regex.test(pathname);\n } catch {\n return false;\n }\n}\n\nconst literalRegexCache = new Map<string, RegExp>();\n\n/**\n * Match a pattern against a pathname using LITERAL semantics \u2014 no named\n * captures. Only `*` is special (matches any characters including `/`); every\n * other character (including `:`) is treated as a literal.\n *\n * This preserves the pre-`feat/rewrites` semantics of header rules,\n * `routing.revalidate` keys, and `routing.revalidateQueryAllowlist` keys \u2014\n * those callers never had `:name` capture syntax and existing tenant configs\n * may include literal `:` (e.g. `/api/v1:health`, `:batchGet`-style URLs).\n *\n * The capture-aware `matchPattern` above continues to be used by routing\n * rules (`redirects`/`rewrites`/`fallbacks`) where `:name` capture syntax was\n * intentionally introduced (see design-doc 0064).\n */\nexport function matchLiteralPattern(pattern: string, pathname: string): boolean {\n let regex = literalRegexCache.get(pattern);\n if (regex) {\n // LRU touch \u2014 same scheme as the legacy header matcher.\n literalRegexCache.delete(pattern);\n literalRegexCache.set(pattern, regex);\n } else {\n try {\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&').replaceAll('*', '.*');\n regex = new RegExp(`^${escaped}$`);\n } catch {\n return false;\n }\n if (literalRegexCache.size >= MAX_CACHE) {\n const first = literalRegexCache.keys().next();\n if (!first.done) {\n literalRegexCache.delete(first.value);\n }\n }\n literalRegexCache.set(pattern, regex);\n }\n try {\n return regex.test(pathname);\n } catch {\n return false;\n }\n}\n\nconst segmentRegexCache = new Map<string, RegExp>();\n\n/**\n * Match a REVALIDATE ROUTE pattern against a pathname using SEGMENT-ANCHORED\n * semantics. Like `matchLiteralPattern` except a WHOLE-SEGMENT `:name` (a `:`\n * right after `/` or at the start of the pattern, whose name is any non-empty\n * run of non-`/` characters \u2014 NOT just JS-identifier chars, so `:post-id`,\n * `:post.id`, etc. all anchor \u2014 running up to the next `/` or end of string)\n * matches exactly ONE non-empty path segment (`[^/]+`). A whole-segment NAMED\n * CATCH-ALL `:name{.+}` (a named catch-all page `[...path]` \u2192 `/docs/:path{.+}`)\n * matches ONE-OR-MORE characters that MAY cross `/` (`.+`, so `/docs/a` and\n * `/docs/a/b` both match, but bare `/docs` / `/docs/` do NOT). Only the exact\n * `{.+}` constraint widens \u2014 a REGEX-constrained param like `:path{[0-9]+}`\n * keeps its single-segment `[^/]+` meaning. `*` still expands to a catch-all\n * that crosses `/`. A mid-segment `:` (e.g. `/api/v1:health`,\n * `/api/documents:batchGet`) stays a LITERAL \u2014 only whole-segment `:name` /\n * `:name{.+}` anchors.\n *\n * This is for `routing.revalidate` keys ONLY. Those keys are machine-generated\n * from page routes on the deploy write side (`[slug]` \u2192 `/blog/:slug`,\n * `[...path]` \u2192 `/docs/:path{.+}`), so the `:name` here is a real route param\n * and MUST bind the same way the framework's own client route matcher\n * (`patternToRegex` in `pages/manifest.ts`) binds it \u2014 matching the write-side\n * matcher in `packages/api/src/routes/deploy.ts`.\n *\n * It is intentionally NOT used for user-authored header rules\n * (`applyHeaderRules`) or `revalidateQueryAllowlist` keys\n * (`buildVariantOriginalUrl`), where `:name` must stay a literal \u2014 those keep\n * using `matchLiteralPattern`. Sharing the segment behaviour there would make a\n * user rule like `/:batchGet` over-match every single-segment path.\n *\n * NOTE: this matcher has its OWN regex cache \u2014 the same pattern string compiles\n * to a DIFFERENT regex than `matchLiteralPattern` produces, so the caches must\n * not be shared or they would cross-contaminate.\n */\nexport function matchSegmentPattern(pattern: string, pathname: string): boolean {\n let regex = segmentRegexCache.get(pattern);\n if (regex) {\n // LRU touch \u2014 same scheme as the literal matcher.\n segmentRegexCache.delete(pattern);\n segmentRegexCache.set(pattern, regex);\n } else {\n try {\n // Two private-use sentinels stand in for route params so the regex-special\n // escape step below can't touch the classes we swap in last:\n // \\uE000 - a whole-segment `:name` -> one path segment (`[^/]+`)\n // \\uE001 - a named catch-all `:name{.+}` -> >=1 char, crosses `/` (`.+`)\n // The named-catch-all rule runs FIRST so `:name{.+}` is consumed as a unit\n // before the plain `:name` rule can grab `:name` and strand the `{.+}`. The\n // `{.+}` name class is `[^/{}]+` (excludes braces) so a REGEX-constrained\n // param like `:path{[0-9]+}` does NOT match and stays a single segment.\n const escaped = pattern\n .replace(/(^|\\/):[^/{}]+\\{\\.\\+\\}(?=\\/|$)/g, '$1\\uE001') // named catch-all :name{.+} -> catch-all sentinel\n .replace(/(^|\\/):[^/]+(?=\\/|$)/g, '$1\\uE000') // whole-segment :name -> segment sentinel\n .replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&') // escape regex specials\n .replaceAll('*', '.*') // legacy `*` crosses '/'\n .replaceAll('\\uE000', '[^/]+') // segment sentinel -> one segment\n .replaceAll('\\uE001', '.+'); // catch-all sentinel -> >=1 char, crosses '/'\n regex = new RegExp(`^${escaped}$`);\n } catch {\n return false;\n }\n if (segmentRegexCache.size >= MAX_CACHE) {\n const first = segmentRegexCache.keys().next();\n if (!first.done) {\n segmentRegexCache.delete(first.value);\n }\n }\n segmentRegexCache.set(pattern, regex);\n }\n try {\n return regex.test(pathname);\n } catch {\n return false;\n }\n}\n\n/**\n * Substitute `:name` and `:name*` tokens in a destination string with the\n * matching named captures from `params`. `:splat` works for legacy `*` patterns\n * because `compilePattern` captures anonymous `*` as `splat`.\n */\nexport function substituteParams(destination: string, params: Record<string, string>): string {\n return destination.replace(/:([A-Za-z0-9_]+)\\*?/g, (whole, name: string) => {\n return params[name] ?? whole;\n });\n}\n", "import type { HeaderRule } from '@void/deploy-core';\nimport { matchLiteralPattern } from './pattern.ts';\n\nexport type { HeaderRule } from '@void/deploy-core';\n\nexport type HeaderRulePolicy = Readonly<{\n /**\n * Protect unrelated tenants that share one registrable domain. Direct\n * deployments own their hostname and may safely use cookie header rules.\n */\n cookieIsolation?: 'shared-domain' | 'origin';\n}>;\n\n/**\n * Headers that user header rules may not set at all, because they are always a\n * cookie operation. On the shared *.void.app domain (not on the PSL) void.app\n * is the registrable domain, so a `Set-Cookie` with `Domain=.void.app` is\n * readable by every tenant's subdomain. Dropped wholesale.\n *\n * `Clear-Site-Data` is the other cookie trust-boundary header, but it is NOT a\n * blanket block \u2014 see {@link sanitizeClearSiteData}: only its cookie-clearing\n * directives are stripped, since its other directives are origin-scoped.\n *\n * HSTS and other per-host headers are safe \u2014 they don't cross subdomain\n * boundaries (includeSubDomains scopes to the responding host's subtree).\n *\n * TODO: Once void.app is registered on the Public Suffix List, these defenses\n * can be removed \u2014 browsers will scope cross-subdomain cookies automatically.\n */\nconst BLOCKED_HEADERS = new Set(['set-cookie']);\n\n/** A single member of a `Clear-Site-Data` list. */\nexport type ClearSiteDataMember = Readonly<{\n /** The member text, trimmed of surrounding whitespace; kept for re-serialization. */\n raw: string;\n /**\n * The quoted-string content (original case) when the member is a well-formed\n * quoted-string, else `null`. A browser ignores members that are not\n * well-formed quoted-strings.\n */\n directive: string | null;\n}>;\n\n/**\n * Parse one list member into its quoted-string content, or `null` when it is not\n * a well-formed quoted-string. Implements RFC 7230's\n * `quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE`: it must be wrapped\n * in double quotes, a backslash escapes the next character, and an unescaped\n * inner quote (or a dangling escape) is malformed.\n */\nfunction parseQuotedString(member: string): string | null {\n if (member.length < 2 || member[0] !== '\"' || member[member.length - 1] !== '\"') {\n return null;\n }\n let content = '';\n for (let i = 1; i < member.length - 1; i += 1) {\n const char = member[i];\n if (char === '\\\\') {\n // quoted-pair: take the next character literally.\n i += 1;\n if (i >= member.length - 1) {\n return null; // trailing backslash before the closing quote\n }\n content += member[i];\n } else if (char === '\"') {\n return null; // unescaped quote before the end\n } else {\n content += char;\n }\n }\n return content;\n}\n\n/**\n * Parse a `Clear-Site-Data` header value into its list members. The value is a\n * comma-separated list of quoted-strings (W3C Clear-Site-Data); a comma inside a\n * quoted-string does not split a member. Empty members are dropped.\n */\nexport function parseClearSiteData(value: string): Array<ClearSiteDataMember> {\n const members: Array<ClearSiteDataMember> = [];\n const pushMember = (slice: string): void => {\n const raw = slice.trim();\n if (raw.length > 0) {\n members.push({ raw, directive: parseQuotedString(raw) });\n }\n };\n\n let start = 0;\n let inQuotes = false;\n for (let i = 0; i < value.length; i += 1) {\n const char = value[i];\n if (inQuotes) {\n if (char === '\\\\') {\n i += 1; // skip the escaped character so an escaped quote stays in-string\n } else if (char === '\"') {\n inQuotes = false;\n }\n } else if (char === '\"') {\n inQuotes = true;\n } else if (char === ',') {\n pushMember(value.slice(start, i));\n start = i + 1;\n }\n }\n pushMember(value.slice(start));\n return members;\n}\n\n/**\n * Sanitize a `Clear-Site-Data` value so a tenant rule can't clear cookies across\n * the shared *.void.app boundary, while still allowing the safe directives.\n *\n * Only `\"cookies\"` and `\"*\"` clear cookies for the registrable domain (and thus\n * every tenant's subdomain). `\"cache\"`, `\"storage\"`, `\"executionContexts\"`, and\n * any future quoted directive are origin-scoped \u2014 each subdomain is its own\n * origin \u2014 so they are kept verbatim. Malformed members are dropped (a browser\n * ignores them, and dropping forecloses a lenient parser honoring them).\n *\n * Returns the filtered value, or `null` when nothing safe remains: a `\"*\"`\n * includes cookies and can't be expressed without them, and a value that is only\n * `\"cookies\"` collapses to empty.\n */\nexport function sanitizeClearSiteData(value: string): string | null {\n const kept: Array<string> = [];\n for (const { raw, directive } of parseClearSiteData(value)) {\n const normalized = directive?.toLowerCase();\n if (normalized === '*') {\n return null;\n }\n if (directive === null || normalized === 'cookies') {\n continue;\n }\n kept.push(raw);\n }\n return kept.length > 0 ? kept.join(', ') : null;\n}\n\n/**\n * Apply matching header rules to a response.\n * All matching rules merge; last match wins for same header name.\n * Returns the original response unchanged when no rules or no matches.\n */\nexport function applyHeaderRules(\n response: Response,\n pathname: string,\n rules?: ReadonlyArray<HeaderRule>,\n policy?: HeaderRulePolicy,\n): Response {\n if (!rules || rules.length === 0) {\n return response;\n }\n\n const matched: Array<[string, string]> = [];\n for (const rule of rules) {\n if (matchLiteralPattern(rule.pattern, pathname)) {\n matched.push(...rule.headers);\n }\n }\n\n if (matched.length === 0) {\n return response;\n }\n\n // Clone response to modify headers\n const newResponse = new Response(response.body, response);\n // Fallback for a Clear-Site-Data rule that sanitizes to nothing: last-match-wins\n // means such a rule discards an earlier rule's value, so we fall back to the\n // origin's own Clear-Site-Data rather than leaving the earlier rule's value\n // behind. It is sanitized too, so rule processing never *resurfaces* a\n // cross-tenant cookie directive \u2014 not from a rule, and not from the origin\n // response either. (The origin's own header is otherwise ungated here; gating\n // it across the board is a separate dispatch-layer concern.)\n const isolateSharedDomainCookies = policy?.cookieIsolation !== 'origin';\n const rawOriginClearSiteData = isolateSharedDomainCookies\n ? response.headers.get('clear-site-data')\n : null;\n const originClearSiteData =\n rawOriginClearSiteData === null ? null : sanitizeClearSiteData(rawOriginClearSiteData);\n for (const [name, value] of matched) {\n const lowerName = name.toLowerCase();\n if (isolateSharedDomainCookies && BLOCKED_HEADERS.has(lowerName)) {\n continue;\n }\n if (isolateSharedDomainCookies && lowerName === 'clear-site-data') {\n const safe = sanitizeClearSiteData(value);\n if (safe !== null) {\n newResponse.headers.set(name, safe);\n } else if (originClearSiteData !== null) {\n newResponse.headers.set(name, originClearSiteData);\n } else {\n newResponse.headers.delete(name);\n }\n continue;\n }\n newResponse.headers.set(name, value);\n }\n\n return newResponse;\n}\n", "import type { RedirectRule } from '@void/deploy-core';\nimport { compilePattern, substituteParams } from './pattern.ts';\n\nexport type { RedirectRule } from '@void/deploy-core';\n\nexport type RoutingRuleResult =\n | { type: 'redirect'; destination: string; status: number }\n | { type: 'rewrite'; destination: string };\n\n/**\n * Check routing rules (redirects + rewrites) against a request pathname.\n *\n * **First match wins** \u2014 matches Netlify `_redirects` and Vercel `vercel.json`\n * semantics: users put more-specific rules above more-general ones, and the\n * first rule whose source matches takes effect. (Header rules in this same\n * package use last-match-wins for compatibility with Netlify `_headers`,\n * which is the opposite of `_redirects`. The asymmetry is intentional.)\n *\n * `requestHost` is the WHATWG `url.hostname` (lowercase, port-stripped).\n * Rules with a `host` field are skipped when `rule.host !== requestHost`;\n * path-only rules apply to every host bound to the project.\n *\n * Returns a discriminated result. The caller is responsible for building the\n * actual `Response` for redirects (so it can merge the request's query string\n * into the `Location` header).\n */\nexport function applyRoutingRules(\n pathname: string,\n rules?: ReadonlyArray<RedirectRule>,\n requestHost?: string,\n): RoutingRuleResult | null {\n if (!rules?.length) {\n return null;\n }\n\n for (const rule of rules) {\n if (rule.host && rule.host !== requestHost) {\n continue;\n }\n let regex: RegExp;\n try {\n ({ regex } = compilePattern(rule.source));\n } catch (err) {\n // A malformed `source` (e.g. duplicate named params) throws inside\n // `new RegExp`. Framework validation rejects those at build, but a\n // hand-crafted manifest could still reach the edge. Skip the offending\n // rule and continue rather than 500ing the whole request.\n console.warn(\n `[dispatch] skipping routing rule with invalid source ${JSON.stringify(rule.source)}: ${err instanceof Error ? err.message : String(err)}`,\n );\n continue;\n }\n const match = regex.exec(pathname);\n if (!match) {\n continue;\n }\n\n const destination = substituteParams(rule.destination, match.groups ?? {});\n\n if (rule.status === 200) {\n return { type: 'rewrite', destination };\n }\n\n return { type: 'redirect', destination, status: rule.status };\n }\n\n return null;\n}\n\n/**\n * Merge a request's query string into a redirect destination.\n *\n * If the destination already contains a `?`, its parameters take precedence\n * over the request's. Otherwise the request's query is appended verbatim.\n *\n * A `#fragment` on the destination is stripped before the merge and\n * re-appended afterwards, so `/new#faq` + `?utm=x` becomes `/new?utm=x#faq`\n * rather than `/new#faq?utm=x` (which browsers treat as fragment text).\n */\nexport function mergeQueryIntoLocation(destination: string, requestSearch: string): string {\n if (!requestSearch || requestSearch === '?') {\n return destination;\n }\n const fragIdx = destination.indexOf('#');\n const base = fragIdx === -1 ? destination : destination.slice(0, fragIdx);\n const fragment = fragIdx === -1 ? '' : destination.slice(fragIdx);\n\n const destQueryIdx = base.indexOf('?');\n if (destQueryIdx === -1) {\n return base + requestSearch + fragment;\n }\n if (destQueryIdx === base.length - 1) {\n return base.slice(0, destQueryIdx) + fragment;\n }\n const reqParams = new URLSearchParams(requestSearch);\n const destParams = new URLSearchParams(base.slice(destQueryIdx + 1));\n for (const [key, value] of reqParams) {\n if (!destParams.has(key)) {\n destParams.append(key, value);\n }\n }\n return base.slice(0, destQueryIdx) + '?' + destParams.toString() + fragment;\n}\n", "import type { AssetConfig } from '@void/deploy-core';\n\nexport type { AssetConfig } from '@void/deploy-core';\n\nexport type ResolvedAsset = Readonly<{\n path: string;\n hash: string;\n redirect?: string;\n notFound?: boolean;\n spa?: boolean;\n}>;\n\n/**\n * Percent-decode a request pathname for a manifest lookup, honoring ONLY the\n * encodings a conformant URL is required to use. Returns the raw value\n * unchanged on a malformed sequence (e.g. a lone `%`) or on any non-canonical /\n * over-encoded spelling.\n *\n * Request pathnames arrive percent-encoded \u2014 WHATWG `URL.pathname` never\n * decodes \u2014 but manifest keys are the asset's decoded on-disk path (a file\n * named `oxc masthead.riv` is stored under `/assets/oxc masthead.riv`, not\n * `%20`). Callers try the raw key first, then this decoded form.\n *\n * The decoded form is accepted only when re-encoding it reproduces the request\n * path (up to percent-escape letter case) \u2014 i.e. the only encoded bytes were\n * characters a URL MUST encode (space, `#`, non-ASCII, \u2026). This rejects\n * over-encoded spellings of ordinary path text (`%2F`\u2192`/`, `%61`\u2192`a`, `%5F`\u2192`_`,\n * `%2e%2e`\u2192`..`), which a browser would never send and which would otherwise let\n * a request reconstruct a guarded path (`/assets%2Fx`, `/%61ssets/x`,\n * `/%5F%5Fvoid/x`) and serve the manifest entry while the raw-`url.pathname`\n * policy gates \u2014 the `/__void/*` reserved-route block, the hashed-asset prefix\n * gate, and the header/redirect rules \u2014 never fire. The URL pathname setter\n * applies exactly the WHATWG \"path percent-encode set\", making it the canonical\n * re-encoder.\n *\n * Known limitation: a file whose name contains a literal `%` (e.g. `logo%20.svg`,\n * requested as `logo%2520.svg`) is not resolved \u2014 the path encoder leaves `%`\n * as-is, so the round-trip can't reproduce the double-escaped request. Such\n * names 404'd before this change too, so this is not a regression.\n */\nexport function safeDecodePathname(pathname: string): string {\n let decoded: string;\n try {\n decoded = decodeURIComponent(pathname);\n } catch {\n return pathname;\n }\n if (decoded === pathname) {\n return pathname;\n }\n const canonical = reencodePathname(decoded);\n if (canonical === null) {\n return pathname;\n }\n // Compare up to percent-escape letter case: the URL encoder emits upper-case\n // (`%C3`), but a client may send lower-case (`%c3`), and both are valid.\n return normalizePercentCase(canonical) === normalizePercentCase(pathname) ? decoded : pathname;\n}\n\n/** Uppercase the hex digits of every `%xx` escape so encodings compare equal\n * regardless of the letter case a client used. */\nfunction normalizePercentCase(pathname: string): string {\n return pathname.replace(/%[0-9a-fA-F]{2}/g, (escape) => escape.toUpperCase());\n}\n\n/**\n * Serialize a decoded path back to a safe URL pathname via the WHATWG \"path\n * percent-encode set\" (the `URL.pathname` setter). Returns null if the value\n * can't be encoded. Used to canonicalize the decoded lookup key and to make a\n * redirect Location URL-safe.\n */\nfunction reencodePathname(pathname: string): string | null {\n try {\n const encoder = new URL('https://void.invalid/');\n encoder.pathname = pathname;\n return encoder.pathname;\n } catch {\n return null;\n }\n}\n\n/**\n * Match a pathname against the manifest via exact match + html_handling rules\n * (no not-found fallback). Returns null when nothing matches.\n */\nfunction matchManifestEntry(\n pathname: string,\n manifest: Record<string, string>,\n htmlHandling: NonNullable<AssetConfig['html_handling']>,\n): ResolvedAsset | null {\n // Exact match always wins\n if (manifest[pathname]) {\n return { path: pathname, hash: manifest[pathname] };\n }\n\n switch (htmlHandling) {\n case 'auto-trailing-slash': {\n // Try appending .html first (preferred over /index.html)\n const withHtml = pathname + '.html';\n if (manifest[withHtml]) {\n return { path: withHtml, hash: manifest[withHtml] };\n }\n // Try /index.html\n const withIndex = (pathname.endsWith('/') ? pathname : pathname + '/') + 'index.html';\n if (manifest[withIndex]) {\n return { path: withIndex, hash: manifest[withIndex] };\n }\n break;\n }\n case 'force-trailing-slash': {\n // If path doesn't end with /, redirect to trailing slash version\n if (!pathname.endsWith('/') && pathname !== '/') {\n const withIndex = pathname + '/index.html';\n if (manifest[withIndex]) {\n return {\n path: withIndex,\n hash: manifest[withIndex],\n redirect: pathname + '/',\n };\n }\n }\n // Serve /path/ from /path/index.html\n const indexPath = pathname + 'index.html';\n if (manifest[indexPath]) {\n return { path: indexPath, hash: manifest[indexPath] };\n }\n break;\n }\n case 'drop-trailing-slash': {\n // Root path: serve /index.html directly\n if (pathname === '/') {\n if (manifest['/index.html']) {\n return { path: '/index.html', hash: manifest['/index.html'] };\n }\n break;\n }\n // If path ends with /, redirect to non-trailing-slash version\n if (pathname.endsWith('/')) {\n const withoutSlash = pathname.slice(0, -1);\n const withHtml = withoutSlash + '.html';\n if (manifest[withHtml]) {\n return {\n path: withHtml,\n hash: manifest[withHtml],\n redirect: withoutSlash,\n };\n }\n }\n // Serve /path from /path.html\n const withHtml = pathname + '.html';\n if (manifest[withHtml]) {\n return { path: withHtml, hash: manifest[withHtml] };\n }\n break;\n }\n case 'none':\n break;\n }\n\n return null;\n}\n\n/**\n * Resolve a request pathname to a manifest entry using AssetConfig rules.\n * Replicates Cloudflare Workers Assets path resolution behavior.\n */\nexport function resolveStaticPath(\n pathname: string,\n manifest: Record<string, string>,\n config: AssetConfig,\n): ResolvedAsset | null {\n const htmlHandling = config.html_handling ?? 'auto-trailing-slash';\n\n // Try the raw (percent-encoded) path first \u2014 the fast path, and it lets a\n // filename that literally contains a `%` win. On a miss, retry with the\n // decoded path so a file named e.g. `a b.txt` resolves for an `a%20b.txt`\n // request (manifest keys are decoded on-disk paths).\n let matched = matchManifestEntry(pathname, manifest, htmlHandling);\n if (!matched) {\n const decoded = safeDecodePathname(pathname);\n if (decoded !== pathname) {\n matched = matchManifestEntry(decoded, manifest, htmlHandling);\n if (matched?.redirect !== undefined) {\n // The Location was derived from the decoded path; serialize it back to\n // a safe URL pathname (`/docs/a#b/` \u2192 `/docs/a%23b/`) so the client\n // doesn't read `#`/space/etc. as URL structure.\n const safeRedirect = reencodePathname(matched.redirect);\n if (safeRedirect !== null) {\n matched = { ...matched, redirect: safeRedirect };\n }\n }\n }\n }\n if (matched) {\n return matched;\n }\n\n // Not found handling\n switch (config.not_found_handling ?? 'none') {\n case 'single-page-application':\n if (manifest['/index.html']) {\n return {\n path: '/index.html',\n hash: manifest['/index.html'],\n spa: true,\n };\n }\n break;\n case '404-page':\n if (manifest['/404.html']) {\n return {\n path: '/404.html',\n hash: manifest['/404.html'],\n notFound: true,\n };\n }\n break;\n }\n\n return null;\n}\n\nconst MIME_TYPES: Record<string, string> = {\n html: 'text/html; charset=utf-8',\n htm: 'text/html; charset=utf-8',\n css: 'text/css; charset=utf-8',\n js: 'text/javascript; charset=utf-8',\n mjs: 'text/javascript; charset=utf-8',\n json: 'application/json; charset=utf-8',\n xml: 'application/xml; charset=utf-8',\n svg: 'image/svg+xml; charset=utf-8',\n txt: 'text/plain; charset=utf-8',\n csv: 'text/csv; charset=utf-8',\n md: 'text/markdown; charset=utf-8',\n markdown: 'text/markdown; charset=utf-8',\n yaml: 'text/yaml; charset=utf-8',\n yml: 'text/yaml; charset=utf-8',\n toml: 'application/toml',\n png: 'image/png',\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n gif: 'image/gif',\n ico: 'image/x-icon',\n webp: 'image/webp',\n avif: 'image/avif',\n woff: 'font/woff',\n woff2: 'font/woff2',\n ttf: 'font/ttf',\n otf: 'font/otf',\n eot: 'application/vnd.ms-fontobject',\n pdf: 'application/pdf',\n wasm: 'application/wasm',\n webmanifest: 'application/manifest+json; charset=utf-8',\n map: 'application/json; charset=utf-8',\n mp4: 'video/mp4',\n webm: 'video/webm',\n mp3: 'audio/mpeg',\n ogg: 'audio/ogg',\n};\n\n/**\n * Get the Content-Type header value for a given file path based on its extension.\n */\nexport function getContentType(path: string): string {\n const ext = path.split('.').pop()?.toLowerCase() ?? '';\n return MIME_TYPES[ext] ?? 'application/octet-stream';\n}\n\n/**\n * Resolve the Content-Type to serve for a stored asset, reconciling the value\n * persisted at upload time (R2 `httpMetadata.contentType` / KV `ct` metadata)\n * with a fresh path-based lookup. Returns `undefined` when no Content-Type\n * header should be emitted.\n *\n * `application/null` is a sentinel (matching Wrangler) meaning \"omit the\n * Content-Type header entirely\".\n *\n * `application/octet-stream` is the uploader's no-information default: older\n * CLI versions stamped it on any extension their MIME table did not recognize\n * (e.g. `.md`). Because assets are content-addressed and never re-uploaded,\n * those stale octet-stream values can't be corrected at the source, so we\n * treat a stored octet-stream as \"unknown\" and re-derive from the path here.\n * Any other stored value is authoritative and honored as-is.\n */\nexport function resolveAssetContentType(\n stored: string | null | undefined,\n path: string,\n): string | undefined {\n if (stored === 'application/null') {\n return undefined;\n }\n if (!stored || stored === 'application/octet-stream') {\n return getContentType(path);\n }\n return stored;\n}\n", "/**\n * Shared ISR key/URL helpers used by both the API (purge) and the dispatch\n * worker (read/write). These functions MUST produce byte-identical output:\n * the API purges KV keys and edge URLs that dispatch writes and reads.\n *\n * Dispatch derives the deployment id for its keys via\n * `routing.version ?? 'legacy'`, which allows any non-nullish value \u2014\n * including the empty string \u2014 to pass through unchanged. The helpers below\n * preserve that shape so the API can compute the exact same key for purge.\n */\n\nconst ISR_CACHE_KEY_VERSION = 'v3';\n\n/**\n * Previous key version. `v3` keys are ALWAYS host-scoped\n * (`<proj>/isr/v3/<D>/<host>/<path>`); `v2` keys are ALWAYS hostless\n * (`<proj>/isr/v2/<D>/<path>`) \u2014 the `<host>` segment did not exist yet.\n *\n * The bump to `v3` was forced by a real aliasing hazard: under a single\n * version, a host-scoped key `<D>/<host>/<path>` and a legacy hostless key\n * `<D>/<host>/<path>` are byte-identical whenever the legacy path's leading\n * segment happens to look like a hostname. Dotted leading path segments are\n * legal (`[domain]` \u2192 `:domain`, `[...slug]` \u2192 `(.+)`), so a hostless key for\n * the page `/example.com/about` collides exactly with the host-scoped key for\n * `(host=example.com, /about)`. The stored metadata is only `{s,c,t}` (no\n * path/host), so a reader cannot tell them apart and could serve one page's\n * body for the other. Encoding the shape in the version removes the ambiguity:\n * the version alone determines whether a `<host>` segment is present, so no\n * runtime heuristic (e.g. \"is the first segment an attached hostname?\") is\n * needed to classify a key. Package-internal, like `ISR_CACHE_KEY_VERSION`.\n */\nconst ISR_LEGACY_CACHE_KEY_VERSION = 'v2';\n\n/**\n * KV metadata stored alongside every ISR cache entry. This is the single\n * canonical shape shared by the dispatch worker (which writes it on a live\n * miss and reads it back on a hit \u2014 see `dispatch/src/isr.ts`) AND the API\n * prerender-warm path (`api/src/routes/deploy.ts`), which pre-populates the\n * same KV keys during deploy. Both writers MUST use these exact field names:\n * the reader requires `c` (createdAt) and `t` (ttl) and returns null without\n * them, so a writer that drifts (e.g. writes `context` instead of `c`) produces\n * a permanent cold miss that no typecheck would catch unless it is annotated\n * `satisfies IsrCacheMetadata`. Keep the fields terse \u2014 this is stored on every\n * KV entry.\n */\nexport type { IsrCacheMetadata } from './core.ts';\n\n/**\n * Build the normalized path segment for an ISR-cached page.\n * Root path `/` maps to `__index__` to avoid trailing-slash ambiguity.\n */\nexport function normalizeIsrPath(pathname: string): string {\n let normalized = pathname;\n if (normalized === '/') {\n normalized = '__index__';\n } else {\n // Strip leading slash\n normalized = normalized.startsWith('/') ? normalized.slice(1) : normalized;\n // Strip trailing slash\n if (normalized.endsWith('/')) {\n normalized = normalized.slice(0, -1);\n }\n }\n return normalized;\n}\n\n/**\n * Inverse of `normalizeIsrPath`: turn a normalized segment back into a\n * pathname starting with `/`.\n */\nexport function denormalizeIsrPath(normalized: string): string {\n return normalized === '__index__' ? '/' : `/${normalized}`;\n}\n\n/**\n * Canonicalize an inbound pathname to the form used inside edge cache URLs.\n * Equivalent to `denormalizeIsrPath(normalizeIsrPath(pathname))` \u2014 strips any\n * trailing slash except for root.\n */\nexport function canonicalIsrPathname(pathname: string): string {\n return denormalizeIsrPath(normalizeIsrPath(pathname));\n}\n\n/**\n * Prefix shared by every ISR key for a project at the current version \u2014\n * `<projectId>/isr/v3/`. Used internally by `isrCachePrefix`.\n */\nfunction isrCacheVersionPrefix(projectId: string): string {\n return `${projectId}/isr/${ISR_CACHE_KEY_VERSION}/`;\n}\n\n/**\n * Prefix shared by every LEGACY (hostless) ISR key for a project \u2014\n * `<projectId>/isr/v2/`. Used internally by `isrLegacyCachePrefix`.\n */\nfunction isrLegacyCacheVersionPrefix(projectId: string): string {\n return `${projectId}/isr/${ISR_LEGACY_CACHE_KEY_VERSION}/`;\n}\n\n/**\n * Prefix for listing/purging ISR keys.\n *\n * `deploymentId === ''` must still produce the versioned prefix with an\n * empty segment (`<projectId>/isr/v3//`) because dispatch uses\n * `routing.version ?? 'legacy'`, which allows empty strings and writes\n * keys at `<projectId>/isr/v3//<path>`. Only `undefined` selects the\n * legacy scan-all prefix (`<projectId>/isr/`).\n */\nexport function isrCachePrefix(projectId: string, deploymentId?: string): string {\n if (deploymentId !== undefined) {\n return `${isrCacheVersionPrefix(projectId)}${deploymentId}/`;\n }\n return `${projectId}/isr/`;\n}\n\n/**\n * Prefix for listing/purging LEGACY (pre-host-scoping) ISR keys \u2014 the `v2`\n * namespace `<projectId>/isr/v2/<deploymentId>/`. Mirrors `isrCachePrefix`'s\n * optional-`deploymentId` behavior exactly (empty string yields the versioned\n * prefix with an empty segment; only `undefined` selects the scan-all\n * `<projectId>/isr/` prefix).\n *\n * Exists SOLELY for the host-scoping rollout: the purger sweeps this namespace\n * to reap orphaned `v2` KV keys and purge their edge URLs. Current dispatch\n * neither reads nor writes `v2` keys. Transition-only \u2014 remove once `v2`\n * entries have aged out.\n */\nexport function isrLegacyCachePrefix(projectId: string, deploymentId?: string): string {\n if (deploymentId !== undefined) {\n return `${isrLegacyCacheVersionPrefix(projectId)}${deploymentId}/`;\n }\n return `${projectId}/isr/`;\n}\n\n/**\n * Separator that marks the rewrite-variant suffix on an ISR cache key or\n * the corresponding edge-cache URL parameter. `#` cannot appear in\n * `url.pathname` (fragments are stripped before the request reaches the\n * server) and does not survive `normalizeIsrPath`, so it unambiguously\n * identifies the variant suffix.\n */\nconst ISR_VARIANT_SEPARATOR = '#rw=';\n\n/**\n * Build the cache key for an ISR-cached page.\n * ISR is deployment-scoped so cached HTML cannot outlive the hashed assets\n * referenced by the deployment that produced it, and host-scoped (`<host>`\n * segment after the deployment id) so the same path served under different\n * hostnames \u2014 e.g. a project slug and a custom domain, or two custom\n * domains \u2014 never share a cache slot. `host` is the request hostname the\n * dispatch worker saw (`new URL(request.url).hostname`).\n *\n * Host-scoping is a `v3` key format: `<proj>/isr/v3/<D>/<host>/<path>`. The\n * version bump is load-bearing, not cosmetic \u2014 see `ISR_LEGACY_CACHE_KEY_VERSION`.\n * Under a single version, this key would be byte-identical to a legacy hostless\n * key for a page whose leading path segment looks like a hostname (e.g.\n * `(host=example.com, /about)` vs the hostless page `/example.com/about`, both\n * `<D>/example.com/about`). Dotted leading segments are legal, so the collision\n * is reachable. `v3` keys are ALWAYS host-scoped and `v2` keys ALWAYS hostless,\n * so the version segment alone disambiguates the two shapes.\n *\n * When `originalUrl` is provided, the request was served via a dispatch-side\n * rewrite (`redirectRules`/`fallbackRules` with status 200). The original\n * request URL is mixed into the key so a direct hit to `/en/docs` and a\n * rewrite from `/docs` to `/en/docs` do not collide \u2014 user code can branch\n * on `c.isRewritten()` / `c.originalUrl()`, and the cache must honor that.\n * A missing `originalUrl` means \"direct hit\" and produces the legacy\n * rewriteless key (backward-compatible with entries written before this\n * feature landed).\n */\nexport function isrCacheKey(\n projectId: string,\n deploymentId: string,\n host: string,\n pathname: string,\n originalUrl?: string | null,\n): string {\n const base = `${isrCachePrefix(projectId, deploymentId)}${host}/${normalizeIsrPath(pathname)}`;\n if (!originalUrl) {\n return base;\n }\n return `${base}${ISR_VARIANT_SEPARATOR}${hashOriginalUrl(originalUrl)}`;\n}\n\n/**\n * Prefix used to list/purge every variant of a given pathname under a\n * deployment \u2014 both the direct-hit key and any rewrite-variant keys.\n */\nexport function isrCacheVariantPrefix(\n projectId: string,\n deploymentId: string,\n host: string,\n pathname: string,\n): string {\n return `${isrCachePrefix(projectId, deploymentId)}${host}/${normalizeIsrPath(pathname)}${ISR_VARIANT_SEPARATOR}`;\n}\n\n/**\n * Build the exact LEGACY (pre-host-scoping) direct-hit key for a pathname under\n * a deployment: `<projectId>/isr/v2/<deploymentId>/<normalizedPath>` \u2014 the\n * hostless counterpart of `isrCacheKey` with no `<host>/` segment and no\n * rewrite-variant suffix. Used by the purger to reap the orphaned `v2`\n * direct-hit KV key for a requested path.\n *\n * Exists SOLELY for the host-scoping rollout \u2014 current dispatch neither writes\n * nor reads hostless keys. Transition-only. Do not use it on the hot path.\n */\nexport function isrLegacyCacheKey(\n projectId: string,\n deploymentId: string,\n pathname: string,\n): string {\n return `${isrLegacyCachePrefix(projectId, deploymentId)}${normalizeIsrPath(pathname)}`;\n}\n\n/**\n * Prefix used to list/purge the pre-host-scoped (\"legacy\") rewrite variants of\n * a given pathname under a deployment. Before ISR keys grew a `<host>` segment,\n * variant keys were written as\n * `<projectId>/isr/v2/<deploymentId>/<normalizedPath>#rw=<token>` \u2014 identical to\n * `isrCacheVariantPrefix` but with NO `<host>/` segment. Those entries still\n * persist during the host-scoping rollout (ISR puts set no `expirationTtl`),\n * so the purger must scan this hostless `v2` prefix in addition to the\n * host-scoped `v3` one to recover their variant tokens and purge the matching\n * edge URLs.\n *\n * Built off `isrLegacyCachePrefix` (the `v2` namespace), NOT `isrCachePrefix`\n * (now `v3`), so it targets the legacy hostless keys it is meant to sweep.\n *\n * Exists SOLELY for that rollout cleanup \u2014 current dispatch neither writes nor\n * reads hostless keys. Transition-only. Do not use it on the hot path.\n */\nexport function isrLegacyCacheVariantPrefix(\n projectId: string,\n deploymentId: string,\n pathname: string,\n): string {\n return `${isrLegacyCachePrefix(projectId, deploymentId)}${normalizeIsrPath(pathname)}${ISR_VARIANT_SEPARATOR}`;\n}\n\n/**\n * Hash an original-URL value into a fixed-length, opaque variant token.\n * Used as both the KV-key suffix and the `__void_orig` query value, so the\n * writer and purger paths see byte-identical tokens for the same URL.\n *\n * Properties:\n * - Sync (Workers `crypto.subtle.digest` is async; we don't want to push\n * async through every read/write path for this).\n * - 16 hex chars (64 bits) \u2014 bounds the KV key length regardless of input.\n * - Non-recoverable: KV is operator-readable, and the previous base64url\n * encoding let any operator with list access read the original URLs\n * (including sensitive query strings like `?token=\u2026`, `?email=\u2026`).\n * - Not cryptographic: collision resistance is ~2^32 (birthday). Fine for\n * the per-deployment, per-pathname variant set we ever store in one slot.\n *\n * Implementation: FNV-1a 64-bit over UTF-8 bytes. BigInt arithmetic for the\n * multiply (no native u64 in JS), but inputs are short (URLs, sub-1KB) and\n * this only runs once per ISR-touched request.\n */\nconst FNV_OFFSET_BASIS = 0xcbf29ce484222325n;\nconst FNV_PRIME = 0x100000001b3n;\nconst FNV_MASK = 0xffffffffffffffffn;\n\nexport function hashOriginalUrl(originalUrl: string): string {\n const bytes = new TextEncoder().encode(originalUrl);\n let h = FNV_OFFSET_BASIS;\n for (let i = 0; i < bytes.length; i++) {\n h = (h ^ BigInt(bytes[i]!)) & FNV_MASK;\n h = (h * FNV_PRIME) & FNV_MASK;\n }\n return h.toString(16).padStart(16, '0');\n}\n\n/**\n * Split a fully-qualified ISR KV key into the normalized pathname segment\n * and the optional rewrite-variant token. Returns `null` token when the\n * key has no `#rw=` suffix (direct hit).\n *\n * The token is opaque (a hash); the original URL it was derived from is not\n * recoverable. Callers that need to reproduce the matching edge-cache URL\n * pass the token through `isrEdgeCacheUrlForToken`.\n */\nexport function splitIsrCacheKey(fullKey: string): {\n normalizedPath: string;\n variantToken: string | null;\n} {\n const sepIdx = fullKey.indexOf(ISR_VARIANT_SEPARATOR);\n if (sepIdx === -1) {\n return { normalizedPath: fullKey, variantToken: null };\n }\n return {\n normalizedPath: fullKey.slice(0, sepIdx),\n variantToken: fullKey.slice(sepIdx + ISR_VARIANT_SEPARATOR.length),\n };\n}\n\n/**\n * Build the edge cache URL that dispatch uses as its `caches.default` key\n * (wrapped in a GET `Request`). The public URL stays clean; the internal\n * cache key carries the deployment id so a new deploy never reads HTML\n * produced by an older deploy. The `json` variant separates pages-protocol\n * JSON responses from HTML for the same path+deployment.\n *\n * This MUST match the URL dispatch writes. Dispatch builds the URL from\n * `new URL(request.url).hostname`; for standard-port HTTPS traffic (all CF\n * edge traffic) that yields the same origin as the one produced here.\n */\nexport function isrEdgeCacheUrl(\n hostname: string,\n pathname: string,\n deploymentId: string,\n variant: 'html' | 'json',\n originalUrl?: string | null,\n): string {\n return buildIsrEdgeCacheUrl(\n hostname,\n pathname,\n deploymentId,\n variant,\n originalUrl ? hashOriginalUrl(originalUrl) : null,\n );\n}\n\n/**\n * Like `isrEdgeCacheUrl`, but takes a pre-hashed variant token (from\n * `splitIsrCacheKey`). Used by the purger, which only knows the hashed\n * token: the original URL is not recoverable from a KV key.\n */\nexport function isrEdgeCacheUrlForToken(\n hostname: string,\n pathname: string,\n deploymentId: string,\n variant: 'html' | 'json',\n variantToken?: string | null,\n): string {\n return buildIsrEdgeCacheUrl(hostname, pathname, deploymentId, variant, variantToken ?? null);\n}\n\nfunction buildIsrEdgeCacheUrl(\n hostname: string,\n pathname: string,\n deploymentId: string,\n variant: 'html' | 'json',\n variantToken: string | null,\n): string {\n const normalizedPathname = canonicalIsrPathname(pathname);\n const url = new URL(`https://${hostname}${normalizedPathname}`);\n if (variant === 'json') {\n url.searchParams.set('__void', 'json');\n }\n url.searchParams.set('__void_isr', deploymentId);\n if (variantToken) {\n url.searchParams.set('__void_orig', variantToken);\n }\n return url.toString();\n}\n", "import { matchLiteralPattern, matchSegmentPattern } from '@void/edge';\n\n/**\n * Bump when a cached response accepted by an older writer can no longer be\n * proven safe to share. Readers reject entries from earlier policies instead\n * of replaying opaque bodies whose private headers were stripped at write time.\n */\nexport const SHARED_CACHE_POLICY_VERSION = 1 as const;\nexport const SHARED_CACHE_POLICY_HEADER = 'x-void-shared-cache-policy';\n\n/** Stamp an internal edge-cache representation with the policy that admitted it. */\nexport function markSharedCachePolicy(headers: Headers): void {\n headers.set(SHARED_CACHE_POLICY_HEADER, String(SHARED_CACHE_POLICY_VERSION));\n}\n\n/** Reject opaque edge entries admitted before the current privacy policy. */\nexport function hasCurrentSharedCachePolicy(response: Response): boolean {\n return response.headers.get(SHARED_CACHE_POLICY_HEADER) === String(SHARED_CACHE_POLICY_VERSION);\n}\n\nexport type IsrCacheMetadata = Readonly<{\n /** HTTP status code. */\n s: number;\n /** Creation time in milliseconds since the Unix epoch. */\n c: number;\n /** Freshness lifetime in seconds. */\n t: number;\n /** Shared-response privacy policy version. */\n p: typeof SHARED_CACHE_POLICY_VERSION;\n}>;\n\nexport type IsrCacheEntry = Readonly<{\n body: ReadableStream;\n status: number;\n headers: Record<string, string>;\n createdAt: number;\n ttl: number;\n}>;\n\nconst PAGE_DATA_SCRIPT_RE =\n /<script\\b[^>]*\\bid=([\"'])__VOID_PAGE_DATA__\\1[^>]*>([\\s\\S]*?)<\\/script>/i;\nconst SKIP_HEADERS = new Set(['cache-control', 'x-isr-cache', 'x-void-page-data', 'set-cookie']);\n\n/** Map of literal path pattern to the query names retained in an ISR cache variant. */\nexport type QueryAllowlist = Record<string, ReadonlyArray<string>>;\n\n/**\n * Normalize a request URL for cache-key use by retaining only query parameters\n * explicitly allowlisted for its user-facing pathname.\n */\nexport function buildVariantOriginalUrl(\n requestUrl: string,\n pathname: string,\n queryAllowlist: QueryAllowlist | undefined,\n): string {\n const url = new URL(requestUrl);\n if (!url.search) {\n return url.toString();\n }\n const allowed = resolveQueryAllowlist(queryAllowlist, pathname);\n if (allowed.size === 0) {\n url.search = '';\n return url.toString();\n }\n const keys = [...new Set(url.searchParams.keys())].filter((key) => allowed.has(key)).sort();\n const filtered = new URLSearchParams();\n for (const key of keys) {\n for (const value of url.searchParams.getAll(key)) {\n filtered.append(key, value);\n }\n }\n const filteredString = filtered.toString();\n url.search = filteredString ? `?${filteredString}` : '';\n return url.toString();\n}\n\n/** Keep only exact allowlist patterns for uncapped static-cache consumers. */\nexport function exactQueryAllowlist(\n allowlist: QueryAllowlist | undefined,\n): QueryAllowlist | undefined {\n if (!allowlist) {\n return undefined;\n }\n const exact = Object.fromEntries(\n Object.entries(allowlist).filter(([pattern]) => !pattern.includes('*')),\n );\n return Object.keys(exact).length > 0 ? exact : undefined;\n}\n\nfunction resolveQueryAllowlist(\n allowlist: QueryAllowlist | undefined,\n pathname: string,\n): Set<string> {\n if (!allowlist) {\n return new Set();\n }\n for (const [pattern, params] of Object.entries(allowlist)) {\n if (matchLiteralPattern(pattern, pathname)) {\n return new Set(params);\n }\n }\n return new Set();\n}\n\n/** Pack response headers and body into the canonical ISR binary value. */\nexport function packIsrValue(headers: Record<string, string>, body: ArrayBuffer): ArrayBuffer {\n const headerJson = new TextEncoder().encode(JSON.stringify(headers));\n const buffer = new ArrayBuffer(4 + headerJson.byteLength + body.byteLength);\n const view = new DataView(buffer);\n view.setUint32(0, headerJson.byteLength, true);\n new Uint8Array(buffer, 4, headerJson.byteLength).set(headerJson);\n new Uint8Array(buffer, 4 + headerJson.byteLength).set(new Uint8Array(body));\n return buffer;\n}\n\n/** Unpack a canonical ISR binary value, returning null for malformed bytes. */\nexport function unpackIsrValue(\n buffer: ArrayBuffer,\n): { headers: Record<string, string>; body: ArrayBuffer } | null {\n if (buffer.byteLength < 4) {\n return null;\n }\n const view = new DataView(buffer);\n const headerLength = view.getUint32(0, true);\n if (buffer.byteLength < 4 + headerLength) {\n return null;\n }\n try {\n const headerBytes = new Uint8Array(buffer, 4, headerLength);\n const parsed = JSON.parse(new TextDecoder().decode(headerBytes)) as unknown;\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return null;\n }\n const headers: Record<string, string> = {};\n for (const [name, value] of Object.entries(parsed)) {\n if (typeof value !== 'string') {\n return null;\n }\n headers[name] = value;\n }\n return { headers, body: buffer.slice(4 + headerLength) };\n } catch {\n return null;\n }\n}\n\n/** Decode and validate a KV value plus metadata into a safe cache entry. */\nexport function decodeIsrCacheEntry(\n value: ArrayBuffer | null,\n metadata: IsrCacheMetadata | null,\n): IsrCacheEntry | null {\n if (!value || !metadata) {\n return null;\n }\n const unpacked = unpackIsrValue(value);\n if (!unpacked) {\n return null;\n }\n if (!Number.isInteger(metadata.s) || metadata.s < 200 || metadata.s > 599) {\n return null;\n }\n if (\n !Number.isFinite(metadata.c) ||\n metadata.c <= 0 ||\n !Number.isFinite(metadata.t) ||\n metadata.t <= 0 ||\n metadata.p !== SHARED_CACHE_POLICY_VERSION\n ) {\n return null;\n }\n try {\n new Headers(unpacked.headers);\n } catch {\n return null;\n }\n return {\n body: new ReadableStream({\n start(controller): void {\n controller.enqueue(new Uint8Array(unpacked.body));\n controller.close();\n },\n }),\n status: metadata.s,\n headers: unpacked.headers,\n createdAt: metadata.c,\n ttl: metadata.t,\n };\n}\n\n/** Check whether an ISR cache entry has passed its freshness lifetime. */\nexport function isStale(entry: IsrCacheEntry, now: number = Date.now()): boolean {\n return now - entry.createdAt > entry.ttl * 1000;\n}\n\n/** Build an edge-cacheable response from a validated ISR cache entry. */\nexport function isrCacheResponse(\n entry: IsrCacheEntry,\n stale: boolean,\n now: number = Date.now(),\n): Response {\n const headers = new Headers(entry.headers);\n headers.set('x-isr-cache', stale ? 'STALE' : 'HIT');\n if (stale) {\n headers.set(\n 'Cache-Control',\n `public, s-maxage=${Math.min(10, entry.ttl)}, max-age=0, must-revalidate`,\n );\n } else {\n const remainingSeconds = Math.max(\n 0,\n Math.floor((entry.createdAt + entry.ttl * 1000 - now) / 1000),\n );\n headers.set(\n 'Cache-Control',\n `public, s-maxage=${remainingSeconds}, max-age=0, must-revalidate`,\n );\n }\n markSharedCachePolicy(headers);\n return new Response(entry.body, { status: entry.status, headers });\n}\n\n/** Resolve an x-revalidate override, falling back for absent or invalid values. */\nexport function resolveRevalidateTtl(response: Response, defaultTtl: number): number {\n const header = response.headers.get('x-revalidate');\n if (header === null) {\n return defaultTtl;\n }\n const value = Number.parseInt(header, 10);\n return Number.isNaN(value) || value < 0 ? defaultTtl : value;\n}\n\nfunction acceptsEventStream(request: Request): boolean {\n return (\n request.headers\n .get('Accept')\n ?.toLowerCase()\n .split(',')\n .some((part) => part.split(';', 1)[0]?.trim() === 'text/event-stream') ?? false\n );\n}\n\n/** Return whether credentials or EventSource semantics require an ISR bypass. */\nexport function shouldBypassIsr(request: Request): boolean {\n return (\n request.headers.has('Cookie') ||\n request.headers.has('Authorization') ||\n acceptsEventStream(request)\n );\n}\n\n/** Return whether a response explicitly forbids storage in a shared cache. */\nexport function hasSharedCacheOptOut(response: Response): boolean {\n if (response.headers.has('Set-Cookie')) {\n return true;\n }\n const cacheControl = response.headers.get('Cache-Control');\n if (!cacheControl) {\n return false;\n }\n return cacheControl.split(',').some((part) => {\n const directive = part.split('=', 1)[0]?.trim().toLowerCase();\n return directive === 'private' || directive === 'no-store' || directive === 'no-cache';\n });\n}\n\n/** Return whether a complete render may be persisted in the shared ISR cache. */\nexport function isSharedCacheableResponse(response: Response): boolean {\n return response.status === 200 && !hasSharedCacheOptOut(response);\n}\n\n/** Resolve the first matching path TTL using Void route-pattern semantics. */\nexport function resolvePathTtl(\n revalidate: number | Record<string, number> | undefined,\n pathname: string,\n): number {\n if (revalidate == null) {\n return 0;\n }\n if (typeof revalidate === 'number') {\n return revalidate;\n }\n for (const [pattern, ttl] of Object.entries(revalidate)) {\n if (matchSegmentPattern(pattern, pathname)) {\n return ttl;\n }\n }\n return 0;\n}\n\n/** One ordered page-route entry in the shared ISR TTL policy. */\nexport type IsrPageTtl = Readonly<{ pattern: string; revalidate?: number }>;\n\n/**\n * Resolve ISR TTL from the framework's ordered page table.\n *\n * The first matching page is authoritative. A baked positive TTL enables ISR,\n * a baked `0` opts out, and an absent TTL inherits from the raw per-path config.\n * Only requests that match no page fall back to the flattened revalidate config.\n */\nexport function resolvePageTtl(\n pages: ReadonlyArray<IsrPageTtl> | undefined,\n revalidate: number | Record<string, number> | undefined,\n pathRevalidate: Record<string, number> | undefined,\n pathname: string,\n): number {\n if (pages) {\n for (const page of pages) {\n if (!matchSegmentPattern(page.pattern, pathname)) {\n continue;\n }\n return page.revalidate === undefined\n ? resolvePathTtl(pathRevalidate, pathname)\n : page.revalidate > 0\n ? page.revalidate\n : 0;\n }\n }\n return resolvePathTtl(revalidate, pathname);\n}\n\n/** Extract response headers while removing ISR-managed and private headers. */\nexport function serializeHeaders(response: Response): Record<string, string> {\n const result: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n if (!SKIP_HEADERS.has(key.toLowerCase())) {\n result[key] = value;\n }\n });\n return result;\n}\n\n/** Validate page data before storing it as the JSON ISR variant. */\nexport function normalizePageDataForJsonCache(raw: string): string | null {\n try {\n const parsed = JSON.parse(raw) as { deferred?: unknown; deferredKeys?: unknown };\n return parsed.deferred === undefined && parsed.deferredKeys === undefined ? raw : null;\n } catch {\n return null;\n }\n}\n\n/** Extract validated Void Pages data embedded in an HTML response. */\nexport function extractPageDataFromHtml(html: string): string | null {\n const match = html.match(PAGE_DATA_SCRIPT_RE);\n return match ? normalizePageDataForJsonCache(match[2]!) : null;\n}\n", "import { isrCacheKey, isrCacheVariantPrefix, isrEdgeCacheUrl } from '@void/isr';\nimport {\n decodeIsrCacheEntry,\n extractPageDataFromHtml,\n isrCacheResponse,\n isStale,\n normalizePageDataForJsonCache,\n packIsrValue,\n resolvePathTtl,\n resolveRevalidateTtl,\n SHARED_CACHE_POLICY_VERSION,\n serializeHeaders,\n shouldBypassIsr,\n type IsrCacheEntry,\n type IsrCacheMetadata,\n} from '@void/isr/core';\nimport type { Env } from './env.ts';\nimport { matchSegmentPattern } from './pattern.ts';\n\n// Re-export so callers that import from `./isr` (tests, index.ts) still work.\nexport {\n extractPageDataFromHtml,\n hasCurrentSharedCachePolicy,\n hasSharedCacheOptOut,\n isrCacheResponse,\n isStale,\n normalizePageDataForJsonCache,\n packIsrValue,\n resolvePageTtl,\n resolvePathTtl,\n resolveRevalidateTtl,\n serializeHeaders,\n shouldBypassIsr,\n SHARED_CACHE_POLICY_HEADER,\n SHARED_CACHE_POLICY_VERSION,\n markSharedCachePolicy,\n unpackIsrValue,\n} from '@void/isr/core';\nexport { isrCacheKey } from '@void/isr';\nexport type { IsrCacheEntry, IsrCacheMetadata } from '@void/isr/core';\n\n/**\n * Hard cap on rewrite-variant ISR entries per (project, deployment, pathname).\n * The default `revalidateQueryAllowlist = {}` already drops every query param,\n * so most fanout vectors are closed at the variant-key level \u2014 but a path\n * with an allowlisted param (e.g. `/search` with `q`) can still be probed\n * with random `q` values. The cap is the second line of defense: once the\n * KV slot for a pathname holds this many variants, new variants stop being\n * written. The worker still renders fresh content; we simply refuse to\n * persist it, so KV growth and revalidation cost stay bounded.\n *\n * Existing variants continue to update so legitimate ISR refresh keeps\n * working; only NEW variants are rejected past the cap.\n */\nexport const MAX_ISR_VARIANTS_PER_PATH = 200;\n\n/**\n * Read an ISR cache entry from KV.\n * Returns null on cache miss or if metadata is malformed.\n */\nexport async function readIsrCache(\n env: Env,\n projectId: string,\n deploymentId: string,\n host: string,\n pathname: string,\n originalUrl?: string | null,\n): Promise<IsrCacheEntry | null> {\n const key = isrCacheKey(projectId, deploymentId, host, pathname, originalUrl);\n const { value, metadata } = await env.ISR_CACHE.getWithMetadata<IsrCacheMetadata>(\n key,\n 'arrayBuffer',\n );\n return decodeIsrCacheEntry(value, metadata);\n}\n\n/**\n * Delete an ISR cache entry from KV.\n * Used when a worker permanently opts out via x-revalidate: 0.\n */\nexport async function deleteIsrCache(\n env: Env,\n projectId: string,\n deploymentId: string,\n host: string,\n pathname: string,\n originalUrl?: string | null,\n): Promise<void> {\n const key = isrCacheKey(projectId, deploymentId, host, pathname, originalUrl);\n await env.ISR_CACHE.delete(key);\n}\n\n/**\n * Write an ISR cache entry to KV. Variant writes are gated by\n * `MAX_ISR_VARIANTS_PER_PATH` \u2014 past the cap, only updates to existing\n * variant slots go through. Direct-hit entries (no `originalUrl`) are\n * never gated.\n */\nexport async function writeIsrCache(\n env: Env,\n projectId: string,\n deploymentId: string,\n host: string,\n pathname: string,\n response: Response,\n ttl: number,\n originalUrl?: string | null,\n): Promise<void> {\n const key = isrCacheKey(projectId, deploymentId, host, pathname, originalUrl);\n // Clone synchronously so the cap-check `await` below cannot race with\n // callers (in `index.ts`) that consume `response.body` for the client\n // response after kicking us off via `ctx.waitUntil`. The clone has its\n // own independent body; the original is free to be consumed elsewhere.\n const responseClone = response.clone();\n const headers = serializeHeaders(responseClone);\n const status = responseClone.status;\n\n if (\n originalUrl &&\n !(await isVariantWriteAllowed(env, projectId, deploymentId, host, pathname, key))\n ) {\n return;\n }\n\n const body = await responseClone.arrayBuffer();\n const packed = packIsrValue(headers, body);\n\n await env.ISR_CACHE.put(key, packed, {\n metadata: {\n s: status,\n c: Date.now(),\n t: ttl,\n p: SHARED_CACHE_POLICY_VERSION,\n } satisfies IsrCacheMetadata,\n });\n}\n\n/**\n * Returns true if writing the given variant key is allowed under the\n * per-pathname cap. Always allows updates to existing variants (so ISR\n * revalidation keeps working after a path saturates).\n *\n * The KV list call is alphabetically ordered; we list up to `1000` entries\n * (the KV per-call max) which comfortably covers any realistic cap. If a\n * pathname has more variants than the listing returns, we conservatively\n * refuse new writes \u2014 that case shouldn't occur with the cap enforced.\n */\nasync function isVariantWriteAllowed(\n env: Env,\n projectId: string,\n deploymentId: string,\n host: string,\n pathname: string,\n key: string,\n): Promise<boolean> {\n const prefix = isrCacheVariantPrefix(projectId, deploymentId, host, pathname);\n const listed = await env.ISR_CACHE.list({ prefix, limit: 1000 });\n if (listed.keys.length < MAX_ISR_VARIANTS_PER_PATH) {\n return true;\n }\n // At or over cap: only allow updates to existing keys.\n return listed.keys.some((cacheKey) => cacheKey.name === key);\n}\n\n/**\n * Effective ISR TTL for a `pages` entry that ALREADY matched `pathname`,\n * decoding the 3-STATE table the framework's `collectPages` emits:\n * - a baked number is authoritative \u2014 `> 0` = ISR on, `0` = an EXPLICIT\n * opt-out (a per-page `export const revalidate = 0`, or a global-0 config);\n * - an ABSENT `revalidate` is INHERIT-eligible \u2014 resolve the RAW per-path\n * `pathRevalidate` OBJECT config against the ACTUAL path, so a per-path `0`\n * opt-out (or a wildcard / exact rule) that a dynamic page pattern straddles\n * is honored at the edge (build-time baking cannot \u2014 hence the split).\n * Keep in sync with `collectPages` (`packages/void/src/isr-config.ts`) and the api\n * prewarm mirror (`packages/api/src/routes/deploy.ts`).\n */\nfunction matchedPageTtl(\n page: { pattern: string; revalidate?: number },\n pathRevalidate: Record<string, number> | undefined,\n pathname: string,\n): number {\n if (page.revalidate === undefined) {\n return resolvePathTtl(pathRevalidate, pathname);\n }\n return page.revalidate > 0 ? page.revalidate : 0;\n}\n\n/**\n * A pattern is LITERAL when it has no param (`:name`), regex (`{...}`), or\n * wildcard (`*`) marker \u2014 so `matchSegmentPattern` matches ONLY the exact path,\n * never an arbitrary one. Used by `matchesLiteralPage` (applied to the whole\n * pattern).\n */\nexport function isLiteralPattern(pattern: string): boolean {\n return !/[:{*]/.test(pattern);\n}\n\n/**\n * True iff `target` EXACTLY matches a declared LITERAL ISR page (positive TTL).\n * A literal page pattern matches exactly one path, so a match POSITIVELY\n * identifies the fallback target as that specific author-declared ISR page.\n * A catch-all (`/:path{.+}`) or param page (`/:slug`) is NOT literal and never\n * vouches \u2014 it matches arbitrary paths, so it cannot certify an arbitrary\n * fallback target as public page content.\n */\nexport function matchesLiteralPage(\n pages: ReadonlyArray<{ pattern: string; revalidate?: number }> | undefined,\n target: string,\n pathRevalidate: Record<string, number> | undefined,\n): boolean {\n if (!pages) {\n return false;\n }\n for (const page of pages) {\n if (matchSegmentPattern(page.pattern, target)) {\n // First matching route WINS \u2014 mirror resolvePageTtl / the framework's\n // matchRoute order (0077's invariant: never re-order, never skip a matching\n // route). Authorize shared-caching of a fallback render only when that WINNING\n // route is an exact literal page with a positive effective TTL; a catch-all/param\n // winner means the framework renders this path dynamically, so it must NOT be\n // cached. `matchedPageTtl` resolves an inherit-eligible literal page against the\n // per-path config (a literal page maps to exactly one path \u2014 no straddle).\n return isLiteralPattern(page.pattern) && matchedPageTtl(page, pathRevalidate, target) > 0;\n }\n }\n return false;\n}\n\n/**\n * A pattern is a BROAD catch-all when it crosses segment boundaries \u2014 a named\n * catch-all `:name{.+}` (compiles to `.+`) or a `*` wildcard (compiles to `.*`).\n * Such a pattern matches ANY path, including genuine static assets, so it cannot\n * certify a dotted path as page ISR content. A single-segment param (`/blog/:slug`\n * \u2192 `[^/]+`) or a literal (`/feed.xml`) is NOT broad. See `pattern.ts`'s\n * catch-all syntax (`:[^/{}]+\\{\\.\\+\\}` and `*`).\n */\nexport function isBroadCatchAll(pattern: string): boolean {\n return pattern.includes('*') || pattern.includes('{.+}');\n}\n\n/**\n * A dotted request path is ISR page content (not a static asset) when it matches a\n * declared page route that is NOT a broad catch-all: a literal (`/feed.xml`) or a\n * single-segment param (`/blog/:slug`) that matches means the framework serves it\n * as that page, so `/blog/release.v2` gets ISR even though it has a dot. A broad\n * catch-all (`/:path{.+}`, `*`) matches everything including genuine static assets\n * (`/robots.txt`), so it does NOT make a dotted path ISR content. Mirrors\n * `resolvePageTtl`'s match order: pages first-match, then the flat map. A bare\n * global-NUMBER `revalidate` declares no pattern, so dotted paths under it are NOT\n * treated as ISR-eligible page content (documented narrow residual).\n */\nexport function isDottedPathIsrEligible(\n pages: ReadonlyArray<{ pattern: string; revalidate?: number }> | undefined,\n revalidate: number | Record<string, number> | undefined,\n pathRevalidate: Record<string, number> | undefined,\n pathname: string,\n): boolean {\n if (pages && pages.length > 0) {\n for (const page of pages) {\n if (matchSegmentPattern(page.pattern, pathname)) {\n // `matchedPageTtl` resolves an inherit-eligible page against the per-path\n // config; a broad catch-all winner never certifies a dotted path as page\n // content (it also matches genuine static assets like `/robots.txt`).\n return matchedPageTtl(page, pathRevalidate, pathname) > 0 && !isBroadCatchAll(page.pattern);\n }\n }\n // no page matched \u2192 fall through to the flat map (mirror resolvePageTtl)\n }\n if (revalidate && typeof revalidate === 'object') {\n for (const [pattern, ttl] of Object.entries(revalidate)) {\n if (matchSegmentPattern(pattern, pathname)) {\n return ttl > 0 && !isBroadCatchAll(pattern);\n }\n }\n }\n return false;\n}\n\n/**\n * Build a normalized cache key Request for the edge cache (caches.default).\n * The public URL stays clean; the internal cache key carries the deployment\n * id so a new deploy never reads HTML produced by an older deploy.\n *\n * When `originalUrl` is provided (the request was dispatch-rewritten), it is\n * mixed into the key so direct and rewritten requests to the same rewritten\n * pathname do not share a cache slot. See `isrCacheKey` for rationale.\n */\nexport function isrEdgeCacheKey(\n request: Request,\n pathname: string,\n deploymentId: string,\n originalUrl?: string | null,\n): Request {\n return new Request(\n isrEdgeCacheUrl(new URL(request.url).hostname, pathname, deploymentId, 'html', originalUrl),\n { method: 'GET' },\n );\n}\n\n/**\n * Build an edge cache key for the JSON variant (pages protocol navigation).\n * Uses `?__void=json` plus the deployment id to separate it from both HTML\n * and JSON generated by other deployments. `originalUrl` is mixed in under\n * the same rules as `isrEdgeCacheKey`.\n */\nexport function isrEdgeCacheKeyJson(\n request: Request,\n pathname: string,\n deploymentId: string,\n originalUrl?: string | null,\n): Request {\n return new Request(\n isrEdgeCacheUrl(new URL(request.url).hostname, pathname, deploymentId, 'json', originalUrl),\n { method: 'GET' },\n );\n}\n", "import { PLATFORM_USAGE_PROTOCOL_VERSION } from '@void/platform';\n\nexport const USAGE_PROTOCOL_VERSION = PLATFORM_USAGE_PROTOCOL_VERSION;\n\nexport const USAGE_SIGNING_KEY_KV_KEY = '__void:usage-signing-key:v1';\n/** Operational usage intervals and their replay receipts share one validity window. */\nexport const SANDBOX_USAGE_RETENTION_MS = 8 * 24 * 60 * 60_000;\n\nexport type UsageEventSource = 'dispatch' | 'sandbox-counter';\n\nexport type SignedUsageEnvelope<T = unknown> = Readonly<{\n version: 1 | typeof USAGE_PROTOCOL_VERSION;\n source: UsageEventSource;\n eventId: string;\n event: T;\n signature: string;\n}>;\n\nconst encoder = new TextEncoder();\nconst DERIVATION_CONTEXT = 'void-platform:usage-events:v1';\n\nfunction base64url(bytes: ArrayBuffer): string {\n let binary = '';\n for (const byte of new Uint8Array(bytes)) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nfunction decodeBase64url(value: string): Uint8Array {\n const normalized = value.replace(/-/g, '+').replace(/_/g, '/');\n const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, '=');\n const binary = atob(padded);\n return Uint8Array.from(binary, (character) => character.charCodeAt(0));\n}\n\nasync function hmac(data: string, secret: string): Promise<ArrayBuffer> {\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n return crypto.subtle.sign('HMAC', key, encoder.encode(data));\n}\n\n/**\n * Return the platform-only queue signing key, creating it on first use.\n *\n * Only the purpose-separated derivative is stored in ROUTING. Dispatch can\n * therefore sign request metering without receiving the API's JWT_SECRET.\n * Tenant Workers have neither ROUTING nor this derived value.\n */\nexport async function ensureUsageSigningKey(\n routing: KVNamespace,\n jwtSecret: string,\n): Promise<string> {\n const existing = await routing.get(USAGE_SIGNING_KEY_KV_KEY);\n if (existing) {\n return existing;\n }\n const derived = base64url(await hmac(DERIVATION_CONTEXT, jwtSecret));\n await routing.put(USAGE_SIGNING_KEY_KV_KEY, derived);\n return derived;\n}\n\nexport async function readUsageSigningKey(routing: KVNamespace): Promise<string | null> {\n return routing.get(USAGE_SIGNING_KEY_KV_KEY, { cacheTtl: 60 });\n}\n\nfunction signedPayload<T>(\n version: SignedUsageEnvelope['version'],\n source: UsageEventSource,\n eventId: string,\n event: T,\n): string {\n return JSON.stringify([version, source, eventId, event]);\n}\n\nexport async function signUsageEvent<T>(\n key: string,\n source: UsageEventSource,\n eventId: string,\n event: T,\n): Promise<SignedUsageEnvelope<T>> {\n return {\n version: USAGE_PROTOCOL_VERSION,\n source,\n eventId,\n event,\n signature: base64url(\n await hmac(signedPayload(USAGE_PROTOCOL_VERSION, source, eventId, event), key),\n ),\n };\n}\n\nexport async function verifyUsageEnvelope<T>(\n value: unknown,\n key: string,\n): Promise<SignedUsageEnvelope<T> | null> {\n if (typeof value !== 'object' || value === null) {\n return null;\n }\n const envelope = value as Record<string, unknown>;\n if (\n (envelope.version !== 1 && envelope.version !== USAGE_PROTOCOL_VERSION) ||\n (envelope.source !== 'dispatch' && envelope.source !== 'sandbox-counter') ||\n typeof envelope.eventId !== 'string' ||\n envelope.eventId.length === 0 ||\n envelope.eventId.length > 256 ||\n typeof envelope.signature !== 'string' ||\n !/^[A-Za-z0-9_-]{43}$/.test(envelope.signature) ||\n typeof envelope.event !== 'object' ||\n envelope.event === null ||\n Array.isArray(envelope.event)\n ) {\n return null;\n }\n try {\n const signingKey = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(key),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['verify'],\n );\n const signature = decodeBase64url(envelope.signature);\n const valid = await crypto.subtle.verify(\n 'HMAC',\n signingKey,\n signature.buffer as ArrayBuffer,\n encoder.encode(\n signedPayload(envelope.version, envelope.source, envelope.eventId, envelope.event),\n ),\n );\n return valid ? (envelope as SignedUsageEnvelope<T>) : null;\n } catch {\n return null;\n }\n}\n", "import { readUsageSigningKey, signUsageEvent } from '@voidcloud/api/usage-auth';\nimport type { Env } from './env.ts';\n\nexport type RequestType = 'api' | 'static' | 'ssr' | 'isr' | 'websocket';\nexport type FailureKind =\n | 'platform-static-asset-timeout'\n | 'platform-static-asset-error'\n | 'platform-static-asset-missing';\n\nexport function recordRequest(\n env: Env,\n data: {\n projectId: string;\n type: RequestType;\n method: string;\n status: number;\n responseBytes: number;\n durationMs: number;\n slug: string;\n failureKind?: FailureKind;\n },\n): void {\n env.ANALYTICS.writeDataPoint({\n indexes: [data.projectId],\n blobs: [\n data.projectId,\n data.type,\n data.method,\n String(data.status),\n data.slug,\n data.failureKind ?? '',\n ],\n doubles: [1, data.responseBytes, data.durationMs],\n });\n}\n\n/**\n * Split a WfP script name into the pieces the `void_logs` dataset is keyed on.\n *\n * Mirrors `parseScriptName` in `packages/tail/src/index.ts`, restricted to the\n * `user-*` names dispatch can attribute. This MUST agree with the tail worker:\n * `GET /projects/:id/logs` selects on `index1 = 'user-<slug>'`, so a key the\n * tail worker would not have produced is a row the user can never read.\n * `packages/dispatch/test/unit/platform-log.test.ts` asserts the agreement\n * against the tail implementation itself.\n *\n * Returns `null` for anything that is not a user worker, so a platform script\n * name can never be written under a project's key.\n */\nexport function splitWorkerName(\n workerName: string,\n): { projectKey: string; deployId: string } | null {\n if (!workerName.startsWith('user-')) {\n return null;\n }\n const dplIndex = workerName.lastIndexOf('-dpl_');\n if (dplIndex > 4) {\n return {\n projectKey: workerName.slice(0, dplIndex),\n deployId: workerName.slice(dplIndex + 1),\n };\n }\n return { projectKey: workerName, deployId: '' };\n}\n\n// Analytics Engine caps the SUM of a data point's blobs at 16 KB. There is no\n// per-blob limit, and a data point over the cap is DROPPED \u2014 which\n// `recordPlatformLog` would then swallow, silently losing the row it exists to\n// write. Neither budget is a guess: the longest URL already in `void_logs` is\n// 6,703 bytes against a p99 of 195, and this row would otherwise carry the URL\n// TWICE (raw in blob4, and as the pathname inside the blob2 message). Together\n// these two caps hold every blob set under ~3.5 KB no matter the input, which\n// is a deterministic bound rather than an average-case one.\nconst MAX_LOG_URL_BYTES = 2048;\nconst MAX_LOG_PATH_BYTES = 1024;\n\n/**\n * Cut `value` to at most `maxBytes` of UTF-8, on a character boundary.\n *\n * The budget must be measured in the bytes that actually go on the wire, not in\n * UTF-16 code units \u2014 one CJK character is 1 unit and 3 bytes. Cutting mid\n * sequence is worse than useless: the split tail decodes to U+FFFD, which is\n * itself 3 bytes and pushes the field back over its budget. So the slice walks\n * back over continuation bytes and drops an incomplete lead byte before\n * decoding. A truncated value ends in an ellipsis so the reader can tell.\n */\nexport function truncateUtf8(value: string, maxBytes: number): string {\n const encoded = new TextEncoder().encode(value);\n if (encoded.length <= maxBytes) {\n return value;\n }\n\n const ellipsis = '\u2026'; // 3 bytes in UTF-8\n if (maxBytes < 3) {\n return '';\n }\n\n // Provisional cut, leaving room for the ellipsis. `encoded.length > maxBytes`\n // here, so this index is always in range.\n let end = maxBytes - 3;\n\n // If the byte AT the cut is a continuation byte (0b10xxxxxx) then the cut\n // falls inside a character \u2014 walk back to that character's lead byte, which\n // `slice(0, end)` then excludes. A cut already on a boundary stops at once,\n // so a whole character is never dropped needlessly.\n while (end > 0 && (encoded[end]! & 0xc0) === 0x80) {\n end--;\n }\n\n return new TextDecoder().decode(encoded.slice(0, end)) + ellipsis;\n}\n\n/**\n * Write one row into `void_logs` explaining a 503 that dispatch generated.\n *\n * A worker cut at the dispatch budget never returns, so it emits no tail event\n * of its own worth reading: the runtime records the invocation as `canceled`,\n * which is indistinguishable from a real client hang-up. Only dispatch knows it\n * was the one that hung up, so only dispatch can say so. Without this row\n * `void project logs` is empty for exactly the failure the user most needs\n * explained.\n *\n * The row is the same seven-blob/two-double shape `packages/tail/src/index.ts`\n * writes, so the existing read path needs no change. `outcome` is `canceled` to\n * match the tail row for the same invocation rather than invent a status.\n *\n * Best effort by construction: every call site is already returning a 503, and\n * an uncaught throw there would surface to the client as a 500. A dropped log\n * line is strictly better than that, so all failures are swallowed.\n */\nexport function recordPlatformLog(\n env: Env,\n data: {\n workerName: string | undefined;\n method: string;\n url: string;\n status: number;\n timeoutMs: number;\n },\n): void {\n if (!data.workerName) {\n return;\n }\n const parsed = splitWorkerName(data.workerName);\n if (!parsed) {\n return;\n }\n\n let pathname = data.url;\n try {\n pathname = new URL(data.url).pathname;\n } catch {\n // Keep the raw string \u2014 a message is worth more than a thrown URL parse.\n }\n\n const message =\n `Void platform: your worker did not respond within ${data.timeoutMs} ms. ` +\n `${data.method} ${truncateUtf8(pathname, MAX_LOG_PATH_BYTES)} was cut short and ` +\n `returned ${data.status}. The operation may still have side effects; ` +\n `check its outcome before retrying.`;\n\n try {\n env.LOGS.writeDataPoint({\n // `projectKey` is NOT truncated. It is the read key, so a shortened one\n // would produce a row `GET /projects/:id/logs` can never select \u2014 worse\n // than no row. It is bounded upstream by the project slug, and the tail\n // worker writes the same value whole.\n indexes: [parsed.projectKey],\n blobs: [\n 'canceled',\n JSON.stringify([{ level: 'error', message: [message], timestamp: Date.now() }]),\n '[]',\n truncateUtf8(data.url, MAX_LOG_URL_BYTES),\n data.method,\n String(data.status),\n parsed.deployId,\n ],\n doubles: [Date.now(), data.status],\n });\n } catch {\n // See the doc comment: never turn the 503 being explained into a 500.\n }\n}\n\nexport async function sendUsageEvent(\n env: Env,\n data: {\n projectId: string;\n userId: string;\n slug: string;\n requests: number;\n responseBytes: number;\n status?: number;\n failureKind?: FailureKind;\n },\n): Promise<void> {\n const key = await readUsageSigningKey(env.ROUTING);\n if (!key) {\n // The API health check creates the key before installation traffic is\n // enabled. During a staged upgrade, fail closed rather than emitting an\n // unsigned frame the hardened consumer would (correctly) reject.\n throw new Error('Usage metering is not initialized. Check the platform API /health endpoint.');\n }\n const eventId = crypto.randomUUID();\n await env.USAGE_QUEUE.send(await signUsageEvent(key, 'dispatch', eventId, data));\n}\n", "// Keep these wire values aligned with @void/platform. This private runtime is\n// bundled into that package, but must not import the package being built.\nexport const PLATFORM_DISABLED_KEY = '__void/platform/disabled/v1';\nexport const PLATFORM_DISABLED_VALUE = 'disabled';\n", "export const SITE_DOMAIN = 'void.app';\n", "import { SITE_DOMAIN } from './constants.ts';\n\n/**\n * Extract the project slug from a hostname.\n * Returns null if the hostname doesn't match the expected pattern.\n *\n * Examples:\n * \"my-app.void.app\" \u2192 \"my-app\"\n * \"void.app\" \u2192 null\n * \"foo.bar.void.app\" \u2192 null (no subdomains)\n * \"example.com\" \u2192 null\n */\nexport function extractSlug(hostname: string, baseHostname: string = SITE_DOMAIN): string | null {\n const suffix = `.${baseHostname}`;\n if (!hostname.endsWith(suffix)) {\n return null;\n }\n\n const slug = hostname.slice(0, -suffix.length);\n\n // Must be non-empty and contain no dots (no nested subdomains)\n if (!slug || slug.includes('.')) {\n return null;\n }\n\n // Validate slug format: lowercase alphanumeric + dashes, no leading/trailing dash\n if (!/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(slug)) {\n return null;\n }\n\n return slug;\n}\n", "import {\n platformProjectWorkersDevHostname,\n platformWorkersDevAliasKey,\n readPlatformApplication,\n type PlatformApplicationProject,\n} from '@void/platform';\nimport type { Env } from './env.ts';\nimport { extractSlug } from './hostname.ts';\n\nexport async function resolveProjectHostname(\n hostname: string,\n env: Env,\n): Promise<{ slug: string | null; projectId?: string; workersDev: boolean }> {\n const application = readPlatformApplication(env);\n const isWorkersDev =\n !!application.workersDev &&\n hostname.endsWith(`.${application.workersDev.subdomain}.workers.dev`);\n if (!isWorkersDev) {\n return { slug: extractSlug(hostname, env.BASE_HOSTNAME), workersDev: false };\n }\n const raw = await env.ROUTING.get(platformWorkersDevAliasKey(hostname));\n if (raw) {\n const project = JSON.parse(raw) as PlatformApplicationProject;\n if (platformProjectWorkersDevHostname(project, application.workersDev!) === hostname) {\n return { slug: project.slug, projectId: project.id, workersDev: true };\n }\n }\n return { slug: null, workersDev: true };\n}\n\n/** workers.dev has no operator-owned zone to purge. Retain shared ISR and omit this edge layer. */\nfunction isTestHostname(request: RequestInfo | URL): boolean {\n return new URL(\n typeof request === 'string' || request instanceof URL ? request : request.url,\n ).hostname.endsWith('.workers.dev');\n}\n\nexport const applicationEdgeCache: Cache = {\n async match(request, options) {\n return isTestHostname(request) ? undefined : caches.default.match(request, options);\n },\n async put(request, response) {\n if (!isTestHostname(request)) {\n await caches.default.put(request, response);\n }\n },\n async delete(request, options) {\n return isTestHostname(request) ? false : caches.default.delete(request, options);\n },\n};\n", "import type { RequestType } from './metering.ts';\n\n/** True if the last path segment contains a `.` (has a file extension). */\nexport function hasExtension(pathname: string): boolean {\n return pathname.slice(pathname.lastIndexOf('/') + 1).includes('.');\n}\n\n/**\n * Classify a user-worker (dynamic) request for metering from its path and whether\n * the project is SSR. Returns 'api'/'ssr', or null to keep the caller's existing\n * default ('static'/'websocket'). Used on BOTH the success path and the dispatch\n * TIMEOUT path so timed-out /api and SSR requests are metered with the right type\n * instead of collapsing into the 'static' bucket.\n */\nexport function classifyDynamicRequestType(\n pathname: string,\n ssr: boolean | undefined,\n): RequestType | null {\n if (pathname.startsWith('/api/') || pathname === '/api') {\n return 'api';\n }\n if (ssr && !hasExtension(pathname)) {\n return 'ssr';\n }\n return null;\n}\n", "/**\n * Error thrown when a promise wrapped by {@link withTimeout} does not settle\n * within its allotted time. The `label` identifies which awaited operation\n * timed out (e.g. `'kv:get'`, `'r2:head'`) for logging/observability.\n */\nexport class DispatchTimeoutError extends Error {\n readonly label: string;\n\n constructor(label: string) {\n super(`Dispatch operation timed out: ${label}`);\n this.name = 'DispatchTimeoutError';\n this.label = label;\n }\n}\n\n/**\n * Bounds an awaited `promise` so the request path never blocks indefinitely.\n *\n * - When `ms` is not a positive finite number (`<= 0`, `NaN`, or `Infinity`),\n * the original `promise` is returned unchanged (escape hatch \u2014 no timer).\n * - Otherwise the `promise` races a timer that rejects with a\n * {@link DispatchTimeoutError} after `ms` milliseconds.\n * - The timer is cleared as soon as `promise` settles (resolve **or** reject),\n * so it never fires late and leaves no dangling handle. A fast rejection\n * propagates the ORIGINAL reason (not a timeout error).\n * - If the timer wins, the result rejects with a `DispatchTimeoutError`. The\n * underlying `promise` keeps running to completion in the background; we do\n * not attempt to cancel the in-flight KV/R2 work.\n */\nexport function withTimeout<T>(promise: Promise<T>, ms: number, label: string): Promise<T> {\n if (!(ms > 0) || !Number.isFinite(ms)) {\n return promise;\n }\n\n let timer: ReturnType<typeof setTimeout> | null = null;\n const timeout = new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => {\n reject(new DispatchTimeoutError(label));\n }, ms);\n });\n\n return Promise.race([promise, timeout]).finally(() => {\n clearTimeout(timer);\n });\n}\n\ntype HedgedOutcome<T> =\n | Readonly<{ ok: true; value: T | null }>\n | Readonly<{ ok: false; error: unknown }>;\n\ntype DelayedHedgeOptions<T> = Readonly<{\n delayMs: number;\n timeoutMs: number;\n label: string;\n discard?: (value: T) => void | Promise<void>;\n onHedge?: () => void;\n}>;\n\n/**\n * Run one operation and launch at most one fresh attempt if the first remains\n * pending after `delayMs`.\n *\n * - Both attempts share one absolute `timeoutMs` deadline.\n * - A fast success or miss (`null`) preserves the one-attempt fast path.\n * - A fast rejection retries immediately.\n * - Once hedged, the first non-null success wins. A miss/rejection from one\n * attempt waits for its peer instead of masking a usable result.\n * - `discard` cleans up every successful non-null loser, including results\n * which arrive after the absolute timeout (for R2-backed Responses this\n * cancels the unread body stream).\n * - Every attempt is internally settled, so late rejection cannot become\n * unhandled after the winner or timeout returns.\n * - A non-positive/non-finite delay disables hedging. A non-positive/non-\n * finite timeout disables the deadline.\n */\nexport async function withDelayedHedge<T>(\n operation: () => Promise<T | null>,\n options: DelayedHedgeOptions<T>,\n): Promise<T | null> {\n const hedgeEnabled = options.delayMs > 0 && Number.isFinite(options.delayMs);\n const timeoutEnabled = options.timeoutMs > 0 && Number.isFinite(options.timeoutMs);\n const run = async (): Promise<HedgedOutcome<T>> => {\n try {\n return { ok: true, value: await operation() };\n } catch (error) {\n return { ok: false, error };\n }\n };\n\n type Attempt = Readonly<{ id: number; promise: Promise<HedgedOutcome<T>> }>;\n const attempts: Array<Attempt> = [];\n const startAttempt = (): Attempt => {\n const attempt = { id: attempts.length + 1, promise: run() };\n attempts.push(attempt);\n return attempt;\n };\n\n let hedgeTimer: ReturnType<typeof setTimeout> | null = null;\n const hedgeSignal = hedgeEnabled\n ? new Promise<Readonly<{ kind: 'hedge' }>>((resolve) => {\n hedgeTimer = setTimeout(() => resolve({ kind: 'hedge' }), options.delayMs);\n })\n : null;\n\n let timeoutTimer: ReturnType<typeof setTimeout> | null = null;\n const timeoutSignal = timeoutEnabled\n ? new Promise<Readonly<{ kind: 'timeout' }>>((resolve) => {\n timeoutTimer = setTimeout(() => resolve({ kind: 'timeout' }), options.timeoutMs);\n })\n : null;\n\n const clearTimers = (): void => {\n clearTimeout(hedgeTimer);\n clearTimeout(timeoutTimer);\n };\n const discardAttempt = (attempt: Attempt): void => {\n // The storage binding itself is not abortable. Keep a handled continuation\n // so a late body is canceled and a late rejection is always observed.\n void attempt.promise\n .then(async (outcome) => {\n if (outcome.ok && outcome.value !== null) {\n await options.discard?.(outcome.value);\n }\n })\n .catch(() => {});\n };\n const finish = (winnerId?: number): void => {\n clearTimers();\n for (const attempt of attempts) {\n if (attempt.id !== winnerId) {\n discardAttempt(attempt);\n }\n }\n };\n const timeout = (): never => {\n finish();\n throw new DispatchTimeoutError(options.label);\n };\n const waitForAttempt = (attempt: Attempt) =>\n attempt.promise.then((outcome) => ({\n kind: 'attempt' as const,\n attempt,\n outcome,\n }));\n\n const first = startAttempt();\n const initial = await Promise.race([\n waitForAttempt(first),\n ...(hedgeSignal ? [hedgeSignal] : []),\n ...(timeoutSignal ? [timeoutSignal] : []),\n ]);\n\n if (initial.kind === 'timeout') {\n return timeout();\n }\n\n if (initial.kind === 'attempt') {\n clearTimeout(hedgeTimer);\n if (initial.outcome.ok) {\n finish(first.id);\n return initial.outcome.value;\n }\n if (!hedgeEnabled) {\n finish();\n throw initial.outcome.error;\n }\n\n // Binding errors are often transient. Retry one fast rejection without\n // waiting for the hedge delay; the same absolute deadline still applies.\n options.onHedge?.();\n const retry = startAttempt();\n const retried = await Promise.race([\n waitForAttempt(retry),\n ...(timeoutSignal ? [timeoutSignal] : []),\n ]);\n if (retried.kind === 'timeout') {\n return timeout();\n }\n finish(retry.id);\n if (retried.outcome.ok) {\n return retried.outcome.value;\n }\n throw retried.outcome.error;\n }\n\n // The timer fired, so attempt one is still pending. Launch exactly one\n // independent read and prefer the first usable (non-null) result.\n options.onHedge?.();\n const second = startAttempt();\n const winner = await Promise.race([\n waitForAttempt(first),\n waitForAttempt(second),\n ...(timeoutSignal ? [timeoutSignal] : []),\n ]);\n\n if (winner.kind === 'timeout') {\n return timeout();\n }\n if (winner.outcome.ok && winner.outcome.value !== null) {\n finish(winner.attempt.id);\n return winner.outcome.value;\n }\n\n const peer = winner.attempt.id === first.id ? second : first;\n const peerResult = await Promise.race([\n waitForAttempt(peer),\n ...(timeoutSignal ? [timeoutSignal] : []),\n ]);\n if (peerResult.kind === 'timeout') {\n return timeout();\n }\n\n if (peerResult.outcome.ok && peerResult.outcome.value !== null) {\n finish(peer.id);\n return peerResult.outcome.value;\n }\n finish();\n if (winner.outcome.ok || peerResult.outcome.ok) {\n return null;\n }\n throw winner.outcome.error;\n}\n\n/**\n * Resolve the timeout budget (ms) from the raw `DISPATCH_TIMEOUT_MS` env value.\n *\n * - Unset (`undefined`) \u2192 the `fallback` default (10s).\n * - Any explicitly-provided value is passed through via `Number(...)` UNCHANGED \u2014\n * including `'0'`, negatives, empty string, and non-numeric strings (`NaN`). This\n * preserves the escape hatch: {@link withTimeout} treats any non-positive/non-finite\n * budget as \"no timer\", so an operator can disable the bounded paths by setting\n * `DISPATCH_TIMEOUT_MS='0'` WITHOUT a redeploy. A blanket `|| fallback` would defeat\n * this by collapsing every disabling value back to the default.\n */\nexport function resolveTimeoutMs(raw: string | undefined, fallback = 10000): number {\n return raw === undefined ? fallback : Number(raw);\n}\n", "import { resolvePlatformApplicationEnvironment } from '@void/platform';\nimport type { Env } from './env.ts';\nimport { createErrorResponse } from './error-page.ts';\nimport { applyHeaderRules, type HeaderRule } from './headers.ts';\nimport {\n readIsrCache,\n writeIsrCache,\n deleteIsrCache,\n isStale,\n isrCacheResponse,\n isrEdgeCacheKey,\n isrEdgeCacheKeyJson,\n hasCurrentSharedCachePolicy,\n hasSharedCacheOptOut,\n SHARED_CACHE_POLICY_HEADER,\n markSharedCachePolicy,\n resolveRevalidateTtl,\n resolvePathTtl,\n resolvePageTtl,\n matchesLiteralPage,\n isDottedPathIsrEligible,\n shouldBypassIsr,\n extractPageDataFromHtml,\n normalizePageDataForJsonCache,\n} from './isr.ts';\nimport {\n recordPlatformLog,\n recordRequest,\n sendUsageEvent,\n type FailureKind,\n type RequestType,\n} from './metering.ts';\nimport { PLATFORM_DISABLED_KEY, PLATFORM_DISABLED_VALUE } from './platform-lifecycle.ts';\nimport { applicationEdgeCache, resolveProjectHostname } from './project-hostname.ts';\nimport { classifyDynamicRequestType, hasExtension } from './request-type.ts';\nimport { applyRoutingRules, mergeQueryIntoLocation, type RedirectRule } from './routing-rules.ts';\nimport { resolveStaticPath, resolveAssetContentType, safeDecodePathname } from './static.ts';\nimport type { AssetConfig } from './static.ts';\nimport {\n buildVariantOriginalUrl,\n exactQueryAllowlist,\n type QueryAllowlist,\n} from './variant-key.ts';\nimport {\n DispatchTimeoutError,\n resolveTimeoutMs,\n withDelayedHedge,\n withTimeout,\n} from './with-timeout.ts';\n\ntype RoutingEntry = Readonly<{\n workerName: string;\n projectId: string;\n userId?: string;\n type?: 'void' | 'spa' | 'static' | 'framework';\n ssr?: boolean;\n revalidate?: number | Record<string, number>;\n pages?: ReadonlyArray<{ pattern: string; revalidate?: number }>;\n // RAW per-path `routing.revalidate` OBJECT config (pages mode). Resolved at\n // the edge against the real request path for a matched inherit-eligible page\n // (a `pages` entry with no baked `revalidate`) \u2014 honors per-path `0` opt-outs\n // a dynamic pattern straddles. Distinct from the folded `revalidate` map.\n pathRevalidate?: Record<string, number>;\n version?: string;\n limits?: Record<string, number>;\n suspended?: string;\n hashedAssetsPrefix?: string;\n headerRules?: ReadonlyArray<HeaderRule>;\n // `redirectRules` fires pre-asset, `fallbackRules` fires post-asset.\n // List identity encodes the pre-vs-post-asset semantic.\n redirectRules?: ReadonlyArray<RedirectRule>;\n fallbackRules?: ReadonlyArray<RedirectRule>;\n // Per-pathname allowlist of query params that are part of the ISR variant\n // key on a rewrite. Default (no entry / no allowlist) drops every param,\n // so an attacker can't fan out the cache by varying `?utm`/`?cb`/etc.\n queryAllowlist?: QueryAllowlist;\n staticDeploymentId?: string;\n assetManifestId?: string;\n assetConfig?: AssetConfig;\n}>;\n\ntype QueueRoutingEntry = Readonly<{\n workerName: string;\n projectId: string;\n queueName: string;\n // HMAC-signed proxy token matching the user worker's __VOID_PROXY_TOKEN\n // binding. The framework-generated /__void/queue handler rejects relays\n // without a matching `x-void-internal` header with 401. Absent on entries\n // written by older API versions.\n proxyToken?: string;\n}>;\n\nconst CLIENT_REVALIDATE_CACHE_CONTROL = 'public, max-age=0, must-revalidate';\nconst STATIC_ASSET_HEDGE_DELAY_MS = 1000;\nconst PLATFORM_QUEUE_RETRY_DELAY_SECONDS = 300;\nconst PLATFORM_STATIC_ASSET_TIMEOUT: FailureKind = 'platform-static-asset-timeout';\nconst PLATFORM_STATIC_ASSET_ERROR: FailureKind = 'platform-static-asset-error';\nconst PLATFORM_STATIC_ASSET_MISSING: FailureKind = 'platform-static-asset-missing';\n\n// How long a STALE ISR entry may keep being served without a successful refresh\n// before a background revalidation evicts it. Measured from when the entry became\n// STALE (`createdAt + ttl`), NOT from creation \u2014 so an entry with a long TTL still\n// gets the full grace of STALE tolerance and a transient failure right after expiry\n// does not evict immediately. Bounds the \"serve stale forever\" window for a\n// permanently-removed page (origin now 404s and falls back to a non-cacheable shell,\n// so the entry can neither refresh nor authoritatively opt-out-evict) while staying\n// far above any transient deploy-race 404 so normal stale-while-revalidate is intact.\nconst ISR_STALE_EVICT_GRACE_SECONDS = 86_400; // 24h of STALE tolerance\n\nfunction clientRevalidateResponse(response: Response): Response {\n const res = new Response(response.body, response);\n res.headers.set('Cache-Control', CLIENT_REVALIDATE_CACHE_CONTROL);\n res.headers.delete(SHARED_CACHE_POLICY_HEADER);\n return res;\n}\n\n// Fast body-less response for an operation bounded by `withTimeout` that\n// stalled past the budget. `X-Void-Timeout` names the stalled operation for\n// observability; 503s advertise a short `Retry-After` so clients back off.\nfunction timeoutResponse(status: number, label: string): Response {\n return new Response(null, {\n status,\n headers: {\n 'X-Void-Timeout': label,\n ...(status === 503 ? { 'Retry-After': '5' } : {}),\n },\n });\n}\n\nfunction staticAssetFailureResponse(kind: FailureKind): Response {\n if (kind === PLATFORM_STATIC_ASSET_TIMEOUT) {\n return timeoutResponse(503, 'static-asset');\n }\n return new Response(null, {\n status: 503,\n headers: {\n 'X-Void-Storage-Error':\n kind === PLATFORM_STATIC_ASSET_MISSING ? 'static-asset-missing' : 'static-asset-read',\n 'Retry-After': '5',\n },\n });\n}\n\nexport function isEventStreamResponse(response: Response): boolean {\n return (\n response.headers.get('content-type')?.toLowerCase().split(';', 1)[0]?.trim() ===\n 'text/event-stream'\n );\n}\n\nexport function isHtmlResponse(response: Response): boolean {\n return (\n response.headers.get('content-type')?.toLowerCase().split(';', 1)[0]?.trim() === 'text/html'\n );\n}\n\nfunction jsonCacheResponse(pageData: string, ttl: number, state: 'HIT' | 'MISS'): Response {\n const response = new Response(pageData, {\n headers: {\n 'content-type': 'application/json',\n 'Cache-Control': `public, s-maxage=${ttl}, max-age=0, must-revalidate`,\n 'x-isr-cache': state,\n },\n });\n markSharedCachePolicy(response.headers);\n return response;\n}\n\nasync function populateJsonEdgeCache(\n cache: Cache,\n cacheKey: Request,\n response: Response,\n ttl: number,\n state: 'HIT' | 'MISS',\n): Promise<void> {\n const fromHeader = response.headers.get('x-void-page-data');\n const pageData = fromHeader\n ? normalizePageDataForJsonCache(fromHeader)\n : extractPageDataFromHtml(await response.clone().text());\n if (!pageData) {\n return;\n }\n await cache.put(cacheKey, jsonCacheResponse(pageData, ttl, state));\n}\n\ntype SharedIsrEntry = Readonly<{\n projectId: string;\n deploymentId: string;\n host: string;\n pathname: string;\n originalUrl?: string;\n htmlKey: Request;\n jsonKey: Request;\n}>;\n\nasync function deleteSharedIsrEntry(env: Env, entry: SharedIsrEntry): Promise<void> {\n await Promise.all([\n deleteIsrCache(\n env,\n entry.projectId,\n entry.deploymentId,\n entry.host,\n entry.pathname,\n entry.originalUrl,\n ),\n applicationEdgeCache.delete(entry.htmlKey),\n applicationEdgeCache.delete(entry.jsonKey),\n ]);\n}\n\nasync function applyWorkerFallbackRules(opts: {\n response: Response;\n worker: { fetch(request: Request): Promise<Response> };\n dispatchReq: Request;\n routing: RoutingEntry;\n pathname: string;\n url: URL;\n originalRequestUrl: string;\n originalUrlHeader?: string;\n originalUrlVariant?: string;\n deadline?: Readonly<{ startedAt: number; timeoutMs: number }>;\n}): Promise<{\n response: Response;\n pathname: string;\n originalUrlVariant?: string;\n applied: boolean;\n}> {\n if (opts.response.status !== 404 || !opts.routing.fallbackRules?.length) {\n return {\n response: opts.response,\n pathname: opts.pathname,\n originalUrlVariant: opts.originalUrlVariant,\n applied: false,\n };\n }\n if (opts.routing.type === 'void' && opts.response.headers.get('X-Void-No-Match') !== '1') {\n return {\n response: opts.response,\n pathname: opts.pathname,\n originalUrlVariant: opts.originalUrlVariant,\n applied: false,\n };\n }\n\n const fallback = applyRoutingRules(opts.pathname, opts.routing.fallbackRules, opts.url.hostname);\n if (fallback?.type !== 'rewrite') {\n return {\n response: opts.response,\n pathname: opts.pathname,\n originalUrlVariant: opts.originalUrlVariant,\n applied: false,\n };\n }\n\n const fallbackHeader = opts.originalUrlHeader ?? opts.originalRequestUrl;\n const originalUrlVariant =\n opts.originalUrlVariant ??\n buildVariantOriginalUrl(opts.originalRequestUrl, opts.pathname, opts.routing.queryAllowlist);\n const fallbackUrl = new URL(opts.url.toString());\n fallbackUrl.pathname = fallback.destination;\n const fallbackRequest = rebuildRequest(opts.dispatchReq, fallbackUrl.toString(), (headers) =>\n headers.set('X-Void-Original-URL', fallbackHeader),\n );\n\n return {\n response:\n opts.deadline === undefined\n ? await opts.worker.fetch(fallbackRequest)\n : await withTimeout(\n opts.worker.fetch(fallbackRequest),\n remainingTimeoutBudget(opts.deadline.startedAt, opts.deadline.timeoutMs, 'dispatch'),\n 'dispatch',\n ),\n pathname: fallback.destination,\n originalUrlVariant,\n applied: true,\n };\n}\n\nfunction buildFallbackOriginalUrlVariant(\n requestUrl: string,\n pathname: string,\n requestHost: string,\n routing: RoutingEntry,\n originalUrlVariant: string | undefined,\n): string | undefined {\n // Fallback rewrites are discovered after the first worker/static miss, but\n // ISR needs the read key before dispatching. If a fallback rule can handle\n // this pathname, use the same original-URL variant a later fallback dispatch\n // would expose via X-Void-Original-URL so query-allowlisted renders cannot\n // collide with the direct ISR key.\n if (originalUrlVariant || !routing.fallbackRules?.length) {\n return originalUrlVariant;\n }\n const fallback = applyRoutingRules(pathname, routing.fallbackRules, requestHost);\n if (fallback?.type !== 'rewrite') {\n return undefined;\n }\n return buildVariantOriginalUrl(requestUrl, pathname, routing.queryAllowlist);\n}\n\nfunction resolveCachedWfpFallbackPathname(\n pathname: string,\n routing: RoutingEntry,\n requestHost: string,\n): string | undefined {\n const fallback = applyRoutingRules(pathname, routing.fallbackRules, requestHost);\n return fallback?.type === 'rewrite' ? fallback.destination : undefined;\n}\n\n// CF's error text for WC-4511 asset dedupe poisoning. Not guaranteed\n// stable \u2014 monitor fallback telemetry if CF's worker-runtime changes.\nconst CF_ASSETS_STUB_MARKER = 'Assets have not yet been deployed to this script';\n\nfunction isLikelyCfAssetStub(response: Response): boolean {\n if (response.status !== 200) {\n return false;\n }\n const contentType = response.headers.get('content-type')?.toLowerCase();\n if (!contentType?.startsWith('text/plain')) {\n return false;\n }\n const contentLengthRaw = response.headers.get('content-length');\n if (!contentLengthRaw) {\n return false;\n }\n const contentLength = Number.parseInt(contentLengthRaw, 10);\n return contentLength > 0 && contentLength < 200;\n}\n\n// Serve the requested asset from platform R2/KV using the mirror written\n// on deploy. Returns null if the routing entry lacks a manifest, the\n// manifest is missing from KV, or the path/hash cannot be resolved. The\n// caller turns that confirmed poison-stub fallback miss into an attributed\n// platform 503 so no successful cache entry can be written.\nfunction remainingTimeoutBudget(\n startedAt: number,\n timeoutMs: number,\n label = 'static-asset',\n): number {\n if (!(timeoutMs > 0 && Number.isFinite(timeoutMs))) {\n return timeoutMs;\n }\n const remainingMs = timeoutMs - (Date.now() - startedAt);\n if (remainingMs <= 0) {\n throw new DispatchTimeoutError(label);\n }\n return remainingMs;\n}\n\nasync function fetchAssetManifest(\n env: Env,\n deploymentId: string,\n projectId: string,\n timeoutMs: number,\n): Promise<Record<string, string> | null> {\n const hedgeDelayMs =\n timeoutMs > 0 && Number.isFinite(timeoutMs)\n ? Math.min(STATIC_ASSET_HEDGE_DELAY_MS, timeoutMs / 2)\n : 0;\n try {\n const raw = await withDelayedHedge(\n () => env.ROUTING.get(`manifest:${deploymentId}`, { cacheTtl: 86400 }),\n {\n delayMs: hedgeDelayMs,\n timeoutMs,\n label: 'static-asset',\n onHedge: () => {\n console.warn(\n JSON.stringify({\n event: 'wfp-asset-manifest-read-hedge',\n projectId,\n deploymentId,\n delayMs: hedgeDelayMs,\n ts: Date.now(),\n }),\n );\n },\n },\n );\n if (!raw) {\n return null;\n }\n return JSON.parse(raw) as Record<string, string>;\n } catch (error) {\n console.error(\n JSON.stringify({\n event:\n error instanceof DispatchTimeoutError\n ? 'wfp-asset-manifest-timeout'\n : 'wfp-asset-manifest-read-error',\n projectId,\n deploymentId,\n error:\n error instanceof DispatchTimeoutError\n ? undefined\n : error instanceof Error\n ? error.message\n : String(error),\n ts: Date.now(),\n }),\n );\n if (error instanceof DispatchTimeoutError) {\n throw error;\n }\n throw new StaticAssetReadError(error);\n }\n}\n\nasync function serveWfpAssetFallback(\n env: Env,\n routing: RoutingEntry,\n pathname: string,\n timeoutMs = 10000,\n fallbackPathname?: string,\n): Promise<{ response: Response; pathname: string } | null> {\n if (!routing.assetManifestId) {\n return null;\n }\n const startedAt = Date.now();\n const assetManifest = await fetchAssetManifest(\n env,\n routing.assetManifestId,\n routing.projectId,\n remainingTimeoutBudget(startedAt, timeoutMs),\n );\n if (!assetManifest) {\n return null;\n }\n const assetConfig: AssetConfig = routing.assetConfig ?? { not_found_handling: 'none' };\n let resolvedPathname = pathname;\n let resolved = resolveStaticPath(pathname, assetManifest, assetConfig);\n if ((!resolved || resolved.notFound) && fallbackPathname && fallbackPathname !== pathname) {\n const fallbackResolved = resolveStaticPath(fallbackPathname, assetManifest, assetConfig);\n if (fallbackResolved && !fallbackResolved.notFound) {\n resolved = fallbackResolved;\n resolvedPathname = fallbackPathname;\n }\n }\n if (!resolved) {\n return null;\n }\n if (resolved.redirect) {\n return {\n response: new Response(null, {\n status: 308,\n headers: { Location: resolved.redirect },\n }),\n pathname: resolvedPathname,\n };\n }\n const assetResponse = await fetchStaticAsset(\n env,\n resolved.hash,\n resolved.path,\n routing.projectId,\n routing.assetManifestId,\n remainingTimeoutBudget(startedAt, timeoutMs),\n );\n if (!assetResponse) {\n return null;\n }\n return {\n response: new Response(assetResponse.body, {\n status: resolved.notFound ? 404 : 200,\n headers: assetResponse.headers,\n }),\n pathname: resolvedPathname,\n };\n}\n\nfunction logWfpAssetFallback(\n routing: RoutingEntry,\n pathname: string,\n userAgent: string | null,\n): void {\n console.log(\n JSON.stringify({\n event: 'wfp-asset-fallback',\n projectId: routing.projectId,\n deploymentId: routing.assetManifestId,\n pathname,\n userAgent,\n ts: Date.now(),\n }),\n );\n}\n\nasync function maybeServeWfpAssetFallback(opts: {\n env: Env;\n routing: RoutingEntry;\n pathname: string;\n response: Response;\n userAgent: string | null;\n timeoutMs?: number;\n deadline?: Readonly<{ startedAt: number; timeoutMs: number }>;\n fallbackPathname?: string;\n}): Promise<{ response: Response; failureKind?: FailureKind; pathname: string }> {\n const startedAt = opts.deadline?.startedAt ?? Date.now();\n const timeoutMs = opts.deadline?.timeoutMs ?? opts.timeoutMs ?? 10000;\n if (isEventStreamResponse(opts.response)) {\n return { response: opts.response, pathname: opts.pathname };\n }\n if (!isLikelyCfAssetStub(opts.response)) {\n return { response: opts.response, pathname: opts.pathname };\n }\n let stubConfirmed = false;\n let fallback: { response: Response; pathname: string } | null;\n try {\n const body = await withTimeout(\n opts.response.clone().text(),\n remainingTimeoutBudget(startedAt, timeoutMs),\n 'static-asset',\n );\n if (!body.includes(CF_ASSETS_STUB_MARKER)) {\n return { response: opts.response, pathname: opts.pathname };\n }\n stubConfirmed = true;\n fallback = await serveWfpAssetFallback(\n opts.env,\n opts.routing,\n opts.pathname,\n remainingTimeoutBudget(startedAt, timeoutMs),\n opts.fallbackPathname,\n );\n } catch (error) {\n // Once the CF poison stub is confirmed, never pass its HTTP 200 through:\n // callers may cache successful responses. Surface an attributed platform\n // 503 instead so the failure is retryable without poisoning edge/ISR caches.\n if (error instanceof DispatchTimeoutError) {\n if (!stubConfirmed) {\n return {\n response: timeoutResponse(503, 'dispatch'),\n pathname: opts.pathname,\n };\n }\n return {\n response: staticAssetFailureResponse(PLATFORM_STATIC_ASSET_TIMEOUT),\n failureKind: PLATFORM_STATIC_ASSET_TIMEOUT,\n pathname: opts.pathname,\n };\n }\n if (error instanceof StaticAssetReadError) {\n return {\n response: staticAssetFailureResponse(PLATFORM_STATIC_ASSET_ERROR),\n failureKind: PLATFORM_STATIC_ASSET_ERROR,\n pathname: opts.pathname,\n };\n }\n throw error;\n }\n if (!fallback) {\n console.error(\n JSON.stringify({\n event: 'wfp-asset-fallback-missing',\n projectId: opts.routing.projectId,\n deploymentId: opts.routing.assetManifestId,\n pathname: opts.pathname,\n ts: Date.now(),\n }),\n );\n return {\n response: staticAssetFailureResponse(PLATFORM_STATIC_ASSET_MISSING),\n failureKind: PLATFORM_STATIC_ASSET_MISSING,\n pathname: opts.pathname,\n };\n }\n logWfpAssetFallback(opts.routing, fallback.pathname, opts.userAgent);\n return fallback;\n}\n\n/**\n * Rebuild a `Request` with mutated headers, optionally under a new URL.\n * Handles the body-preservation cases we hit at three points in the fetch\n * handler (ingress header-strip, rewrite URL swap, post-ISR dispatch):\n *\n * - Body already consumed/locked: drop body and any stale framing headers\n * (`content-length` / `transfer-encoding`) \u2014 some runtimes reject bodiless\n * frames that still advertise a framing size.\n * - GET / HEAD: no body to forward; skip the body + duplex dance.\n * - Everything else: forward the streaming body with `duplex: 'half'`.\n */\nexport function rebuildRequest(\n request: Request,\n url: string,\n mutateHeaders: (headers: Headers) => void,\n): Request {\n const headers = new Headers(request.headers);\n mutateHeaders(headers);\n // `cf` (country, colo, botManagement, tlsClientAuth, \u2026) is populated by\n // the CF edge and read by user workers. A plain `new Request(url, init)`\n // does not propagate it; we have to thread it through init.cf explicitly.\n const cfProperties = request.cf;\n if (request.bodyUsed || request.body?.locked) {\n headers.delete('content-length');\n headers.delete('transfer-encoding');\n return new Request(url, { method: request.method, headers, cf: cfProperties });\n }\n if (request.method === 'GET' || request.method === 'HEAD') {\n return new Request(url, { method: request.method, headers, cf: cfProperties });\n }\n return new Request(url, {\n method: request.method,\n headers,\n body: request.body,\n cf: cfProperties,\n // @ts-expect-error -- duplex required for streaming bodies in CF Workers\n duplex: 'half',\n });\n}\n\nexport default {\n async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {\n env = await resolvePlatformApplicationEnvironment(env);\n const url = new URL(request.url);\n if (\n !env.PLATFORM_INSTALLATION_ID &&\n url.pathname === '/health' &&\n request.headers.get('X-Health-Check') === 'void-admin'\n ) {\n return Response.json({ ok: true });\n }\n // The installer proves the complete cutover while the public routing gate\n // remains closed. This endpoint exposes no application data and is already\n // reserved for the installer's exact health-check header.\n if (\n env.PLATFORM_HEALTH_PROBE_TOKEN &&\n url.pathname === '/health' &&\n request.headers.get('X-Void-Platform-Probe') === env.PLATFORM_HEALTH_PROBE_TOKEN\n ) {\n return Response.json({\n ok: true,\n ...(env.PLATFORM_APPLICATION ? { installationId: env.PLATFORM_INSTALLATION_ID } : {}),\n });\n }\n if (\n env.PLATFORM_TRAFFIC_STATE === 'staging' ||\n env.PLATFORM_TRAFFIC_STATE === 'sandbox-drain' ||\n (env.PLATFORM_INSTALLATION_ID &&\n (await env.ROUTING.get(PLATFORM_DISABLED_KEY)) === PLATFORM_DISABLED_VALUE)\n ) {\n return createErrorResponse(request, 503, 'Platform disabled', {\n 'Cache-Control': 'no-store',\n });\n }\n const startTime = Date.now();\n // Budget for the bounded hot paths (static-asset reads, primary dispatch).\n // Unset \u2192 the 10s default. An explicit `0`/negative/non-finite override is\n // passed through verbatim, disabling the timers via `withTimeout`'s escape\n // hatch (any non-positive/non-finite value = \"no timer\") \u2014 an operator kill\n // switch that works WITHOUT a redeploy.\n const timeoutMs = resolveTimeoutMs(env.DISPATCH_TIMEOUT_MS);\n\n // Block Void-internal routes from external HTTP access.\n // Only /__void/* is reserved by the platform \u2014 other __ prefixes\n // (e.g. /__nuxt_content, /__og-image__) are user/framework assets.\n if (\n url.pathname.startsWith('/__void/') ||\n // Legacy: old SDK versions register these top-level paths. Block them\n // at the edge so we don't rely solely on worker-side token checks.\n // TODO: remove once all deployed workers use /__void/* paths. See #88\n url.pathname === '/__scheduled' ||\n url.pathname === '/__queue'\n ) {\n return createErrorResponse(request, 404, 'Not Found');\n }\n\n const selected = await resolveProjectHostname(url.hostname, env);\n const slug = selected.slug;\n if (selected.workersDev && !selected.projectId) {\n return createErrorResponse(request, 404, 'Not Found');\n }\n const routingKey = slug ?? `domain:${url.hostname}`;\n\n const routingRaw = await env.ROUTING.get(routingKey, { cacheTtl: 60 });\n if (!routingRaw) {\n return createErrorResponse(request, 404, 'Not Found', {\n 'Cache-Control': 'public, max-age=30',\n });\n }\n\n const routing: RoutingEntry = JSON.parse(routingRaw);\n if (selected.projectId && selected.projectId !== routing.projectId) {\n return createErrorResponse(request, 404, 'Not Found');\n }\n\n // Check if project is suspended\n if (routing.suspended) {\n return Response.json(\n { error: 'usage limit exceeded', reason: routing.suspended },\n { status: 429, headers: { 'Cache-Control': 'public, s-maxage=30, max-age=0' } },\n );\n }\n\n // Strip any client-supplied X-Void-Original-URL on entry. Dispatch owns this\n // header: the only legitimate source is a dispatch-side rewrite below, which\n // sets it on `workerRequest` with the true original URL. Allowing a client\n // value to flow through would let callers spoof the \"original URL\" seen by\n // user workers that trust the header.\n if (request.headers.has('X-Void-Original-URL')) {\n request = rebuildRequest(request, request.url, (headers) =>\n headers.delete('X-Void-Original-URL'),\n );\n }\n let pathname = url.pathname;\n let sharedIsrEntry: SharedIsrEntry | undefined;\n let requestType: RequestType =\n request.headers.get('upgrade')?.toLowerCase() === 'websocket' ? 'websocket' : 'static';\n\n const meter = (response: Response, options?: { failureKind?: FailureKind }) => {\n const responseBytes = isEventStreamResponse(response)\n ? 0\n : Number(response.headers.get('content-length') ?? 0);\n recordRequest(env, {\n projectId: routing.projectId,\n type: requestType,\n method: request.method,\n status: response.status,\n responseBytes,\n durationMs: Date.now() - startTime,\n slug: slug ?? url.hostname,\n ...(options?.failureKind && { failureKind: options.failureKind }),\n });\n if (routing.userId) {\n ctx.waitUntil(\n sendUsageEvent(env, {\n projectId: routing.projectId,\n userId: routing.userId,\n slug: slug ?? url.hostname,\n requests: 1,\n responseBytes,\n ...(response.status >= 500 && { status: response.status }),\n ...(options?.failureKind && { failureKind: options.failureKind }),\n }),\n );\n }\n const res = new Response(response.body, response);\n res.headers.delete('X-Void-No-Match');\n // Cache API and upstream responses have immutable headers. Strip the\n // internal cache marker only from this writable client response.\n res.headers.delete(SHARED_CACHE_POLICY_HEADER);\n res.headers.set('X-Hosted-By', 'void.cloud');\n return res;\n };\n\n // The user's worker blew the dispatch budget. It returned nothing, so it\n // logged nothing, and its own tail event records only `canceled` \u2014 which a\n // real client hang-up produces too. Dispatch is the only party that knows\n // it was the one that hung up, so it says so in the project's log stream.\n // Metering is unchanged; this only adds the explanation.\n const meterWorkerTimeout = () => {\n recordPlatformLog(env, {\n workerName: routing.workerName,\n method: request.method,\n url: request.url,\n status: 503,\n timeoutMs,\n });\n return meter(timeoutResponse(503, 'dispatch'));\n };\n\n // Routing rules \u2014 redirects short-circuit, rewrites modify pathname\n // Two distinct values flow out of a rewrite:\n // - `originalUrlVariant`: feeds the ISR variant key. Normalized via\n // `routing.queryAllowlist` so an attacker can't fan out cache slots\n // by varying `?utm`/`?cb`/etc.\n // - `originalUrlHeader`: the X-Void-Original-URL surfaced to user\n // workers for `c.originalUrl()`. Carries the full request URL \u2014\n // user code expects to see the actual URL the client sent.\n let originalUrlVariant: string | undefined;\n let originalUrlHeader: string | undefined;\n if (routing.redirectRules?.length) {\n const result = applyRoutingRules(pathname, routing.redirectRules, url.hostname);\n if (result?.type === 'redirect') {\n const location = mergeQueryIntoLocation(result.destination, url.search);\n return meter(\n new Response(null, { status: result.status, headers: { Location: location } }),\n );\n }\n if (result?.type === 'rewrite') {\n // Destination shape (path-absolute, no `//`, no `?`) is enforced by\n // the framework validator and re-checked by the API on manifest ingest\n // (see `packages/api/src/routes/deploy.ts`). Dispatch trusts those two\n // gates and does not re-validate here.\n originalUrlHeader = request.url;\n originalUrlVariant = buildVariantOriginalUrl(request.url, pathname, routing.queryAllowlist);\n pathname = result.destination;\n url.pathname = pathname;\n }\n }\n\n // If rewritten, build the request the worker + ISR should see (rewritten\n // URL + original-URL header).\n let workerRequest = request;\n if (originalUrlHeader) {\n workerRequest = rebuildRequest(request, url.toString(), (headers) =>\n headers.set('X-Void-Original-URL', originalUrlHeader),\n );\n }\n\n // Edge-cache hashed static assets (immutable, content-addressed URLs)\n if (routing.hashedAssetsPrefix && isSharedStaticCacheRequestEligible(request)) {\n const prefix = '/' + routing.hashedAssetsPrefix + '/';\n if (pathname.startsWith(prefix)) {\n // Cache key tracks the post-rewrite (hash-bearing) URL, not the\n // request URL: hashed entries are stored with a 1-year immutable\n // Cache-Control, so a redirect rule that maps a stable path like\n // /logo to /assets/logo-<hash>.png must not cache content under\n // /logo \u2014 a future deploy that points /logo at a different hash\n // would keep serving the stale entry. Strip query: hashed\n // filenames are already content-addressed by their pathname.\n const cacheUrl = new URL(url.toString());\n cacheUrl.search = '';\n const cacheKey = new Request(cacheUrl.toString());\n\n // Hashed assets are served straight from the immutable edge cache. Apply\n // routing.headerRules on the way OUT \u2014 on both cache HIT and MISS \u2014 instead\n // of baking them into the cached body. This is what lets a cross-origin\n // isolated app put COOP/COEP/CORP on its hashed worker/wasm assets: browsers\n // fetch those over GET, and without per-serve header application the GET\n // response (unlike a HEAD, which falls through to the worker and is handled\n // by the dispatch path's applyHeaderRules) would ship with no COEP, so a\n // module worker spawned from a require-corp document would be blocked.\n // Applying per-serve rather than at cache-write also means a header-rule\n // change in a later deploy takes effect even when the content hash \u2014 and\n // thus the unversioned, immutable cache key \u2014 is unchanged.\n //\n // Tenant rules apply ADDITIVELY only. The platform/origin owns how a\n // content-addressed asset is cached, represented, and framed on the wire;\n // tenants may ADD headers (COOP/COEP/CORP, security) but must not rewrite\n // the headers below, so each is restored from the pre-rule response after\n // the rules run. The set is exactly the headers whose forgery would corrupt\n // the asset or break the immutable-cache / usage-metering contract:\n // cache-control immutable contract; the cache-HIT check above keys on it\n // content-type wrong MIME breaks ES-module / WebAssembly loading\n // content-encoding a false `gzip` makes the browser mis-decode the bytes\n // content-length meter() bills from it; clients frame the body by it\n // content-range } forging range/framing semantics truncates or\n // accept-ranges } mis-reads a body the platform did not range-encode\n // transfer-encoding hop-by-hop framing; must never come from a tenant rule\n // Cosmetic metadata (Vary, ETag, ...) is left overridable \u2014 on an immutable\n // URL-keyed asset it is neither a corruption nor a security risk. This\n // mirrors how the static-asset paths force their own Cache-Control after\n // applyHeaderRules via clientRevalidateResponse.\n const MANAGED_ASSET_HEADERS = [\n 'cache-control',\n 'content-type',\n 'content-encoding',\n 'content-length',\n 'content-range',\n 'accept-ranges',\n 'transfer-encoding',\n ] as const;\n const finalizeAsset = (assetResponse: Response, failureKind?: FailureKind): Response => {\n const ruled = applyHeaderRules(assetResponse, pathname, routing.headerRules);\n // applyHeaderRules returns the same object when nothing matched \u2014 then\n // there is no override to undo and we can skip the header restore.\n if (ruled !== assetResponse) {\n for (const name of MANAGED_ASSET_HEADERS) {\n const managed = assetResponse.headers.get(name);\n if (managed === null) {\n ruled.headers.delete(name);\n } else {\n ruled.headers.set(name, managed);\n }\n }\n }\n return meter(ruled, failureKind ? { failureKind } : undefined);\n };\n\n const cache = applicationEdgeCache;\n const cached = await cache.match(cacheKey);\n if (\n cached?.headers.get('Cache-Control')?.includes('immutable') &&\n isCurrentStaticCacheResponse(cached)\n ) {\n if (!routing.staticDeploymentId) {\n const repairResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname,\n response: cached,\n userAgent: request.headers.get('user-agent'),\n timeoutMs,\n });\n if (repairResult.response !== cached) {\n if (isStaticCacheResponseEligible(repairResult.response)) {\n const repaired = new Response(repairResult.response.body, repairResult.response);\n repaired.headers.set('Cache-Control', 'public, max-age=31536000, immutable');\n markSharedCachePolicy(repaired.headers);\n const repairedForCache = repaired.clone();\n ctx.waitUntil(\n cache.delete(cacheKey).then(() => cache.put(cacheKey, repairedForCache)),\n );\n return finalizeAsset(repaired, repairResult.failureKind);\n }\n ctx.waitUntil(cache.delete(cacheKey));\n return finalizeAsset(repairResult.response, repairResult.failureKind);\n }\n }\n return finalizeAsset(cached);\n }\n if (cached) {\n await cache.delete(cacheKey);\n }\n // Cache miss \u2014 fetch from KV/R2 for static deployments, or invoke worker\n if (routing.staticDeploymentId) {\n const staticAssetStartedAt = Date.now();\n let assetManifest: Record<string, string> | null;\n try {\n assetManifest = await fetchAssetManifest(\n env,\n routing.staticDeploymentId,\n routing.projectId,\n remainingTimeoutBudget(staticAssetStartedAt, timeoutMs),\n );\n } catch (err) {\n if (err instanceof DispatchTimeoutError) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_TIMEOUT), {\n failureKind: PLATFORM_STATIC_ASSET_TIMEOUT,\n });\n }\n if (err instanceof StaticAssetReadError) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_ERROR), {\n failureKind: PLATFORM_STATIC_ASSET_ERROR,\n });\n }\n throw err;\n }\n if (!assetManifest) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_MISSING), {\n failureKind: PLATFORM_STATIC_ASSET_MISSING,\n });\n }\n // Manifest keys are decoded on-disk paths, but `pathname` stays\n // percent-encoded. Try the raw key, then the decoded key (e.g. a\n // hashed file named `oxc masthead.riv` requested as `oxc%20masthead.riv`).\n let assetPath = pathname;\n let hash = assetManifest[pathname];\n if (!hash) {\n const decoded = safeDecodePathname(pathname);\n if (decoded !== pathname && assetManifest[decoded]) {\n assetPath = decoded;\n hash = assetManifest[decoded];\n }\n }\n let response: Response;\n if (hash) {\n try {\n const assetResponse = await fetchStaticAsset(\n env,\n hash,\n assetPath,\n routing.projectId,\n routing.staticDeploymentId,\n remainingTimeoutBudget(staticAssetStartedAt, timeoutMs),\n );\n if (!assetResponse) {\n logStaticAssetMissing(routing, assetPath, hash);\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_MISSING), {\n failureKind: PLATFORM_STATIC_ASSET_MISSING,\n });\n }\n response = assetResponse;\n } catch (err) {\n // No `resolved.notFound` in scope on this hashed-asset branch \u2014 a\n // storage failure is always a real asset read, so fast 503.\n if (err instanceof DispatchTimeoutError) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_TIMEOUT), {\n failureKind: PLATFORM_STATIC_ASSET_TIMEOUT,\n });\n }\n if (err instanceof StaticAssetReadError) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_ERROR), {\n failureKind: PLATFORM_STATIC_ASSET_ERROR,\n });\n }\n throw err;\n }\n } else {\n response = createErrorResponse(request, 404, 'Not Found');\n }\n if (isStaticCacheResponseEligible(response)) {\n const res = new Response(response.body, response);\n res.headers.set('Cache-Control', 'public, max-age=31536000, immutable');\n markSharedCachePolicy(res.headers);\n ctx.waitUntil(cache.put(cacheKey, res.clone()));\n return finalizeAsset(res);\n }\n return finalizeAsset(response);\n }\n try {\n const worker = getWorker(env, routing);\n const wfpAssetStartedAt = Date.now();\n let response = await withTimeout(\n worker.fetch(workerRequest),\n remainingTimeoutBudget(wfpAssetStartedAt, timeoutMs),\n 'static-asset',\n );\n // Safety net for CF asset dedupe poisoning (WC-4511). See\n // meta/design-docs/0066. Detection only triggers on the CF\n // stub's fingerprint; all other responses stream through.\n const fallbackResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname,\n response,\n userAgent: request.headers.get('user-agent'),\n deadline: { startedAt: wfpAssetStartedAt, timeoutMs },\n });\n response = fallbackResult.response;\n const failureKind = fallbackResult.failureKind;\n if (isStaticCacheResponseEligible(response)) {\n const res = new Response(response.body, response);\n res.headers.set('Cache-Control', 'public, max-age=31536000, immutable');\n markSharedCachePolicy(res.headers);\n ctx.waitUntil(cache.put(cacheKey, res.clone()));\n return finalizeAsset(res, failureKind);\n }\n return finalizeAsset(response, failureKind);\n } catch (err) {\n if (err instanceof DispatchTimeoutError) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_TIMEOUT), {\n failureKind: PLATFORM_STATIC_ASSET_TIMEOUT,\n });\n }\n if (err instanceof Error && err.message.includes('Worker exceeded')) {\n return meter(Response.json({ error: 'CPU limit exceeded' }, { status: 429 }));\n }\n throw err;\n }\n }\n }\n\n // ISR: stale-while-revalidate for configured paths\n // Two-layer cache: Edge (per-colo, sub-ms) \u2192 R2 (global, ~50ms) \u2192 Worker (render)\n // Pages protocol (X-VoidPages) uses a separate JSON edge cache; HTML uses R2+edge.\n // ISR applies to SSR page paths only. An API route or an asset-extension\n // path that happens to match a catch-all page pattern must render live and\n // never enter the ISR cache \u2014 mirrors the write-back guard (requestType ===\n // 'ssr') below and how meta-frameworks resolve API routes to non-ISR outputs.\n const isSsrPath =\n routing.ssr === true &&\n isIsrEligiblePath(pathname, routing.pages, routing.revalidate, routing.pathRevalidate);\n if (isSsrPath && (routing.revalidate || routing.pages?.length)) {\n const isrTtl = resolvePageTtl(\n routing.pages,\n routing.revalidate,\n routing.pathRevalidate,\n pathname,\n );\n // Range requests must render LIVE so the origin produces a correct partial\n // response (`206 Partial Content`) for the requested byte range. They must\n // never read the shared ISR entry (a full body for a partial request) nor\n // write it (a truncated 206 that a later full request would then be served),\n // so bail out of the ISR ladder entirely before any cache read or write.\n if (\n isrTtl > 0 &&\n request.method === 'GET' &&\n !request.headers.has('Range') &&\n !shouldBypassIsr(request)\n ) {\n const isPagesRequest = request.headers.has('X-VoidPages');\n const isrDeploymentId = routing.version ?? 'legacy';\n const cache = applicationEdgeCache;\n const isrOriginalUrlVariant = buildFallbackOriginalUrlVariant(\n request.url,\n pathname,\n url.hostname,\n routing,\n originalUrlVariant,\n );\n const cacheKey = isrEdgeCacheKey(request, pathname, isrDeploymentId, isrOriginalUrlVariant);\n const jsonCacheKey = isrEdgeCacheKeyJson(\n request,\n pathname,\n isrDeploymentId,\n isrOriginalUrlVariant,\n );\n sharedIsrEntry = {\n projectId: routing.projectId,\n deploymentId: isrDeploymentId,\n host: url.hostname,\n pathname,\n originalUrl: isrOriginalUrlVariant,\n htmlKey: cacheKey,\n jsonKey: jsonCacheKey,\n };\n\n // Pages protocol: check JSON edge cache, fall through on miss\n if (isPagesRequest) {\n const jsonCached = await cache.match(jsonCacheKey);\n if (jsonCached && hasCurrentSharedCachePolicy(jsonCached)) {\n requestType = 'isr';\n return meter(clientRevalidateResponse(jsonCached));\n }\n if (jsonCached) {\n await cache.delete(jsonCacheKey);\n }\n // Miss \u2014 fall through to general dispatch (worker returns JSON for X-VoidPages)\n } else {\n // HTML path: Edge \u2192 R2 \u2192 Worker\n const purgePoisonedIsrEntry = async (): Promise<void> => {\n await deleteSharedIsrEntry(env, sharedIsrEntry!);\n };\n\n // L1: Edge cache (per-colo)\n const edgeCached = await cache.match(cacheKey);\n if (edgeCached && hasCurrentSharedCachePolicy(edgeCached)) {\n requestType = 'isr';\n const repairResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname,\n response: edgeCached,\n userAgent: request.headers.get('user-agent'),\n timeoutMs,\n fallbackPathname: resolveCachedWfpFallbackPathname(pathname, routing, url.hostname),\n });\n if (repairResult.response !== edgeCached) {\n ctx.waitUntil(purgePoisonedIsrEntry());\n return meter(\n repairResult.response.ok\n ? clientRevalidateResponse(repairResult.response)\n : repairResult.response,\n repairResult.failureKind ? { failureKind: repairResult.failureKind } : undefined,\n );\n }\n return meter(clientRevalidateResponse(edgeCached));\n }\n if (edgeCached) {\n await cache.delete(cacheKey);\n }\n\n // L2: R2 (global)\n const cached = await readIsrCache(\n env,\n routing.projectId,\n isrDeploymentId,\n url.hostname,\n pathname,\n isrOriginalUrlVariant,\n );\n if (cached) {\n const stale = isStale(cached);\n const cacheResponse = isrCacheResponse(cached, stale);\n const repairResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname,\n response: cacheResponse,\n userAgent: request.headers.get('user-agent'),\n timeoutMs,\n fallbackPathname: resolveCachedWfpFallbackPathname(pathname, routing, url.hostname),\n });\n if (repairResult.response !== cacheResponse) {\n ctx.waitUntil(purgePoisonedIsrEntry());\n requestType = 'isr';\n return meter(\n repairResult.response.ok\n ? clientRevalidateResponse(repairResult.response)\n : repairResult.response,\n repairResult.failureKind ? { failureKind: repairResult.failureKind } : undefined,\n );\n }\n if (stale) {\n const staleCacheResponse = cacheResponse.clone();\n ctx.waitUntil(\n revalidateInBackground(\n env,\n routing,\n workerRequest,\n url.hostname,\n pathname,\n isrTtl,\n cacheKey,\n jsonCacheKey,\n cached.createdAt + cached.ttl * 1000,\n isrOriginalUrlVariant,\n timeoutMs,\n ).then(async (sharedEntryChanged) => {\n if (!sharedEntryChanged) {\n await cache.put(cacheKey, staleCacheResponse);\n }\n }),\n );\n }\n requestType = 'isr';\n if (!stale) {\n ctx.waitUntil(cache.put(cacheKey, cacheResponse.clone()));\n }\n return meter(clientRevalidateResponse(cacheResponse));\n }\n\n // Cache miss: render via worker, cache in background\n requestType = 'isr';\n const worker = getWorker(env, routing);\n const isrWorkerStartedAt = Date.now();\n let workerResponse: Response;\n try {\n workerResponse = await withTimeout(\n worker.fetch(workerRequest),\n remainingTimeoutBudget(isrWorkerStartedAt, timeoutMs, 'dispatch'),\n 'dispatch',\n );\n } catch (error) {\n if (error instanceof DispatchTimeoutError) {\n return meterWorkerTimeout();\n }\n throw error;\n }\n let isWorkerEventStream = isEventStreamResponse(workerResponse);\n let workerResponseFailureKind: FailureKind | undefined;\n const cachePathname = pathname;\n const cacheOriginalUrlVariant = isrOriginalUrlVariant;\n const cacheKeyForWrite = cacheKey;\n const jsonCacheKeyForWrite = jsonCacheKey;\n // The pathname the ISR write is effectively for. A fallback rewrite can\n // turn a page 404 into a 200 from `/api/*` \u2014 a dynamic body that must\n // never be cached under the original page URL. `fallbackResult` is\n // block-scoped below, so capture its post-fallback pathname AND whether a\n // fallback fired here (the write gate needs both, out of that scope).\n let effectiveMissPathname = cachePathname;\n let missFallbackApplied = false;\n if (!isWorkerEventStream) {\n const assetFallbackResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname,\n response: workerResponse,\n userAgent: request.headers.get('user-agent'),\n deadline: { startedAt: isrWorkerStartedAt, timeoutMs },\n });\n workerResponse = assetFallbackResult.response;\n workerResponseFailureKind = assetFallbackResult.failureKind;\n isWorkerEventStream = isEventStreamResponse(workerResponse);\n }\n if (!isWorkerEventStream) {\n let fallbackResult: Awaited<ReturnType<typeof applyWorkerFallbackRules>>;\n try {\n fallbackResult = await applyWorkerFallbackRules({\n response: workerResponse,\n worker,\n dispatchReq: workerRequest,\n routing,\n pathname,\n url,\n originalRequestUrl: request.url,\n originalUrlHeader,\n originalUrlVariant: isrOriginalUrlVariant,\n deadline: { startedAt: isrWorkerStartedAt, timeoutMs },\n });\n } catch (error) {\n if (error instanceof DispatchTimeoutError) {\n return meterWorkerTimeout();\n }\n throw error;\n }\n if (fallbackResult.applied) {\n missFallbackApplied = true;\n effectiveMissPathname = fallbackResult.pathname;\n workerResponse = fallbackResult.response;\n isWorkerEventStream = isEventStreamResponse(workerResponse);\n if (!isWorkerEventStream) {\n const assetFallbackResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname: fallbackResult.pathname,\n response: workerResponse,\n userAgent: request.headers.get('user-agent'),\n deadline: { startedAt: isrWorkerStartedAt, timeoutMs },\n });\n workerResponse = assetFallbackResult.response;\n workerResponseFailureKind = assetFallbackResult.failureKind;\n isWorkerEventStream = isEventStreamResponse(workerResponse);\n }\n }\n }\n if (isWorkerEventStream) {\n return meter(workerResponse);\n }\n const ttl = resolveRevalidateTtl(workerResponse, isrTtl);\n // Only a full 200 may enter the shared full-response cache. `.ok` is\n // 200\u2013299 (INCLUDING 206 Partial Content), which would poison the entry.\n // Also gate on the POST-fallback pathname: a fallback that rewrote the\n // page 404 into a 200 from `/api/*` must never be cached under the\n // original page URL (an `/api` body is per-request dynamic). Never cache\n // a response that DECLARES itself uncacheable via Cache-Control\n // (private/no-store/no-cache). Finally \u2014 the shared-cache-safety gate \u2014\n // when a FALLBACK was APPLIED the render may enter the ORIGINAL page key\n // ONLY when the fallback TARGET is the WINNING EXACT declared literal ISR\n // page AND the render is HTML (see `isFallbackTargetCacheable`). Any other\n // target \u2014 a dotted `text/html` shell (`/account.html`), an undeclared\n // extensionless target (e.g. `/* \u2192 /graphql`), a catch-all/param page\n // match \u2014 is INDISTINGUISHABLE here from a per-user dynamic endpoint, so it\n // is NOT shared-cached (it is still SERVED live). Positive identification \u2014\n // never the mere ABSENCE of an opt-out header \u2014 is required: a\n // user-configured rewrite to a private endpoint must not be able to poison\n // the page key just by omitting Cache-Control.\n if (\n ttl > 0 &&\n workerResponse.status === 200 &&\n !isApiPath(effectiveMissPathname) &&\n !hasSharedCacheOptOut(workerResponse) &&\n (!missFallbackApplied ||\n isFallbackTargetCacheable(\n routing.pages,\n effectiveMissPathname,\n workerResponse,\n routing.pathRevalidate,\n ))\n ) {\n ctx.waitUntil(\n writeIsrCache(\n env,\n routing.projectId,\n isrDeploymentId,\n url.hostname,\n cachePathname,\n workerResponse,\n ttl,\n cacheOriginalUrlVariant,\n ),\n );\n ctx.waitUntil(\n populateJsonEdgeCache(cache, jsonCacheKeyForWrite, workerResponse, ttl, 'MISS'),\n );\n const cacheHeaders = new Headers(workerResponse.headers);\n cacheHeaders.set(\n 'Cache-Control',\n `public, s-maxage=${ttl}, max-age=0, must-revalidate`,\n );\n cacheHeaders.set('x-isr-cache', 'MISS');\n markSharedCachePolicy(cacheHeaders);\n cacheHeaders.delete('x-void-page-data');\n cacheHeaders.delete('set-cookie');\n const cacheResponse = new Response(workerResponse.clone().body, {\n status: workerResponse.status,\n headers: cacheHeaders,\n });\n ctx.waitUntil(cache.put(cacheKeyForWrite, cacheResponse.clone()));\n\n const clientHeaders = new Headers(cacheHeaders);\n clientHeaders.set('Cache-Control', CLIENT_REVALIDATE_CACHE_CONTROL);\n clientHeaders.delete(SHARED_CACHE_POLICY_HEADER);\n const clientResponse = new Response(workerResponse.body, {\n status: workerResponse.status,\n headers: clientHeaders,\n });\n return meter(\n clientResponse,\n workerResponseFailureKind ? { failureKind: workerResponseFailureKind } : undefined,\n );\n }\n if (\n workerResponse.status === 200 &&\n !missFallbackApplied &&\n (ttl === 0 || hasSharedCacheOptOut(workerResponse))\n ) {\n ctx.waitUntil(purgePoisonedIsrEntry());\n }\n return meter(\n workerResponse,\n workerResponseFailureKind ? { failureKind: workerResponseFailureKind } : undefined,\n );\n }\n }\n }\n\n // Edge-cache non-hashed static assets using deploy-versioned cache keys.\n // The same request gate feeds both cache reads and writes. Credentialed,\n // Range, and Pages-protocol requests must reach the worker instead of a\n // shared representation. For SSR deployments, a dotted path is only a\n // candidate when the emitted asset manifest positively identifies it.\n const staticCachePathname = pathname;\n const isStaticCandidate =\n isStaticCacheRequestEligible(request, staticCachePathname, routing) &&\n (await isKnownStaticAssetPath(env, staticCachePathname, routing, timeoutMs));\n\n let staticCacheKey: Request | undefined;\n if (isStaticCandidate) {\n // Project allowlisted query params into the key so a dynamic extensioned\n // route whose body depends on the query (e.g. an image/badge endpoint that\n // declares `queryAllowlist`) caches per-variant instead of collapsing to the\n // first render. Only EXACT (wildcard-free) allowlist patterns opt in: this\n // static-candidate cache has no per-path variant cap (unlike ISR), so a broad\n // `*` / prefix-wildcard entry here could let a cache-buster query fan out\n // true static assets. `buildVariantOriginalUrl` drops the query entirely when\n // no pattern matches, so a route with no exact match keeps its pathname-only\n // key \u2014 unchanged behavior. The allowlist is authored against the user-facing\n // path, so match on the original request pathname (a rewrite above may have\n // reassigned `pathname` to a destination).\n const cacheUrl = new URL(\n buildVariantOriginalUrl(\n request.url,\n new URL(request.url).pathname,\n exactQueryAllowlist(routing.queryAllowlist),\n ),\n );\n cacheUrl.searchParams.set('_v', String(routing.version));\n const candidateCacheKey = new Request(cacheUrl.toString());\n staticCacheKey = candidateCacheKey;\n const staticCache = applicationEdgeCache;\n const cached = await staticCache.match(candidateCacheKey);\n if (cached && isCurrentStaticCacheResponse(cached)) {\n requestType = 'static';\n if (!routing.staticDeploymentId) {\n const repairResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname,\n response: cached,\n userAgent: request.headers.get('user-agent'),\n timeoutMs,\n fallbackPathname: resolveCachedWfpFallbackPathname(pathname, routing, url.hostname),\n });\n if (repairResult.response !== cached) {\n if (isStaticCacheResponseEligible(repairResult.response)) {\n const finalRes = applyHeaderRules(\n repairResult.response,\n repairResult.pathname,\n routing.headerRules,\n );\n const repaired = new Response(finalRes.clone().body, finalRes);\n repaired.headers.set(\n 'Cache-Control',\n 'public, s-maxage=31536000, max-age=0, must-revalidate',\n );\n markSharedCachePolicy(repaired.headers);\n const repairedForCache = repaired.clone();\n ctx.waitUntil(\n staticCache\n .delete(candidateCacheKey)\n .then(() => staticCache.put(candidateCacheKey, repairedForCache)),\n );\n return meter(clientRevalidateResponse(finalRes));\n }\n ctx.waitUntil(staticCache.delete(candidateCacheKey));\n return meter(\n repairResult.response,\n repairResult.failureKind ? { failureKind: repairResult.failureKind } : undefined,\n );\n }\n }\n return meter(clientRevalidateResponse(cached));\n }\n if (cached) {\n // Entries written by older dispatch versions may contain an unverified\n // dynamic response. Do not serve it, and remove it opportunistically.\n await staticCache.delete(candidateCacheKey);\n }\n }\n\n // KV/R2-backed static serving \u2014 no WfP worker needed\n if (routing.staticDeploymentId) {\n const staticAssetStartedAt = Date.now();\n let assetManifest: Record<string, string> | null;\n try {\n assetManifest = await fetchAssetManifest(\n env,\n routing.staticDeploymentId,\n routing.projectId,\n remainingTimeoutBudget(staticAssetStartedAt, timeoutMs),\n );\n } catch (err) {\n if (err instanceof DispatchTimeoutError) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_TIMEOUT), {\n failureKind: PLATFORM_STATIC_ASSET_TIMEOUT,\n });\n }\n if (err instanceof StaticAssetReadError) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_ERROR), {\n failureKind: PLATFORM_STATIC_ASSET_ERROR,\n });\n }\n throw err;\n }\n if (!assetManifest) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_MISSING), {\n failureKind: PLATFORM_STATIC_ASSET_MISSING,\n });\n }\n const assetConfig: AssetConfig = routing.assetConfig ?? {};\n\n // Capture pathname before the fallback rewrite potentially mutates it.\n // The edge cache must be keyed on the path seen here (what the client\n // requested, post any pre-asset rewrites), not the rewrite target \u2014\n // otherwise future requests to this path miss the cache entry.\n const fallbackOriginPathname = pathname;\n let resolved = resolveStaticPath(pathname, assetManifest, assetConfig);\n\n // Fallback rules \u2014 fire only when nothing matched in static resolution.\n // Single-pass: re-resolve with rewritten path, no further fallbacks.\n // `fallbackRules` are status-200-only (enforced at API ingest), so\n // `applyRoutingRules` only ever yields `type: 'rewrite'` here.\n if (!resolved && routing.fallbackRules?.length) {\n const fallback = applyRoutingRules(pathname, routing.fallbackRules, url.hostname);\n if (fallback?.type === 'rewrite') {\n // Same trust model as the redirectRules rewrite above \u2014 framework +\n // API both validate destination shape before the manifest lands here.\n pathname = fallback.destination;\n url.pathname = pathname;\n resolved = resolveStaticPath(pathname, assetManifest, assetConfig);\n }\n }\n\n if (!resolved) {\n return meter(createErrorResponse(request, 404, 'Not Found'));\n }\n\n if (resolved.redirect) {\n return meter(\n new Response(null, {\n status: 308,\n headers: { Location: resolved.redirect },\n }),\n );\n }\n\n let assetResponse: Response | null;\n try {\n assetResponse = await fetchStaticAsset(\n env,\n resolved.hash,\n resolved.path,\n routing.projectId,\n routing.staticDeploymentId,\n remainingTimeoutBudget(staticAssetStartedAt, timeoutMs),\n );\n } catch (err) {\n // A stalled read of the not-found asset was always going to 404, so\n // return a fast 404 (must not trip the 5xx alert); a real asset read\n // that stalled \u2192 fast 503.\n if (err instanceof DispatchTimeoutError) {\n return meter(\n timeoutResponse(resolved.notFound ? 404 : 503, 'static-asset'),\n resolved.notFound ? undefined : { failureKind: PLATFORM_STATIC_ASSET_TIMEOUT },\n );\n }\n if (err instanceof StaticAssetReadError) {\n return meter(\n resolved.notFound\n ? createErrorResponse(request, 404, 'Not Found')\n : staticAssetFailureResponse(PLATFORM_STATIC_ASSET_ERROR),\n resolved.notFound ? undefined : { failureKind: PLATFORM_STATIC_ASSET_ERROR },\n );\n }\n throw err;\n }\n if (!assetResponse) {\n if (resolved.notFound) {\n return meter(createErrorResponse(request, 404, 'Not Found'));\n }\n logStaticAssetMissing(routing, resolved.path, resolved.hash);\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_MISSING), {\n failureKind: PLATFORM_STATIC_ASSET_MISSING,\n });\n }\n\n const status = resolved.notFound ? 404 : 200;\n const response = new Response(assetResponse.body, {\n status,\n headers: assetResponse.headers,\n });\n const finalRes = applyHeaderRules(response, pathname, routing.headerRules);\n\n // Populate edge cache (same pattern as existing deploy-versioned static cache).\n // Key on the ORIGINAL pathname the client requested, not the post-fallback\n // rewrite target \u2014 otherwise future requests to the original path miss.\n const edgeCacheKey =\n staticCacheKey ??\n (isSharedStaticCacheRequestEligible(request)\n ? new Request(`${url.origin}${fallbackOriginPathname}?_v=${routing.staticDeploymentId}`)\n : undefined);\n if (edgeCacheKey && isStaticCacheResponseEligible(finalRes)) {\n const cached = new Response(finalRes.clone().body, finalRes);\n cached.headers.set(\n 'Cache-Control',\n 'public, s-maxage=31536000, max-age=0, must-revalidate',\n );\n markSharedCachePolicy(cached.headers);\n ctx.waitUntil(applicationEdgeCache.put(edgeCacheKey, cached.clone()));\n }\n\n return meter(clientRevalidateResponse(finalRes));\n }\n\n // Dispatch to user worker \u2014 CF handles static assets transparently\n const worker = getWorker(env, routing);\n try {\n let dispatchReq = workerRequest;\n if (dispatchReq.bodyUsed) {\n dispatchReq = rebuildRequest(dispatchReq, dispatchReq.url, () => {});\n }\n // If a worker-backed fallbackRule could fire on a 404, the inner\n // re-dispatch needs the original body \u2014 but `worker.fetch` consumes\n // the body stream and `rebuildRequest` on a `bodyUsed` request drops\n // it (silently). Clone here so the fallback path has a replayable\n // copy. `Request.clone()` tees the stream on CF Workers. Skip the\n // clone when there are no fallback rules or the method has no body\n // (GET/HEAD) \u2014 the common case stays free.\n const hasBodyMethod = dispatchReq.method !== 'GET' && dispatchReq.method !== 'HEAD';\n const dispatchReqForFallback =\n hasBodyMethod && routing.fallbackRules?.length ? dispatchReq.clone() : dispatchReq;\n const workerDispatchStartedAt = Date.now();\n let response = await withTimeout(\n worker.fetch(dispatchReq),\n remainingTimeoutBudget(workerDispatchStartedAt, timeoutMs, 'dispatch'),\n 'dispatch',\n );\n let isEventStream = isEventStreamResponse(response);\n let responseFailureKind: FailureKind | undefined;\n\n // Safety net for CF asset dedupe poisoning (WC-4511). See\n // meta/design-docs/0066. Pre-check gates body read so non-asset\n // responses stream through untouched.\n if (!isEventStream) {\n const assetFallbackResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname,\n response,\n userAgent: request.headers.get('user-agent'),\n deadline: { startedAt: workerDispatchStartedAt, timeoutMs },\n });\n response = assetFallbackResult.response;\n responseFailureKind = assetFallbackResult.failureKind;\n isEventStream = isEventStreamResponse(response);\n }\n\n // routing.fallbackRules \u2014 for static deployments these fire post-asset\n // (line ~533). The user worker is the equivalent path resolver here, so\n // a 404 is the analogue of a static-asset miss. Single-pass: the\n // rewrite target's response is returned as-is even if it's also 404.\n //\n // `fallbackResult` is block-scoped below, but the ISR write-back gate\n // needs to know whether a fallback fired (the fallback-target positive-ID\n // check). Hoist the flag out here \u2014 mirrors the miss-write's\n // `missFallbackApplied`.\n let writebackFallbackApplied = false;\n if (!isEventStream) {\n const fallbackResult = await applyWorkerFallbackRules({\n response,\n worker,\n dispatchReq: dispatchReqForFallback,\n routing,\n pathname,\n url,\n originalRequestUrl: request.url,\n originalUrlHeader,\n originalUrlVariant,\n deadline: { startedAt: workerDispatchStartedAt, timeoutMs },\n });\n if (fallbackResult.applied) {\n writebackFallbackApplied = true;\n pathname = fallbackResult.pathname;\n url.pathname = pathname;\n originalUrlVariant = fallbackResult.originalUrlVariant;\n response = fallbackResult.response;\n isEventStream = isEventStreamResponse(response);\n if (!isEventStream) {\n const assetFallbackResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname,\n response,\n userAgent: request.headers.get('user-agent'),\n deadline: { startedAt: workerDispatchStartedAt, timeoutMs },\n });\n response = assetFallbackResult.response;\n responseFailureKind = assetFallbackResult.failureKind;\n isEventStream = isEventStreamResponse(response);\n }\n }\n }\n\n if (\n sharedIsrEntry &&\n response.status === 200 &&\n !writebackFallbackApplied &&\n (resolveRevalidateTtl(\n response,\n resolvePageTtl(\n routing.pages,\n routing.revalidate,\n routing.pathRevalidate,\n sharedIsrEntry.pathname,\n ),\n ) === 0 ||\n hasSharedCacheOptOut(response))\n ) {\n ctx.waitUntil(deleteSharedIsrEntry(env, sharedIsrEntry));\n }\n\n // Cache static asset at edge if eligible. Require a full 200 \u2014 `.ok` is\n // 200\u2013299 and would admit a `206 Partial Content` (a Range request to a\n // dotted SSR path skips the ISR ladder and falls through here), poisoning\n // the shared `<path>?_v=` key with a partial body that a later full request\n // could then be served. Mirrors the `status === 200` guard at the ISR sites.\n if (staticCacheKey && !writebackFallbackApplied && isStaticCacheResponseEligible(response)) {\n const res = new Response(response.body, response);\n res.headers.delete('x-void-page-data');\n const finalRes = applyHeaderRules(res, pathname, routing.headerRules);\n const cacheRes = new Response(finalRes.clone().body, finalRes);\n cacheRes.headers.set(\n 'Cache-Control',\n 'public, s-maxage=31536000, max-age=0, must-revalidate',\n );\n markSharedCachePolicy(cacheRes.headers);\n ctx.waitUntil(applicationEdgeCache.put(staticCacheKey, cacheRes.clone()));\n return meter(\n clientRevalidateResponse(finalRes),\n responseFailureKind ? { failureKind: responseFailureKind } : undefined,\n );\n }\n\n // Classify for metering\n const dynamicType = classifyDynamicRequestType(pathname, routing.ssr);\n if (dynamicType) {\n requestType = dynamicType;\n }\n\n // Write ISR cache on miss \u2014 skip pages protocol responses (JSON, not HTML)\n // Guard: only cache GET requests without credentials, and respect worker x-revalidate\n // Range requests are excluded here too: a partial (206) response must never\n // be written into the shared full-response ISR cache. Mirrors the ISR-ladder\n // guard above.\n if (\n (routing.revalidate || routing.pages?.length) &&\n !isEventStream &&\n !request.headers.has('X-VoidPages') &&\n request.method === 'GET' &&\n !request.headers.has('Range') &&\n !shouldBypassIsr(request)\n ) {\n const configTtl = resolvePageTtl(\n routing.pages,\n routing.revalidate,\n routing.pathRevalidate,\n pathname,\n );\n // Config TTL is the gatekeeper \u2014 worker x-revalidate can reduce but not enable ISR\n const isrTtl = configTtl > 0 ? resolveRevalidateTtl(response, configTtl) : 0;\n // Only a full 200 is cacheable \u2014 `.ok` (200\u2013299) would let a 206 poison the entry.\n // `requestType` was reclassified above from the POST-fallback pathname, so\n // `=== 'ssr'` already skips a fallback that rewrote to `/api` \u2014 the same\n // `/api` exclusion the miss-write and background-revalidation sites spell out\n // with `!isApiPath(effective\u2026)`. (This SSR-path gate is stricter than those two:\n // it also skips extension targets, but requests reaching this branch are not\n // the ssr+revalidate ISR-ladder path where SPA `/index.html` fallbacks cache.)\n //\n // Fallback positive-ID gate \u2014 the same one the miss-write and background sites\n // enforce: when a FALLBACK rewrote this request, the render may enter the shared\n // cache under the fallback TARGET key ONLY when that target is a positively\n // identified declared literal ISR page rendering HTML (`isFallbackTargetCacheable`).\n // A non-fallback SSR render is unaffected. This makes all three ISR write sites\n // apply identical fallback policy: a rewrite to an undeclared dynamic target\n // (e.g. `/api/* \u2192 /graphql`) is served LIVE but never shared-cached, even when it\n // omits a Cache-Control opt-out. (Without this, such a write is unreadable \u2014\n // keyed `<target>#rw=hash(<original non-ISR-eligible path>)`, which no later\n // request recomputes \u2014 but it is still a wasted KV write and a defense-in-depth\n // gap, so the gate is correct as both consistency and hardening.)\n if (\n isrTtl > 0 &&\n response.status === 200 &&\n requestType === 'ssr' &&\n !hasSharedCacheOptOut(response) &&\n (!writebackFallbackApplied ||\n isFallbackTargetCacheable(routing.pages, pathname, response, routing.pathRevalidate))\n ) {\n const isrDeploymentId = routing.version ?? 'legacy';\n ctx.waitUntil(\n writeIsrCache(\n env,\n routing.projectId,\n isrDeploymentId,\n url.hostname,\n pathname,\n response,\n isrTtl,\n originalUrlVariant,\n ),\n );\n const jsonCacheKey = isrEdgeCacheKeyJson(\n request,\n pathname,\n isrDeploymentId,\n originalUrlVariant,\n );\n ctx.waitUntil(\n populateJsonEdgeCache(applicationEdgeCache, jsonCacheKey, response, isrTtl, 'MISS'),\n );\n }\n }\n\n // Strip internal header before returning to client\n if (response.headers.has('x-void-page-data')) {\n const stripped = new Response(response.body, response);\n stripped.headers.delete('x-void-page-data');\n return meter(\n applyHeaderRules(stripped, pathname, routing.headerRules),\n responseFailureKind ? { failureKind: responseFailureKind } : undefined,\n );\n }\n return meter(\n applyHeaderRules(response, pathname, routing.headerRules),\n responseFailureKind ? { failureKind: responseFailureKind } : undefined,\n );\n } catch (err) {\n if (err instanceof DispatchTimeoutError) {\n if (err.label === 'static-asset') {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_TIMEOUT), {\n failureKind: PLATFORM_STATIC_ASSET_TIMEOUT,\n });\n }\n const dynamicType = classifyDynamicRequestType(pathname, routing.ssr);\n if (dynamicType) {\n requestType = dynamicType;\n }\n return meterWorkerTimeout();\n }\n if (err instanceof StaticAssetReadError) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_ERROR), {\n failureKind: PLATFORM_STATIC_ASSET_ERROR,\n });\n }\n if (err instanceof Error && err.message.includes('Worker exceeded')) {\n return meter(Response.json({ error: 'CPU limit exceeded' }, { status: 429 }));\n }\n throw err;\n }\n },\n\n async queue(batch: MessageBatch, env: Env): Promise<void> {\n if (\n env.PLATFORM_TRAFFIC_STATE === 'staging' ||\n env.PLATFORM_TRAFFIC_STATE === 'sandbox-drain'\n ) {\n console.warn(\n `[queue-relay] platform traffic is staging; retrying queue=\"${batch.queue}\" in ${PLATFORM_QUEUE_RETRY_DELAY_SECONDS}s`,\n );\n batch.retryAll({ delaySeconds: PLATFORM_QUEUE_RETRY_DELAY_SECONDS });\n return;\n }\n if (env.PLATFORM_INSTALLATION_ID) {\n let disabled: string | null;\n try {\n disabled = await env.ROUTING.get(PLATFORM_DISABLED_KEY);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(\n `[queue-relay] platform traffic gate read failed; retrying queue=\"${batch.queue}\" in ${PLATFORM_QUEUE_RETRY_DELAY_SECONDS}s error=${JSON.stringify(message)}`,\n );\n batch.retryAll({ delaySeconds: PLATFORM_QUEUE_RETRY_DELAY_SECONDS });\n return;\n }\n if (disabled === PLATFORM_DISABLED_VALUE) {\n console.warn(\n `[queue-relay] platform traffic is disabled; retrying queue=\"${batch.queue}\" in ${PLATFORM_QUEUE_RETRY_DELAY_SECONDS}s`,\n );\n batch.retryAll({ delaySeconds: PLATFORM_QUEUE_RETRY_DELAY_SECONDS });\n return;\n }\n }\n\n // Look up which user worker handles this queue\n const routingRaw = await env.ROUTING.get(`queue:${batch.queue}`, { cacheTtl: 60 });\n if (!routingRaw) {\n console.error(\n `[queue-relay] missing routing entry for queue=\"${batch.queue}\"; retrying all messages`,\n );\n batch.retryAll();\n return;\n }\n const { workerName, queueName, proxyToken } = JSON.parse(routingRaw) as QueueRoutingEntry;\n\n // Serialize batch for relay\n const messages = Array.from(batch.messages, (message) => ({\n id: message.id,\n timestamp: message.timestamp.toISOString(),\n body: message.body,\n attempts: message.attempts,\n }));\n\n const worker = env.DISPATCH.get(workerName);\n try {\n const body = JSON.stringify({ queue: queueName, messages });\n const queueHeaders: Record<string, string> = { 'Content-Type': 'application/json' };\n if (proxyToken) {\n queueHeaders['x-void-internal'] = proxyToken;\n }\n let res = await worker.fetch(\n new Request('https://internal/__void/queue', {\n method: 'POST',\n headers: queueHeaders,\n body,\n }),\n );\n // Legacy: fall back for workers deployed before the /__void/ migration.\n // TODO: remove once all deployed workers use /__void/* paths.\n if (res.status === 404) {\n res = await worker.fetch(\n new Request('https://internal/__queue', {\n method: 'POST',\n headers: queueHeaders,\n body,\n }),\n );\n }\n\n if (!res.ok) {\n // Preserve observability: dispatch tail ingests this under the\n // __platform-dispatch project key so operators can query who is\n // rejecting relays and why.\n let snippet = '';\n try {\n snippet = (await res.clone().text()).slice(0, 200);\n } catch {\n /* body may be unreadable \u2014 status alone is still useful */\n }\n console.error(\n `[queue-relay] relay failed queue=\"${queueName}\" worker=\"${workerName}\" status=${res.status} body=${JSON.stringify(snippet)}`,\n );\n batch.retryAll();\n return;\n }\n\n let result: {\n ok?: boolean;\n decisions?: Record<string, { action: string; delaySeconds?: number }>;\n };\n try {\n result = await res.json();\n } catch {\n // Non-JSON 2xx = legacy framework, treat as success\n batch.ackAll();\n return;\n }\n\n if (!result.decisions) {\n // No decisions = legacy protocol, batch fallback\n if (result.ok !== false) {\n batch.ackAll();\n } else {\n batch.retryAll();\n }\n return;\n }\n\n // Apply per-message decisions\n const messageMap = new Map(batch.messages.map((message) => [message.id, message]));\n for (const [id, decision] of Object.entries(result.decisions)) {\n const cfMessage = messageMap.get(id);\n if (!cfMessage) {\n continue;\n }\n if (decision.action === 'ack') {\n cfMessage.ack();\n } else if (decision.action === 'retry') {\n cfMessage.retry(\n decision.delaySeconds != null ? { delaySeconds: decision.delaySeconds } : undefined,\n );\n }\n }\n\n // Undecided messages: if handler failed, retry all (individual decisions survive per CF)\n if (result.ok === false) {\n batch.retryAll();\n }\n // If ok=true, undecided messages get implicit ack (CF default on successful consumer return)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(\n `[queue-relay] relay threw queue=\"${queueName}\" worker=\"${workerName}\" error=${JSON.stringify(msg)}`,\n );\n batch.retryAll();\n }\n },\n} satisfies ExportedHandler<Env>;\n\nclass StaticAssetReadError extends Error {\n constructor(cause: unknown) {\n super('Static asset storage read failed', { cause });\n this.name = 'StaticAssetReadError';\n }\n}\n\nfunction logStaticAssetMissing(routing: RoutingEntry, pathname: string, hash: string): void {\n console.error(\n JSON.stringify({\n event: 'static-asset-missing',\n store: hash.startsWith('!') ? 'r2' : 'kv',\n projectId: routing.projectId,\n deploymentId: routing.staticDeploymentId ?? routing.assetManifestId,\n pathname,\n ts: Date.now(),\n }),\n );\n}\n\n/**\n * Fetch a static asset from KV (legacy small files) or R2 (`!`-prefixed modern\n * direct uploads and legacy large files).\n *\n * The complete scoped\u2192legacy sequence gets one delayed hedge and one absolute\n * timeout. Hedging the sequence (rather than each binding result) means a KV\n * `{ value: null }` miss has the same semantics as an R2 `null` miss.\n *\n * Each sequence tries the project-scoped key first\n * (`assets/{projectId}/{hash}`), then the legacy shared key (`assets/{hash}`)\n * for backward compatibility with deployments created before asset key\n * scoping.\n * Returns null if the asset is not found.\n */\nasync function fetchStaticAsset(\n env: Env,\n hash: string,\n path: string,\n projectId?: string,\n deploymentId?: string,\n timeoutMs = 10000,\n): Promise<Response | null> {\n const hedgeDelayMs =\n timeoutMs > 0 && Number.isFinite(timeoutMs)\n ? Math.min(STATIC_ASSET_HEDGE_DELAY_MS, timeoutMs / 2)\n : 0;\n const startedAt = Date.now();\n let hedged = false;\n\n try {\n const result = await withDelayedHedge(() => fetchStaticAssetOnce(env, hash, path, projectId), {\n delayMs: hedgeDelayMs,\n timeoutMs,\n label: 'static-asset',\n discard: async (late) => {\n await late.body?.cancel();\n },\n onHedge: () => {\n hedged = true;\n console.warn(\n JSON.stringify({\n event: 'static-asset-read-hedge',\n store: hash.startsWith('!') ? 'r2' : 'kv',\n projectId,\n deploymentId,\n pathname: path,\n delayMs: hedgeDelayMs,\n ts: Date.now(),\n }),\n );\n },\n });\n\n if (hedged) {\n console.warn(\n JSON.stringify({\n event: 'static-asset-read-hedge-result',\n store: hash.startsWith('!') ? 'r2' : 'kv',\n projectId,\n deploymentId,\n pathname: path,\n outcome: result === null ? 'miss' : 'hit',\n elapsedMs: Date.now() - startedAt,\n ts: Date.now(),\n }),\n );\n }\n return result;\n } catch (error) {\n console.error(\n JSON.stringify({\n event:\n error instanceof DispatchTimeoutError\n ? 'static-asset-timeout'\n : 'static-asset-read-error',\n store: hash.startsWith('!') ? 'r2' : 'kv',\n projectId,\n deploymentId,\n pathname: path,\n hedged,\n elapsedMs: Date.now() - startedAt,\n error:\n error instanceof DispatchTimeoutError\n ? undefined\n : error instanceof Error\n ? error.message\n : String(error),\n ts: Date.now(),\n }),\n );\n if (error instanceof DispatchTimeoutError) {\n throw error;\n }\n throw new StaticAssetReadError(error);\n }\n}\n\nasync function fetchStaticAssetOnce(\n env: Env,\n hash: string,\n path: string,\n projectId?: string,\n): Promise<Response | null> {\n const isLarge = hash.startsWith('!');\n const cleanHash = isLarge ? hash.slice(1) : hash;\n const scopedKey = projectId ? `assets/${projectId}/${cleanHash}` : null;\n const legacyKey = `assets/${cleanHash}`;\n\n if (isLarge) {\n // Try scoped key first, then legacy\n const obj = scopedKey\n ? ((await env.STATIC_ASSETS_R2.get(scopedKey)) ?? (await env.STATIC_ASSETS_R2.get(legacyKey)))\n : await env.STATIC_ASSETS_R2.get(legacyKey);\n if (!obj) {\n return null;\n }\n const contentType = resolveAssetContentType(obj.httpMetadata?.contentType, path);\n const headers: HeadersInit = {\n ETag: obj.httpEtag,\n ...(obj.size ? { 'Content-Length': String(obj.size) } : {}),\n };\n if (contentType) {\n (headers as Record<string, string>)['Content-Type'] = contentType;\n }\n return new Response(obj.body, { headers });\n }\n\n // Try scoped key first, then legacy\n if (scopedKey) {\n const scoped = await env.STATIC_ASSETS.getWithMetadata<{ ct: string }>(scopedKey, {\n type: 'arrayBuffer',\n cacheTtl: 86400,\n });\n if (scoped.value) {\n const contentType = resolveAssetContentType(scoped.metadata?.ct, path);\n const headers: HeadersInit = {\n 'Content-Length': String((scoped.value as ArrayBuffer).byteLength),\n };\n if (contentType) {\n (headers as Record<string, string>)['Content-Type'] = contentType;\n }\n return new Response(scoped.value, { headers });\n }\n }\n\n const { value, metadata } = await env.STATIC_ASSETS.getWithMetadata<{ ct: string }>(legacyKey, {\n type: 'arrayBuffer',\n cacheTtl: 86400,\n });\n if (!value) {\n return null;\n }\n const contentType = resolveAssetContentType(metadata?.ct, path);\n const headers: HeadersInit = {\n 'Content-Length': String((value as ArrayBuffer).byteLength),\n };\n if (contentType) {\n (headers as Record<string, string>)['Content-Type'] = contentType;\n }\n return new Response(value, { headers });\n}\n\n/** Get a dispatch worker, applying custom limits if configured. */\nfunction getWorker(env: Env, routing: RoutingEntry): Fetcher {\n if (routing.limits) {\n return env.DISPATCH.get(routing.workerName, {}, { limits: routing.limits });\n }\n return env.DISPATCH.get(routing.workerName);\n}\n\n/**\n * Revalidate an ISR page in the background.\n * Dispatches to the user worker (always as HTML, no X-VoidPages), writes HTML\n * to R2 + HTML edge cache, and populates JSON edge cache from embedded page data.\n * Errors are caught and logged \u2014 serve stale, don't retry.\n */\nasync function revalidateInBackground(\n env: Env,\n routing: RoutingEntry,\n request: Request,\n host: string,\n pathname: string,\n defaultTtl: number,\n cacheKey: Request,\n jsonCacheKey: Request,\n staleSinceMs: number,\n originalUrl?: string | null,\n timeoutMs = 10000,\n): Promise<boolean> {\n try {\n const worker = getWorker(env, routing);\n const revalidationStartedAt = Date.now();\n // Strip X-VoidPages so the worker always returns HTML.\n // Use rebuildRequest so request.cf (country/colo/botManagement/tlsClientAuth)\n // survives the rebuild \u2014 otherwise the background re-render runs with\n // cf === undefined and writes wrong-geo/wrong-bot HTML into the ISR cache.\n const cleanRequest = rebuildRequest(request, request.url, (headers) =>\n headers.delete('X-VoidPages'),\n );\n let response = await withTimeout(\n worker.fetch(cleanRequest),\n remainingTimeoutBudget(revalidationStartedAt, timeoutMs, 'dispatch'),\n 'dispatch',\n );\n if (isEventStreamResponse(response)) {\n return false;\n }\n // Capture the ORIGIN page's OWN pre-fallback status. Only a genuine removal\n // signal (404/410 Gone) may later drive grace-eviction; a transient 5xx / 429 /\n // timeout must PRESERVE the stale entry (stale-while-revalidate). Read it here,\n // before `applyWorkerFallbackRules` reassigns `response` to a fallback target.\n const originalStatus = response.status;\n const fallbackResult = await applyWorkerFallbackRules({\n response,\n worker,\n dispatchReq: cleanRequest,\n routing,\n pathname,\n url: new URL(cleanRequest.url),\n originalRequestUrl: request.url,\n originalUrlHeader: request.headers.get('X-Void-Original-URL') ?? undefined,\n originalUrlVariant: originalUrl ?? undefined,\n deadline: { startedAt: revalidationStartedAt, timeoutMs },\n });\n response = fallbackResult.response;\n if (isEventStreamResponse(response)) {\n return false;\n }\n const assetFallbackResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname: fallbackResult.pathname,\n response,\n userAgent: request.headers.get('user-agent'),\n deadline: { startedAt: revalidationStartedAt, timeoutMs },\n });\n response = assetFallbackResult.response;\n if (isEventStreamResponse(response)) {\n return false;\n }\n const ttl = resolveRevalidateTtl(response, defaultTtl);\n const cache = applicationEdgeCache;\n // Evict every shared representation of this entry: R2/KV + HTML edge + JSON edge.\n const evictSharedEntry = async () => {\n await deleteIsrCache(\n env,\n routing.projectId,\n routing.version ?? 'legacy',\n host,\n pathname,\n originalUrl,\n );\n await cache.delete(cacheKey);\n await cache.delete(jsonCacheKey);\n };\n // The pathname this background re-render effectively resolved to. A fallback\n // rewrite (page 404 \u2192 200 from `/api/*`) must not overwrite the page's ISR\n // entry with a dynamic API body \u2014 same guard as the miss-write.\n const effectiveBgPathname = fallbackResult.applied ? fallbackResult.pathname : pathname;\n // Only a full 200 may refresh the shared cache \u2014 a background re-render that\n // returns 206/etc. (`.ok` is 200\u2013299) must not overwrite the good entry.\n // A re-render that falls back to `/api/*` must not overwrite the page's entry\n // with a dynamic API body. And \u2014 the shared-cache-safety gate mirrored from the\n // miss-write \u2014 when a FALLBACK was APPLIED the re-render may refresh the ORIGINAL\n // page key ONLY when its TARGET is the winning EXACT declared literal ISR page\n // and the render is HTML; any other target (a dotted shell, an undeclared\n // extensionless `/graphql`) is not shared-cached and must not overwrite the entry.\n if (\n ttl > 0 &&\n response.status === 200 &&\n !isApiPath(effectiveBgPathname) &&\n !hasSharedCacheOptOut(response) &&\n (!fallbackResult.applied ||\n isFallbackTargetCacheable(\n routing.pages,\n effectiveBgPathname,\n response,\n routing.pathRevalidate,\n ))\n ) {\n await writeIsrCache(\n env,\n routing.projectId,\n routing.version ?? 'legacy',\n host,\n pathname,\n response,\n ttl,\n originalUrl,\n );\n // Update HTML edge cache with fresh response\n const headers = new Headers(response.headers);\n headers.set('x-isr-cache', 'HIT');\n headers.set('Cache-Control', `public, s-maxage=${ttl}, max-age=0, must-revalidate`);\n markSharedCachePolicy(headers);\n headers.delete('set-cookie');\n headers.delete('x-void-page-data');\n await cache.put(\n cacheKey,\n new Response(response.clone().body, {\n status: response.status,\n headers,\n }),\n );\n await populateJsonEdgeCache(cache, jsonCacheKey, response, ttl, 'HIT');\n return true;\n } else if (\n response.status === 200 &&\n !isApiPath(effectiveBgPathname) &&\n !fallbackResult.applied &&\n (ttl === 0 || hasSharedCacheOptOut(response))\n ) {\n // Evict the stale shared entry ONLY on an AUTHORITATIVE opt-out render of the\n // ORIGIN page itself: a successful render (200, NOT an `/api/*` fallback, and\n // NOT ANY applied fallback) that has withdrawn its public representation \u2014\n // either a permanent `x-revalidate: 0` opt-out OR a `Cache-Control` opt-out\n // (private/no-store/no-cache). A FALLBACK firing means the ORIGIN page 404'd\n // (often transiently \u2014 deploy race); the fallback TARGET's cache intent must\n // NOT delete the origin page's last-known-good entry, so `!fallbackResult.applied`\n // gates eviction to an authoritative render of the origin page. A transient\n // non-200 (even one carrying `x-revalidate: 0`) likewise must NOT evict \u2014 keep\n // serving the last known-good entry (stale-while-revalidate resilience). The\n // write gate already refuses to cache non-authoritative content, so eviction\n // must mirror it. Removes R2/KV + HTML + JSON edge.\n try {\n await evictSharedEntry();\n } catch (error) {\n console.error('ISR privacy eviction failed:', error);\n }\n return true;\n } else if (\n (originalStatus === 404 || originalStatus === 410) &&\n Date.now() - staleSinceMs > ISR_STALE_EVICT_GRACE_SECONDS * 1000\n ) {\n // Convergence \u2014 ONLY on positive removal evidence: the ORIGIN page's OWN\n // pre-fallback render returned 404 or 410 (gone). Such a re-render could neither\n // refresh this entry nor trigger the authoritative opt-out eviction above (a\n // permanent origin 404 that falls back to a non-declared shell \u2014 C12 refuses to\n // cache it). It has now been STALE (since `createdAt + ttl`) beyond the bounded\n // grace \u2014 far past any transient deploy-race 404 \u2014 so the page is permanently\n // removed: evict it rather than serve its last cached body forever. A 5xx / 429 /\n // timeout / any other status is a DEGRADED DEPENDENCY, not a removal \u2014 it MUST\n // keep serving stale (stale-while-revalidate is exactly what protects that\n // request), so it never reaches this branch. Measuring from stale-onset (not\n // creation) means a long-TTL entry still gets the full grace and a transient\n // failure right after expiry keeps serving stale within the grace.\n try {\n await evictSharedEntry();\n } catch (error) {\n console.error('ISR stale-entry eviction failed:', error);\n }\n return true;\n }\n return false;\n } catch (err) {\n console.error('ISR revalidation failed:', err);\n return false;\n }\n}\n\n// An `/api` route (worker-dynamic). Such a path must never enter the shared\n// page ISR cache \u2014 directly, or via a fallback that rewrites a page 404 into a\n// 200 from `/api/*`. A `/api` response is per-request dynamic (cookies, auth,\n// live data); caching it under a page URL would serve one caller's response to\n// everyone. Used at every ISR write site on the effective post-fallback path.\nfunction isApiPath(pathname: string): boolean {\n return pathname === '/api' || pathname.startsWith('/api/');\n}\n\n// ISR eligibility for a REQUEST's own pathname: SSR page paths only \u2014 never an\n// `/api` route. A dotted path is ISR-eligible only when it matches a declared\n// page route that is NOT a broad catch-all \u2014 a literal (`/feed.xml`) or a\n// single-segment param (`/blog/:slug`, so `/blog/release.v2` gets ISR). A broad\n// catch-all (`/:path{.+}`, `*`) that merely happens to match a static asset like\n// `/robots.txt` does NOT make it page-ISR content. This is the read-gate\n// predicate; it deliberately does NOT gate the fallback WRITE sites, which key\n// off the fallback TARGET (see `isFallbackTargetCacheable`).\nfunction isIsrEligiblePath(\n pathname: string,\n pages: ReadonlyArray<{ pattern: string; revalidate?: number }> | undefined,\n revalidate: number | Record<string, number> | undefined,\n pathRevalidate: Record<string, number> | undefined,\n): boolean {\n if (isApiPath(pathname)) {\n return false;\n }\n if (!hasExtension(pathname)) {\n return true;\n }\n return isDottedPathIsrEligible(pages, revalidate, pathRevalidate, pathname);\n}\n\n// A fallback render may enter the shared ORIGINAL page key ONLY when the target is\n// the WINNING EXACT declared literal ISR page AND the render is HTML. There is no\n// safe path-shape signal for a \"static shell\": a dotted `text/html` target\n// (`/account.html`) is indistinguishable here from a dynamic per-user endpoint, so\n// path shape is NOT trusted. A static SPA shell reached via fallback is still\n// SERVED live; it is simply no longer opportunistically ISR-cached under a page key\n// (its cache home is the static-asset path). Full metadata-verified shell caching\n// would need an async asset-manifest lookup this write path does not have.\nfunction isFallbackTargetCacheable(\n pages: ReadonlyArray<{ pattern: string; revalidate?: number }> | undefined,\n targetPathname: string,\n response: Response,\n pathRevalidate: Record<string, number> | undefined,\n): boolean {\n return isHtmlResponse(response) && matchesLiteralPage(pages, targetPathname, pathRevalidate);\n}\n\n/**\n * Every static cache shares one representation across callers, so credentials,\n * EventSource semantics, partial requests, and Pages-protocol requests bypass it.\n */\nfunction isSharedStaticCacheRequestEligible(request: Request): boolean {\n return Boolean(\n request.method === 'GET' &&\n !request.headers.has('Range') &&\n !request.headers.has('X-VoidPages') &&\n !shouldBypassIsr(request),\n );\n}\n\n/** Shared request-side eligibility for the deploy-versioned static cache. */\nfunction isStaticCacheRequestEligible(\n request: Request,\n pathname: string,\n routing: RoutingEntry,\n): boolean {\n return Boolean(\n isSharedStaticCacheRequestEligible(request) &&\n routing.version &&\n !isApiPath(pathname) &&\n (hasExtension(pathname) || !routing.ssr),\n );\n}\n\nasync function isKnownStaticAssetPath(\n env: Env,\n pathname: string,\n routing: RoutingEntry,\n timeoutMs: number,\n): Promise<boolean> {\n if (routing.staticDeploymentId) {\n return true;\n }\n if (!routing.ssr) {\n return true;\n }\n if (!routing.assetManifestId) {\n return false;\n }\n try {\n const manifest = await fetchAssetManifest(\n env,\n routing.assetManifestId,\n routing.projectId,\n Math.min(timeoutMs, STATIC_ASSET_HEDGE_DELAY_MS),\n );\n if (!manifest) {\n return false;\n }\n if (Object.hasOwn(manifest, pathname)) {\n return true;\n }\n const decoded = safeDecodePathname(pathname);\n return decoded !== pathname && Object.hasOwn(manifest, decoded);\n } catch {\n // Asset identity is an optimization gate. If the manifest is unavailable,\n // dispatch the request live instead of guessing from the URL or response.\n return false;\n }\n}\n\n/** Apply the same origin/cached response policy to static reads and writes. */\nfunction isStaticCacheResponseEligible(response: Response): boolean {\n return (\n response.status === 200 && !isEventStreamResponse(response) && !hasSharedCacheOptOut(response)\n );\n}\n\n/** Only entries written under the current shared-cache policy are safe to serve. */\nfunction isCurrentStaticCacheResponse(response: Response): boolean {\n return hasCurrentSharedCachePolicy(response) && isStaticCacheResponseEligible(response);\n}\n"],
|
|
6
|
-
"mappings": "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",
|
|
5
|
+
"sourcesContent": ["//#region src/authentication-recovery.ts\nfunction platformAuthenticationRecoveryMessage(value) {\n\treturn JSON.stringify([\n\t\t\"void-platform-auth-recovery-v1\",\n\t\tvalue.installationId,\n\t\tvalue.administratorUserId,\n\t\tvalue.connectionId,\n\t\tvalue.revision,\n\t\tvalue.generation,\n\t\tvalue.testId,\n\t\tvalue.expiresAt\n\t]);\n}\n//#endregion\n//#region src/authentication.ts\n/** Platform login and perimeter configuration are independent of app authentication. */\nconst PLATFORM_LOGIN_KINDS = [\n\t\"github\",\n\t\"google\",\n\t\"oidc\",\n\t\"cloudflare-access\"\n];\n/** Operator-side coverage verification, bound to one administrator and settings revision. */\nfunction platformProtectionProofMessage(input) {\n\treturn `void-platform-protection-v1\\n${JSON.stringify({\n\t\tinstallationId: input.installationId,\n\t\torigin: input.origin,\n\t\tuserId: input.userId,\n\t\tsessionId: input.sessionId,\n\t\trevision: input.revision,\n\t\tlifecycleVersion: input.lifecycleVersion,\n\t\tprotection: parsePlatformAccessProtection(input.protection),\n\t\texpiresAt: input.expiresAt\n\t})}`;\n}\nfunction parsePlatformSignupAllowlistEntry(value) {\n\tconst entry = record(value, \"Signup allowlist entry\");\n\tconst note = entry.note;\n\tif (note !== void 0 && (typeof note !== \"string\" || note.length > 1e3)) throw new Error(\"Signup allowlist notes must be strings of at most 1000 characters.\");\n\tconst optionalNote = note === void 0 ? {} : { note };\n\tif (entry.type === \"identity\") {\n\t\tconst connectionId = parsePlatformLoginId(entry.connectionId);\n\t\tif (typeof entry.subject !== \"string\" || entry.subject.length === 0 || entry.subject.length > 255) throw new Error(\"Identity subjects must be nonempty strings of at most 255 characters.\");\n\t\treturn {\n\t\t\ttype: \"identity\",\n\t\t\tconnectionId,\n\t\t\tsubject: entry.subject,\n\t\t\t...optionalNote\n\t\t};\n\t}\n\tif (entry.type !== \"github\" && entry.type !== \"email\") throw new Error(\"Signup allowlist entry type must be github, email, or identity.\");\n\tif (typeof entry.pattern !== \"string\" || !entry.pattern || entry.pattern.length > 320 || /[\\s,]/.test(entry.pattern)) throw new Error(\"Signup allowlist patterns must be nonempty strings of at most 320 characters.\");\n\treturn {\n\t\ttype: entry.type,\n\t\tpattern: entry.pattern,\n\t\t...optionalNote\n\t};\n}\n/** Match one verified login identity against persisted signup grants. */\nfunction isPlatformSignupAllowed(identity, entries) {\n\treturn entries.some((entry) => {\n\t\tif (entry.type === \"identity\") return entry.connectionId === identity.connectionId && entry.subject === identity.subject;\n\t\tif (entry.type === \"github\") return identity.provider === \"github\" && entry.pattern.toLowerCase() === identity.login.toLowerCase();\n\t\tif (!identity.email) return false;\n\t\tif (entry.pattern.startsWith(\"*@\")) return identity.email.toLowerCase().endsWith(entry.pattern.slice(1).toLowerCase());\n\t\treturn entry.pattern.toLowerCase() === identity.email.toLowerCase();\n\t});\n}\nfunction parsePlatformAuthenticationSetup(value) {\n\tconst input = record(value, \"Authentication setup\");\n\tif (!Array.isArray(input.connections) || input.connections.length === 0 || input.connections.length > 32) throw new Error(\"Authentication setup requires between 1 and 32 connections.\");\n\tconst connections = input.connections.map((value) => {\n\t\tconst entry = record(value, \"Login connection\");\n\t\tstring(entry.clientSecret, \"Client secret\", 8192);\n\t\treturn {\n\t\t\tconfiguration: parsePlatformLoginConfiguration(entry.configuration),\n\t\t\tclientSecret: entry.clientSecret\n\t\t};\n\t});\n\tif (new Set(connections.map((entry) => entry.configuration.id)).size !== connections.length) throw new Error(\"Authentication setup connection IDs must be unique.\");\n\tconst administratorConnectionId = parsePlatformLoginId(input.administratorConnectionId);\n\tif (!connections.some((entry) => entry.configuration.id === administratorConnectionId)) throw new Error(\"The administrator login method must be included in setup.\");\n\tif (typeof input.bootstrapCredentialHash !== \"string\" || !/^[a-f0-9]{64}$/.test(input.bootstrapCredentialHash)) throw new Error(\"A SHA-256 bootstrap credential hash is required.\");\n\tconst admission = parsePlatformAdmissionPolicy(input.admission);\n\tconst protection = parsePlatformAccessProtection(input.protection ?? null);\n\tvalidatePlatformAdmissionPolicy(admission, connections.map((entry) => entry.configuration), protection);\n\tif (input.resetPending !== void 0 && typeof input.resetPending !== \"boolean\") throw new Error(\"resetPending must be a boolean.\");\n\treturn {\n\t\tconnections,\n\t\tadministratorConnectionId,\n\t\tbootstrapCredentialHash: input.bootstrapCredentialHash,\n\t\tadmission,\n\t\tprotection,\n\t\t...input.resetPending === true ? { resetPending: true } : {}\n\t};\n}\nconst DEFAULT_PLATFORM_SESSION_SECONDS = 2592e3;\nconst GOOGLE_OIDC_ISSUER = \"https://accounts.google.com\";\nconst PLATFORM_AUTH_SETUP_PROOF_PREFIX = \"void.platform.auth.setup.v1\";\nfunction record(value, name) {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(`${name} must be an object.`);\n\treturn value;\n}\nfunction string(value, name, maximum = 512) {\n\tif (typeof value !== \"string\" || !value.trim() || value.length > maximum || Array.from(value).some((character) => character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127)) throw new Error(`${name} must be a nonempty string of at most ${maximum} characters.`);\n\treturn value.trim();\n}\nfunction strings(value, name, maximum = 100) {\n\tif (!Array.isArray(value) || value.length > maximum) throw new Error(`${name} must be an array of at most ${maximum} strings.`);\n\tconst result = value.map((entry) => string(entry, name));\n\tif (new Set(result).size !== result.length) throw new Error(`${name} must not contain duplicates.`);\n\treturn result;\n}\nfunction parsePlatformLoginId(value) {\n\tif (typeof value !== \"string\" || !/^[a-z][a-z0-9-]{0,63}$/.test(value)) throw new Error(\"Login connection IDs must start with a letter and use 1\u201364 lowercase letters, digits, or hyphens.\");\n\treturn value;\n}\n/** HTTPS syntax validation; outbound network policy must additionally validate resolved endpoints. */\nfunction parsePlatformIdentityUrl(value, name, originOnly = false) {\n\tconst input = string(value, name, 2048);\n\tlet url;\n\ttry {\n\t\turl = new URL(input);\n\t} catch {\n\t\tthrow new Error(`${name} must be a credential-free HTTPS URL.`);\n\t}\n\tif (url.protocol !== \"https:\" || url.username || url.password || url.search || url.hash || originOnly && url.pathname !== \"/\") throw new Error(`${name} must be a credential-free HTTPS ${originOnly ? \"origin\" : \"URL\"} without query or fragment.`);\n\treturn originOnly ? url.origin : input;\n}\nfunction parsePlatformLoginDescriptor(value) {\n\tconst entry = record(value, \"Login connection\");\n\tconst id = parsePlatformLoginId(entry.id);\n\tif (!PLATFORM_LOGIN_KINDS.includes(entry.kind)) throw new Error(\"Login kind must be github, google, oidc, or cloudflare-access.\");\n\tconst kind = entry.kind;\n\tif ((id === \"github\" || id === \"google\") && id !== kind) throw new Error(`Connection ID ${id} is reserved for ${id} login.`);\n\tif ((kind === \"github\" || kind === \"google\") && id !== kind) throw new Error(`${kind} uses the fixed connection ID ${kind}.`);\n\treturn {\n\t\tid,\n\t\tkind,\n\t\tlabel: string(entry.label, \"Login label\", 100)\n\t};\n}\nfunction parsePlatformLoginConfiguration(value) {\n\tconst entry = record(value, \"Login configuration\");\n\tconst descriptor = parsePlatformLoginDescriptor(entry);\n\tconst clientId = string(entry.clientId, \"Client ID\");\n\tconst allowedDomains = strings(entry.allowedDomains ?? [], \"Allowed domains\").map((domain) => {\n\t\tconst normalized = domain.toLowerCase();\n\t\tif (!/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z]{2,63}$/.test(normalized)) throw new Error(\"Allowed domains must be exact domain names, without wildcards.\");\n\t\treturn normalized;\n\t});\n\tif (new Set(allowedDomains).size !== allowedDomains.length) throw new Error(\"Allowed domains must not contain duplicates.\");\n\tconst requiredGroups = strings(entry.requiredGroups ?? [], \"Required groups\");\n\tif (descriptor.kind !== \"google\" && allowedDomains.length > 0) throw new Error(\"Workspace domain restrictions are only supported by Google login.\");\n\tif ((descriptor.kind === \"github\" || descriptor.kind === \"google\") && requiredGroups.length > 0) throw new Error(\"Group restrictions require an OIDC or Cloudflare Access connection.\");\n\tlet issuer;\n\tif (descriptor.kind === \"google\") {\n\t\tif (entry.issuer !== void 0 && entry.issuer !== \"https://accounts.google.com\") throw new Error(\"Google login uses the Google issuer.\");\n\t\tissuer = GOOGLE_OIDC_ISSUER;\n\t} else if (descriptor.kind === \"github\") {\n\t\tif (entry.issuer !== void 0) throw new Error(\"GitHub login does not accept an OIDC issuer.\");\n\t} else {\n\t\tissuer = parsePlatformIdentityUrl(entry.issuer, \"OIDC issuer\");\n\t\tif (descriptor.kind === \"cloudflare-access\") {\n\t\t\tconst url = new URL(issuer);\n\t\t\tif (!/^[a-z0-9-]+\\.cloudflareaccess\\.com$/.test(url.hostname) || url.port || !url.pathname.startsWith(\"/cdn-cgi/access/sso/oidc/\") || decodeURIComponent(url.pathname.slice(25).replace(/\\/$/, \"\")) !== clientId) throw new Error(\"Cloudflare Access login requires its application issuer URL and matching client ID. Use generic OIDC for another issuer.\");\n\t\t}\n\t}\n\treturn {\n\t\t...descriptor,\n\t\tclientId,\n\t\t...issuer ? { issuer } : {},\n\t\tallowedDomains,\n\t\trequiredGroups\n\t};\n}\nfunction parsePlatformAccessProtection(value) {\n\tif (value === null) return null;\n\tconst entry = record(value, \"Access protection\");\n\tconst teamDomain = parsePlatformIdentityUrl(entry.teamDomain, \"Access team domain\", true);\n\tconst host = new URL(teamDomain).hostname;\n\tif (!/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.cloudflareaccess\\.com$/.test(host) || new URL(teamDomain).port) throw new Error(\"Access team domain must be an HTTPS cloudflareaccess.com team origin.\");\n\tif (!Array.isArray(entry.applications) || entry.applications.length === 0 || entry.applications.length > 20) throw new Error(\"Access protection requires between 1 and 20 protected origins.\");\n\tconst applications = entry.applications.map((value) => {\n\t\tconst application = record(value, \"Access application\");\n\t\treturn {\n\t\t\torigin: parsePlatformIdentityUrl(application.origin, \"Protected origin\", true),\n\t\t\taudience: string(application.audience, \"Access application audience\")\n\t\t};\n\t});\n\tif (new Set(applications.map((app) => app.origin)).size !== applications.length) throw new Error(\"Each protected origin must have exactly one Access application.\");\n\treturn {\n\t\tteamDomain,\n\t\tapplications\n\t};\n}\nfunction parsePlatformAdmissionPolicy(value) {\n\tconst entry = record(value, \"Admission policy\");\n\tif (entry.mode === \"restricted\" || entry.mode === \"public\") return { mode: entry.mode };\n\tif (entry.mode !== \"company\" || typeof entry.access !== \"boolean\") throw new Error(\"Admission policy must select restricted, company, or public signup.\");\n\tconst connections = strings(entry.connections, \"Company connections\").map(parsePlatformLoginId);\n\tif (!entry.access && connections.length === 0) throw new Error(\"Company admission requires a trusted connection or Access protection.\");\n\treturn {\n\t\tmode: \"company\",\n\t\tconnections,\n\t\taccess: entry.access\n\t};\n}\n/** Run inside the settings mutation transaction, using the resulting enabled connections. */\nfunction validatePlatformAdmissionPolicy(policy, enabledConnections, protection) {\n\tif (policy.mode !== \"company\") return;\n\tif (policy.access && !protection) throw new Error(\"Company admission through Access requires enabled protection.\");\n\tfor (const id of policy.connections) {\n\t\tconst connection = enabledConnections.find((entry) => entry.id === id);\n\t\tif (!connection) throw new Error(`Company admission requires enabled connection ${id}.`);\n\t\tif (connection.kind === \"github\" || connection.kind === \"google\" && connection.allowedDomains.length === 0) throw new Error(\"Unrestricted social login does not establish company membership.\");\n\t}\n}\n//#endregion\n//#region src/manifest.ts\nconst PLATFORM_DEPLOYMENT_SCHEMA_VERSION = 1;\nconst CORE_CAPABILITIES = {\n\tai: true,\n\tcustomDomains: false,\n\temail: false,\n\tgithubActions: false,\n\tgithubOAuth: true,\n\tgoogleOAuth: false,\n\tmanagedBuilds: false,\n\tsandbox: false\n};\nconst CONTROL_PLANE_DEFAULTS = {\n\tapiHostname: null,\n\tdashboardHostname: null,\n\tproxyHostname: null\n};\nfunction assertRecord$1(value, label) {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(`${label} must be an object.`);\n}\nfunction requiredString$1(value, label) {\n\tif (typeof value !== \"string\" || value.trim() === \"\") throw new Error(`${label} must be a non-empty string.`);\n\treturn value;\n}\nfunction normalizeInstallationSlug(value) {\n\tconst slug = value.trim().toLowerCase().replaceAll(/[^a-z0-9-]+/g, \"-\").replaceAll(/^-+|-+$/g, \"\").replaceAll(/-{2,}/g, \"-\");\n\tif (!slug) throw new Error(\"The installation name must contain a letter or number.\");\n\tif (slug.length > 40) throw new Error(\"The installation name must be 40 characters or fewer after normalization.\");\n\treturn slug;\n}\nfunction normalizeApplicationDomain(value) {\n\tlet domain = value.trim().toLowerCase();\n\tif (domain.endsWith(\".\")) domain = domain.slice(0, -1);\n\tif (domain.length > 253 || !domain.includes(\".\") || domain.split(\".\").some((label) => !/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(label))) throw new Error(`Invalid domain: ${JSON.stringify(value)}.`);\n\treturn domain;\n}\nfunction createPlatformResourceNames(installationSlug) {\n\tconst prefix = `void-${normalizeInstallationSlug(installationSlug)}`;\n\tconst datasetPrefix = prefix.replaceAll(\"-\", \"_\");\n\treturn {\n\t\taiGateway: prefix,\n\t\tapiWorker: `${prefix}-api`,\n\t\tassetsBucket: `${prefix}-assets`,\n\t\tcronQueue: `${prefix}-cron-fires`,\n\t\tdashboardWorker: `${prefix}-dashboard`,\n\t\tdispatchNamespace: `${prefix}-users`,\n\t\tdispatchWorker: `${prefix}-dispatch`,\n\t\temailGatewayWorker: `${prefix}-email-gateway`,\n\t\thyperdrive: `${prefix}-database`,\n\t\tisrCacheKv: `${prefix}-isr-cache`,\n\t\tlegacyAssetsKv: `${prefix}-legacy-assets`,\n\t\tlogsDataset: `${datasetPrefix}_logs`,\n\t\tproxyWorker: `${prefix}-proxy`,\n\t\trequestsDataset: `${datasetPrefix}_requests`,\n\t\troutingKv: `${prefix}-routing`,\n\t\ttailWorker: `${prefix}-tail`,\n\t\tusageQueue: `${prefix}-usage-events`\n\t};\n}\nfunction createApplicationRoutes(application) {\n\tif (!application.zoneName && application.workersDev) {\n\t\tif (application.dedicatedZone) throw new Error(\"workers.dev cannot use a dedicated-zone catch-all.\");\n\t\treturn [];\n\t}\n\tconst baseDomain = normalizeApplicationDomain(application.baseDomain);\n\tconst zoneName = normalizeApplicationDomain(application.zoneName);\n\tif (baseDomain !== zoneName && !baseDomain.endsWith(`.${zoneName}`)) throw new Error(`Application domain ${baseDomain} is not inside zone ${zoneName}.`);\n\tconst routes = [{\n\t\tpattern: `*.${baseDomain}/*`,\n\t\tzoneName\n\t}, {\n\t\tpattern: `*.${baseDomain}`,\n\t\tzoneName\n\t}];\n\tif (application.dedicatedZone) {\n\t\tif (baseDomain !== zoneName) throw new Error(\"A dedicated-zone catch-all requires the application domain to be the zone.\");\n\t\troutes.push({\n\t\t\tpattern: \"*/*\",\n\t\t\tzoneName\n\t\t}, {\n\t\t\tpattern: \"*\",\n\t\t\tzoneName\n\t\t});\n\t}\n\treturn routes;\n}\nfunction createPlatformDeploymentManifest(input) {\n\tif (input.emailSharedZoneId === void 0 !== (input.emailSenderDomain === void 0)) throw new Error(\"Shared email configuration requires both emailSenderDomain and emailSharedZoneId.\");\n\tconst installationSlug = normalizeInstallationSlug(input.installationSlug);\n\tconst baseDomain = normalizeApplicationDomain(input.application.baseDomain);\n\tconst workersDev = input.application.workersDev;\n\tif (workersDev && (!/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(workersDev.subdomain) || !/^[a-z0-9][a-z0-9-]{0,80}$/.test(workersDev.installationId))) throw new Error(\"Invalid workers.dev installation identity.\");\n\tconst zoneName = workersDev && input.application.zoneName === \"\" ? \"\" : normalizeApplicationDomain(input.application.zoneName);\n\tif (!zoneName && baseDomain !== `${workersDev.subdomain}.workers.dev`) throw new Error(\"workers.dev application domain must match its account subdomain.\");\n\tconst resources = {\n\t\t...createPlatformResourceNames(installationSlug),\n\t\t...input.resources\n\t};\n\tconst capabilities = {\n\t\t...CORE_CAPABILITIES,\n\t\t...input.capabilities\n\t};\n\tif (capabilities.managedBuilds && !capabilities.githubActions) throw new Error(\"Managed builds require the GitHub Actions capability.\");\n\tconst providers = input.authentication?.providers ?? [\"github\"];\n\tif (providers.some((provider) => !PLATFORM_LOGIN_KINDS.includes(provider)) || new Set(providers).size !== providers.length) throw new Error(\"Authentication providers must be unique supported login kinds.\");\n\tconst configurable = input.authentication?.configurable === true || input.authentication?.accessProtection === true || providers.some((provider) => provider === \"oidc\" || provider === \"cloudflare-access\");\n\tif (providers.length === 0) throw new Error(\"At least one authentication provider is required.\");\n\tif (providers.includes(\"github\") !== capabilities.githubOAuth) throw new Error(\"The GitHub provider and githubOAuth capability must agree.\");\n\tif (providers.includes(\"google\") !== capabilities.googleOAuth) throw new Error(\"The Google provider and googleOAuth capability must agree.\");\n\tconst manifest = {\n\t\tapplication: {\n\t\t\tbaseDomain,\n\t\t\tdedicatedZone: input.application.dedicatedZone ?? false,\n\t\t\tzoneName,\n\t\t\t...workersDev ? { workersDev: { ...workersDev } } : {},\n\t\t\t...input.application.zoneId ? { zoneId: requiredString$1(input.application.zoneId, \"application.zoneId\") } : {}\n\t\t},\n\t\tauthentication: {\n\t\t\tproviders: [...providers],\n\t\t\t...configurable ? { configurable: true } : {},\n\t\t\t...input.authentication?.accessProtection ? { accessProtection: true } : {}\n\t\t},\n\t\tcapabilities,\n\t\t...input.emailSharedZoneId !== void 0 ? { emailSharedZoneId: requiredString$1(input.emailSharedZoneId, \"emailSharedZoneId\") } : {},\n\t\t...input.emailSenderDomain !== void 0 ? { emailSenderDomain: normalizeApplicationDomain(input.emailSenderDomain) } : {},\n\t\tcontrolPlane: {\n\t\t\t...CONTROL_PLANE_DEFAULTS,\n\t\t\t...input.controlPlane\n\t\t},\n\t\tdisplayName: requiredString$1(input.displayName, \"displayName\").trim(),\n\t\tinstallationSlug,\n\t\tresources,\n\t\tschemaVersion: configurable ? 3 : workersDev ? 2 : 1\n\t};\n\tcreateApplicationRoutes(manifest.application);\n\tfor (const [key, value] of Object.entries(manifest.controlPlane)) {\n\t\tif (value !== null) normalizeApplicationDomain(value);\n\t\tif (value === \"\") throw new Error(`controlPlane.${key} must be a hostname or null.`);\n\t}\n\tfor (const [key, value] of Object.entries(manifest.resources)) requiredString$1(value, `resources.${key}`);\n\treturn manifest;\n}\nfunction parsePlatformDeploymentManifest(value) {\n\tassertRecord$1(value, \"Platform deployment manifest\");\n\tif (value.schemaVersion !== 1 && value.schemaVersion !== 2 && value.schemaVersion !== 3) throw new Error(`Unsupported platform deployment schema version: ${String(value.schemaVersion)}.`);\n\tconst application = value.application;\n\tconst authentication = value.authentication;\n\tconst rawCapabilities = value.capabilities;\n\tconst controlPlane = value.controlPlane;\n\tconst rawResources = value.resources;\n\tassertRecord$1(application, \"application\");\n\tlet workersDev;\n\tif (value.schemaVersion === 2 || value.schemaVersion === 3 && application.workersDev !== void 0) {\n\t\tassertRecord$1(application.workersDev, \"application.workersDev\");\n\t\tworkersDev = {\n\t\t\tsubdomain: requiredString$1(application.workersDev.subdomain, \"workersDev.subdomain\"),\n\t\t\tinstallationId: requiredString$1(application.workersDev.installationId, \"workersDev.installationId\")\n\t\t};\n\t} else if (application.workersDev !== void 0) throw new Error(\"workers.dev requires platform deployment schema version 2.\");\n\tassertRecord$1(rawCapabilities, \"capabilities\");\n\tassertRecord$1(controlPlane, \"controlPlane\");\n\tassertRecord$1(authentication, \"authentication\");\n\tassertRecord$1(rawResources, \"resources\");\n\tconst capabilityKeys = Object.keys(CORE_CAPABILITIES);\n\tconst capabilities = {};\n\tfor (const key of capabilityKeys) {\n\t\tconst entry = rawCapabilities[key];\n\t\tif (typeof entry !== \"boolean\") throw new Error(`capabilities.${key} must be a boolean.`);\n\t\tcapabilities[key] = entry;\n\t}\n\tconst providers = authentication.providers;\n\tif (!Array.isArray(providers) || providers.some((provider) => !PLATFORM_LOGIN_KINDS.includes(provider) || value.schemaVersion !== 3 && provider !== \"github\" && provider !== \"google\")) throw new Error(\"authentication.providers must contain only github or google.\");\n\tif (value.schemaVersion === 3 && authentication.configurable !== true || value.schemaVersion !== 3 && (authentication.configurable !== void 0 || authentication.accessProtection !== void 0) || authentication.accessProtection !== void 0 && authentication.accessProtection !== true) throw new Error(\"Configurable authentication requires deployment schema version 3.\");\n\tconst resourceDefaults = createPlatformResourceNames(requiredString$1(value.installationSlug, \"installationSlug\"));\n\tconst resources = {};\n\tfor (const key of Object.keys(resourceDefaults)) resources[key] = requiredString$1(rawResources[key] ?? (key === \"emailGatewayWorker\" ? resourceDefaults[key] : void 0), `resources.${key}`);\n\tconst readHostname = (key) => {\n\t\tconst hostname = controlPlane[key];\n\t\treturn hostname === null ? null : requiredString$1(hostname, `controlPlane.${key}`);\n\t};\n\treturn createPlatformDeploymentManifest({\n\t\tapplication: {\n\t\t\tbaseDomain: requiredString$1(application.baseDomain, \"application.baseDomain\"),\n\t\t\tdedicatedZone: application.dedicatedZone === true,\n\t\t\tzoneName: workersDev && application.zoneName === \"\" ? \"\" : requiredString$1(application.zoneName, \"application.zoneName\"),\n\t\t\t...workersDev ? { workersDev } : {},\n\t\t\t...typeof application.zoneId === \"string\" ? { zoneId: application.zoneId } : {}\n\t\t},\n\t\tauthentication: {\n\t\t\tproviders,\n\t\t\t...authentication.configurable === true ? { configurable: true } : {},\n\t\t\t...authentication.accessProtection === true ? { accessProtection: true } : {}\n\t\t},\n\t\tcapabilities,\n\t\t...value.emailSharedZoneId !== void 0 ? { emailSharedZoneId: requiredString$1(value.emailSharedZoneId, \"emailSharedZoneId\") } : {},\n\t\t...value.emailSenderDomain !== void 0 ? { emailSenderDomain: normalizeApplicationDomain(requiredString$1(value.emailSenderDomain, \"emailSenderDomain\")) } : {},\n\t\tcontrolPlane: {\n\t\t\tapiHostname: readHostname(\"apiHostname\"),\n\t\t\tdashboardHostname: readHostname(\"dashboardHostname\"),\n\t\t\tproxyHostname: readHostname(\"proxyHostname\")\n\t\t},\n\t\tdisplayName: requiredString$1(value.displayName, \"displayName\"),\n\t\tinstallationSlug: requiredString$1(value.installationSlug, \"installationSlug\"),\n\t\tresources\n\t});\n}\n//#endregion\n//#region src/installation.ts\nconst PLATFORM_INSTALLATION_SCHEMA_VERSION = 1;\nconst PLATFORM_DISABLED_KEY = \"__void/platform/disabled/v1\";\nconst PLATFORM_DISABLED_VALUE = \"disabled\";\nconst PLATFORM_REMOTE_INSTALLATION_MANIFEST_KEY = \"__void/platform/installation/v1\";\nconst PLATFORM_SANDBOX_DRAIN_KEY = \"__void/platform/sandbox-drain/v1\";\nconst PLATFORM_R2_OWNERSHIP_MARKER_KEY = \"__void/platform/ownership/v1\";\nconst PLATFORM_RESOURCE_OWNERSHIP_SCHEMA_VERSION = 1;\nconst PLATFORM_USAGE_PROTOCOL_VERSION = 2;\nconst STATUS_TRANSITIONS = {\n\tdraft: [\n\t\t\"planned\",\n\t\t\"failed\",\n\t\t\"uninstalling\"\n\t],\n\tplanned: [\n\t\t\"provisioning\",\n\t\t\"failed\",\n\t\t\"uninstalling\"\n\t],\n\tprovisioning: [\n\t\t\"waiting-for-dns\",\n\t\t\"waiting-for-oauth\",\n\t\t\"deploying\",\n\t\t\"disabling\",\n\t\t\"failed\",\n\t\t\"uninstalling\"\n\t],\n\t\"waiting-for-dns\": [\n\t\t\"provisioning\",\n\t\t\"disabling\",\n\t\t\"failed\",\n\t\t\"uninstalling\"\n\t],\n\t\"waiting-for-oauth\": [\n\t\t\"provisioning\",\n\t\t\"deploying\",\n\t\t\"disabling\",\n\t\t\"failed\",\n\t\t\"uninstalling\"\n\t],\n\tdeploying: [\n\t\t\"provisioning\",\n\t\t\"verifying\",\n\t\t\"disabling\",\n\t\t\"disabled\",\n\t\t\"failed\",\n\t\t\"uninstalling\"\n\t],\n\tverifying: [\n\t\t\"provisioning\",\n\t\t\"installed\",\n\t\t\"disabling\",\n\t\t\"failed\",\n\t\t\"uninstalling\"\n\t],\n\tinstalled: [\n\t\t\"provisioning\",\n\t\t\"disabling\",\n\t\t\"uninstalling\",\n\t\t\"failed\"\n\t],\n\tdisabling: [\n\t\t\"disabled\",\n\t\t\"failed\",\n\t\t\"uninstalling\"\n\t],\n\tdisabled: [\n\t\t\"provisioning\",\n\t\t\"uninstalling\",\n\t\t\"failed\"\n\t],\n\tuninstalling: [\"uninstalled\", \"failed\"],\n\tuninstalled: [],\n\tfailed: [\n\t\t\"planned\",\n\t\t\"provisioning\",\n\t\t\"deploying\",\n\t\t\"verifying\",\n\t\t\"disabling\",\n\t\t\"uninstalling\"\n\t]\n};\nfunction assertRecord(value, label) {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(`${label} must be an object.`);\n}\nfunction requiredString(value, label) {\n\tif (typeof value !== \"string\" || value.trim() === \"\") throw new Error(`${label} must be a non-empty string.`);\n\treturn value;\n}\nfunction isInstallationStatus(value) {\n\treturn typeof value === \"string\" && Object.hasOwn(STATUS_TRANSITIONS, value);\n}\nfunction isResourceKind(value) {\n\treturn value === \"ai-gateway\" || value === \"analytics-dataset\" || value === \"dispatch-namespace\" || value === \"dns-record\" || value === \"hyperdrive\" || value === \"kv-namespace\" || value === \"queue\" || value === \"r2-bucket\" || value === \"worker\" || value === \"worker-custom-domain\" || value === \"worker-route\" || value === \"zone\";\n}\nfunction isOwnership(value) {\n\treturn value === \"created\" || value === \"adopted\" || value === \"external\";\n}\nfunction isResourceState(value) {\n\treturn value === \"ready\" || value === \"retained\" || value === \"deleted\";\n}\nfunction assertTimestamp(value, label) {\n\tif (!Number.isFinite(Date.parse(value))) throw new Error(`${label} must be an ISO timestamp.`);\n\treturn value;\n}\nfunction createPlatformResourceOwnershipMarker(input) {\n\tif (!isResourceKind(input.resourceKind)) throw new Error(\"Invalid ownership marker resource kind.\");\n\treturn {\n\t\taccountId: requiredString(input.accountId, \"ownership accountId\"),\n\t\tinstallationId: requiredString(input.installationId, \"ownership installationId\"),\n\t\townershipNonce: requiredString(input.ownershipNonce, \"ownership ownershipNonce\"),\n\t\tresourceId: requiredString(input.resourceId, \"ownership resourceId\"),\n\t\tresourceKey: requiredString(input.resourceKey, \"ownership resourceKey\"),\n\t\tresourceKind: input.resourceKind,\n\t\tresourceName: requiredString(input.resourceName, \"ownership resourceName\"),\n\t\tschemaVersion: 1\n\t};\n}\nfunction parsePlatformResourceOwnershipMarker(value) {\n\tassertRecord(value, \"Platform resource ownership marker\");\n\tif (value.schemaVersion !== 1) throw new Error(`Unsupported platform resource ownership schema version: ${String(value.schemaVersion)}.`);\n\tif (!isResourceKind(value.resourceKind)) throw new Error(\"Invalid ownership marker resource kind.\");\n\treturn createPlatformResourceOwnershipMarker({\n\t\taccountId: requiredString(value.accountId, \"ownership accountId\"),\n\t\tinstallationId: requiredString(value.installationId, \"ownership installationId\"),\n\t\townershipNonce: requiredString(value.ownershipNonce, \"ownership ownershipNonce\"),\n\t\tresourceId: requiredString(value.resourceId, \"ownership resourceId\"),\n\t\tresourceKey: requiredString(value.resourceKey, \"ownership resourceKey\"),\n\t\tresourceKind: value.resourceKind,\n\t\tresourceName: requiredString(value.resourceName, \"ownership resourceName\")\n\t});\n}\nfunction createPlatformInstallationManifest(input) {\n\tconst createdAt = assertTimestamp(input.createdAt, \"createdAt\");\n\tif (!/^[a-z0-9][a-z0-9-]{7,79}$/.test(input.id)) throw new Error(\"Installation id must be a lowercase identifier between 8 and 80 characters.\");\n\tif (!/^[A-Za-z0-9_-]{32,128}$/.test(input.ownershipNonce)) throw new Error(\"Ownership nonce must contain 32 to 128 URL-safe characters.\");\n\treturn {\n\t\taccount: {\n\t\t\tid: requiredString(input.account.id, \"account.id\"),\n\t\t\tname: requiredString(input.account.name, \"account.name\")\n\t\t},\n\t\tcreatedAt,\n\t\tdatabaseSchemaDigest: null,\n\t\tdeployment: parsePlatformDeploymentManifest(JSON.parse(JSON.stringify(input.deployment))),\n\t\tdesiredState: \"enabled\",\n\t\tendpoints: {\n\t\t\tapiUrl: null,\n\t\t\tdashboardUrl: null,\n\t\t\tproxyUrl: null\n\t\t},\n\t\tid: input.id,\n\t\townershipNonce: input.ownershipNonce,\n\t\tplatformVersion: requiredString(input.platformVersion, \"platformVersion\"),\n\t\tresources: [],\n\t\truntime: null,\n\t\tsafetyProtocols: input.safetyProtocols ?? { sandboxDrain: 0 },\n\t\tschemaVersion: 1,\n\t\tstatus: \"draft\",\n\t\tsteps: [],\n\t\tupdatedAt: createdAt,\n\t\tusageProtocolVersion: input.usageProtocolVersion ?? 0\n\t};\n}\nfunction setInstallationDesiredState(manifest, desiredState, updatedAt) {\n\treturn {\n\t\t...manifest,\n\t\tdesiredState,\n\t\tupdatedAt: assertTimestamp(updatedAt, \"updatedAt\")\n\t};\n}\nfunction normalizeEndpoint(value, label) {\n\tif (value === null) return null;\n\tlet url;\n\ttry {\n\t\turl = new URL(value);\n\t} catch {\n\t\tthrow new Error(`${label} must be an absolute URL or null.`);\n\t}\n\tif (url.protocol !== \"https:\" || url.username || url.password || url.search || url.hash) throw new Error(`${label} must be a credential-free HTTPS URL.`);\n\turl.pathname = url.pathname.replace(/\\/+$/, \"\") || \"/\";\n\treturn url.href.replace(/\\/$/, \"\");\n}\nfunction setInstallationEndpoints(manifest, endpoints, updatedAt) {\n\treturn {\n\t\t...manifest,\n\t\tendpoints: {\n\t\t\tapiUrl: normalizeEndpoint(endpoints.apiUrl, \"endpoints.apiUrl\"),\n\t\t\tdashboardUrl: normalizeEndpoint(endpoints.dashboardUrl, \"endpoints.dashboardUrl\"),\n\t\t\tproxyUrl: normalizeEndpoint(endpoints.proxyUrl, \"endpoints.proxyUrl\")\n\t\t},\n\t\tupdatedAt: assertTimestamp(updatedAt, \"updatedAt\")\n\t};\n}\nfunction transitionInstallation(manifest, status, updatedAt) {\n\tif (status !== manifest.status && !STATUS_TRANSITIONS[manifest.status].includes(status)) throw new Error(`Invalid installation transition: ${manifest.status} -> ${status}.`);\n\treturn {\n\t\t...manifest,\n\t\tstatus,\n\t\tupdatedAt: assertTimestamp(updatedAt, \"updatedAt\")\n\t};\n}\nfunction recordInstallationResource(manifest, resource, updatedAt) {\n\trequiredString(resource.key, \"resource.key\");\n\trequiredString(resource.id, \"resource.id\");\n\trequiredString(resource.name, \"resource.name\");\n\trequiredString(resource.configHash, \"resource.configHash\");\n\tconst collision = manifest.resources.find((entry) => entry.key !== resource.key && entry.kind === resource.kind && entry.id === resource.id);\n\tif (collision) throw new Error(`Resource id ${resource.id} is already owned by ${collision.key}.`);\n\tconst resources = manifest.resources.filter((entry) => entry.key !== resource.key);\n\tresources.push({ ...resource });\n\tresources.sort((left, right) => left.key.localeCompare(right.key));\n\treturn {\n\t\t...manifest,\n\t\tresources,\n\t\tupdatedAt: assertTimestamp(updatedAt, \"updatedAt\")\n\t};\n}\nfunction recordInstallationStep(manifest, step, updatedAt) {\n\trequiredString(step.key, \"step.key\");\n\trequiredString(step.resultHash, \"step.resultHash\");\n\tassertTimestamp(step.completedAt, \"step.completedAt\");\n\tconst existing = manifest.steps.find((entry) => entry.key === step.key);\n\tif (existing && existing.resultHash !== step.resultHash) throw new Error(`Completed installation step ${step.key} has a different result.`);\n\tconst steps = existing ? manifest.steps : [...manifest.steps, { ...step }];\n\treturn {\n\t\t...manifest,\n\t\tsteps,\n\t\tupdatedAt: assertTimestamp(updatedAt, \"updatedAt\")\n\t};\n}\nfunction parsePlatformInstallationManifest(value) {\n\tassertRecord(value, \"Platform installation manifest\");\n\tif (value.schemaVersion !== 1) throw new Error(`Unsupported platform installation schema version: ${String(value.schemaVersion)}.`);\n\tconst account = value.account;\n\tconst endpoints = value.endpoints;\n\tassertRecord(account, \"account\");\n\tassertRecord(endpoints, \"endpoints\");\n\tif (!isInstallationStatus(value.status)) throw new Error(`Invalid installation status: ${String(value.status)}.`);\n\tif (!Array.isArray(value.resources)) throw new Error(\"resources must be an array.\");\n\tif (!Array.isArray(value.steps)) throw new Error(\"steps must be an array.\");\n\tconst manifest = createPlatformInstallationManifest({\n\t\taccount: {\n\t\t\tid: requiredString(account.id, \"account.id\"),\n\t\t\tname: requiredString(account.name, \"account.name\")\n\t\t},\n\t\tcreatedAt: requiredString(value.createdAt, \"createdAt\"),\n\t\tdeployment: parsePlatformDeploymentManifest(value.deployment),\n\t\tid: requiredString(value.id, \"id\"),\n\t\townershipNonce: requiredString(value.ownershipNonce, \"ownershipNonce\"),\n\t\tplatformVersion: requiredString(value.platformVersion, \"platformVersion\"),\n\t\tsafetyProtocols: parseSafetyProtocols(value.safetyProtocols),\n\t\tusageProtocolVersion: parseUsageProtocolVersion$1(value.usageProtocolVersion)\n\t});\n\tconst runtime = parsePlatformRuntimeProvenance(value.runtime);\n\tlet pendingDomain;\n\tif (value.pendingDomain !== void 0) {\n\t\tassertRecord(value.pendingDomain, \"pendingDomain\");\n\t\tpendingDomain = createPlatformDeploymentManifest({\n\t\t\t...manifest.deployment,\n\t\t\tapplication: value.pendingDomain\n\t\t}).application;\n\t\tif (!manifest.deployment.application.workersDev || !pendingDomain.zoneName || JSON.stringify(pendingDomain.workersDev) !== JSON.stringify(manifest.deployment.application.workersDev)) throw new Error(\"Pending domain must retain the installation workers.dev identity.\");\n\t}\n\tconst updatedAt = assertTimestamp(requiredString(value.updatedAt, \"updatedAt\"), \"updatedAt\");\n\tlet next = setInstallationEndpoints({\n\t\t...manifest,\n\t\tdesiredState: value.desiredState === \"disabled\" || value.desiredState === \"enabled\" ? value.desiredState : value.status === \"disabled\" || value.status === \"disabling\" ? \"disabled\" : \"enabled\",\n\t\tstatus: value.status,\n\t\truntime,\n\t\t...pendingDomain ? { pendingDomain } : {},\n\t\t...value.authenticationResources !== void 0 ? { authenticationResources: parseAuthenticationResources(value.authenticationResources) } : {},\n\t\tupdatedAt\n\t}, {\n\t\tapiUrl: endpoints.apiUrl === null ? null : requiredString(endpoints.apiUrl, \"endpoints.apiUrl\"),\n\t\tdashboardUrl: endpoints.dashboardUrl === null ? null : requiredString(endpoints.dashboardUrl, \"endpoints.dashboardUrl\"),\n\t\tproxyUrl: endpoints.proxyUrl === null ? null : requiredString(endpoints.proxyUrl, \"endpoints.proxyUrl\")\n\t}, updatedAt);\n\tfor (const [index, entry] of value.resources.entries()) {\n\t\tassertRecord(entry, `resources[${index}]`);\n\t\tif (!isResourceKind(entry.kind)) throw new Error(`Invalid resources[${index}].kind.`);\n\t\tif (!isOwnership(entry.ownership)) throw new Error(`Invalid resources[${index}].ownership.`);\n\t\tif (!isResourceState(entry.state)) throw new Error(`Invalid resources[${index}].state.`);\n\t\tnext = recordInstallationResource(next, {\n\t\t\tconfigHash: requiredString(entry.configHash, `resources[${index}].configHash`),\n\t\t\tid: requiredString(entry.id, `resources[${index}].id`),\n\t\t\tkey: requiredString(entry.key, `resources[${index}].key`),\n\t\t\tkind: entry.kind,\n\t\t\tname: requiredString(entry.name, `resources[${index}].name`),\n\t\t\townership: entry.ownership,\n\t\t\tstate: entry.state\n\t\t}, next.updatedAt);\n\t}\n\tfor (const [index, entry] of value.steps.entries()) {\n\t\tassertRecord(entry, `steps[${index}]`);\n\t\tnext = recordInstallationStep(next, {\n\t\t\tcompletedAt: requiredString(entry.completedAt, `steps[${index}].completedAt`),\n\t\t\tkey: requiredString(entry.key, `steps[${index}].key`),\n\t\t\tresultHash: requiredString(entry.resultHash, `steps[${index}].resultHash`)\n\t\t}, next.updatedAt);\n\t}\n\tconst recordedDatabaseSchemaDigest = value.databaseSchemaDigest === void 0 || value.databaseSchemaDigest === null ? [...next.steps].reverse().find((step) => step.key.startsWith(\"database-schema:\"))?.resultHash ?? null : requiredString(value.databaseSchemaDigest, \"databaseSchemaDigest\");\n\treturn {\n\t\t...next,\n\t\tdatabaseSchemaDigest: recordedDatabaseSchemaDigest,\n\t\tupdatedAt\n\t};\n}\nfunction parseAuthenticationResources(value) {\n\tif (!Array.isArray(value) || value.length > 100) throw new Error(\"Invalid authentication resource inventory.\");\n\tconst resources = value.map((entry) => {\n\t\tassertRecord(entry, \"Authentication resource\");\n\t\tif (entry.kind !== \"application\" && entry.kind !== \"service-token\" || entry.ownership !== \"created\" && entry.ownership !== \"adopted\") throw new Error(\"Invalid authentication resource kind or ownership.\");\n\t\treturn {\n\t\t\tkey: requiredString(entry.key, \"authentication resource key\"),\n\t\t\tkind: entry.kind,\n\t\t\taccountId: requiredString(entry.accountId, \"authentication resource account\"),\n\t\t\tid: requiredString(entry.id, \"authentication resource ID\"),\n\t\t\tname: requiredString(entry.name, \"authentication resource name\"),\n\t\t\townership: entry.ownership\n\t\t};\n\t});\n\tif (new Set(resources.map((resource) => `${resource.accountId}:${resource.kind}:${resource.id}`)).size !== resources.length) throw new Error(\"Duplicate authentication resource identity.\");\n\treturn resources;\n}\nfunction parseUsageProtocolVersion$1(value) {\n\tif (value === void 0 || value === 0) return 0;\n\tif (value === 1) return 1;\n\tif (value === 2) return 2;\n\tthrow new Error(\"usageProtocolVersion must be 0, 1, or 2.\");\n}\nfunction parseSafetyProtocols(value) {\n\tif (value === void 0) return { sandboxDrain: 0 };\n\tassertRecord(value, \"safetyProtocols\");\n\tif (value.sandboxDrain !== 0 && value.sandboxDrain !== 1 && value.sandboxDrain !== 2 && value.sandboxDrain !== 3) throw new Error(\"safetyProtocols.sandboxDrain must be 0, 1, 2, or 3.\");\n\treturn { sandboxDrain: value.sandboxDrain };\n}\nfunction parsePlatformRuntimeProvenance(value) {\n\tif (value === void 0 || value === null) return null;\n\tassertRecord(value, \"runtime\");\n\tif (value.source !== \"custom\" && value.source !== \"package\") throw new Error(\"runtime.source must be custom or package.\");\n\tconst manifestSha256 = requiredString(value.manifestSha256, \"runtime.manifestSha256\");\n\tif (!/^[0-9a-f]{64}$/.test(manifestSha256)) throw new Error(\"runtime.manifestSha256 must be a SHA-256 digest.\");\n\tconst sourceRevision = value.sourceRevision === null || value.sourceRevision === void 0 ? null : requiredString(value.sourceRevision, \"runtime.sourceRevision\");\n\tif (sourceRevision !== null && (sourceRevision.length > 200 || !/^[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(sourceRevision))) throw new Error(\"runtime.sourceRevision is invalid.\");\n\treturn {\n\t\tmanifestSha256,\n\t\tsource: value.source,\n\t\tsourceRevision\n\t};\n}\n//#endregion\n//#region src/application.ts\n/** Minimal public-origin adapter; request policy remains in the service-bound dispatcher. */\nconst PLATFORM_PROJECT_INGRESS_SOURCE = `export default {\n fetch(request, env) {\n if (new URL(request.url).hostname !== env.VOID_APP_HOSTNAME) {\n return new Response('Not Found', {status: 404});\n }\n return env.PLATFORM_DISPATCH.fetch(request);\n }\n};`;\nfunction readPlatformApplication(env) {\n\tconst baseDomain = env.SITE_DOMAIN ?? env.BASE_HOSTNAME ?? \"void.app\";\n\tif (!env.PLATFORM_APPLICATION) return {\n\t\tbaseDomain,\n\t\tzoneName: baseDomain,\n\t\tdedicatedZone: false\n\t};\n\treturn createPlatformDeploymentManifest({\n\t\tinstallationSlug: \"runtime\",\n\t\tdisplayName: \"Runtime\",\n\t\tapplication: JSON.parse(env.PLATFORM_APPLICATION)\n\t}).application;\n}\nfunction platformWorkersDevAliasKey(hostname) {\n\treturn `workers-dev:${hostname}`;\n}\nconst PLATFORM_APPLICATION_KEY = \"__void/platform/application/v1\";\nasync function resolvePlatformApplicationEnvironment(env) {\n\tif (!env.PLATFORM_APPLICATION) return env;\n\tconst raw = await env.ROUTING.get(PLATFORM_APPLICATION_KEY);\n\tif (!raw) return env;\n\tconst previous = readPlatformApplication(env);\n\tconst next = readPlatformApplication({ PLATFORM_APPLICATION: raw });\n\tif (!previous.workersDev || !next.workersDev || previous.workersDev.installationId !== next.workersDev.installationId || previous.workersDev.subdomain !== next.workersDev.subdomain) throw new Error(\"Application routing belongs to another platform installation.\");\n\treturn {\n\t\t...env,\n\t\tPLATFORM_APPLICATION: raw,\n\t\tSITE_DOMAIN: next.baseDomain,\n\t\tBASE_HOSTNAME: next.baseDomain,\n\t\t...next.zoneId ? { CF_ZONE_ID: next.zoneId } : {}\n\t};\n}\nfunction platformProjectIngressName(project, workersDev) {\n\tif (!/^proj_[a-z0-9]{1,32}$/.test(project.id) || !/^[a-z0-9][a-z0-9-]*$/.test(project.slug)) throw new Error(\"Invalid platform project identity.\");\n\tconst prefix = `void-${workersDev.installationId.slice(-12)}-`;\n\tconst suffix = `-${project.id.slice(5)}`;\n\treturn `${prefix}${project.slug.slice(0, 63 - prefix.length - suffix.length).replace(/-+$/, \"\")}${suffix}`;\n}\nfunction platformProjectWorkersDevHostname(project, workersDev) {\n\treturn `${platformProjectIngressName(project, workersDev)}.${workersDev.subdomain}.workers.dev`;\n}\nfunction platformProjectHostname(project, application) {\n\tif (!application.zoneName && application.workersDev) return platformProjectWorkersDevHostname(project, application.workersDev);\n\treturn `${project.slug}.${application.baseDomain}`;\n}\nfunction platformProjectHostnames(project, application) {\n\treturn [.../* @__PURE__ */ new Set([platformProjectHostname(project, application), ...application.workersDev ? [platformProjectWorkersDevHostname(project, application.workersDev)] : []])];\n}\n//#endregion\n//#region src/discovery.ts\nconst PLATFORM_DISCOVERY_SCHEMA_VERSION = 1;\nfunction normalizeOrigin(value, name) {\n\tlet url;\n\ttry {\n\t\turl = new URL(value);\n\t} catch {\n\t\tthrow new Error(`${name} must be an absolute URL.`);\n\t}\n\tif (!(url.protocol === \"http:\" && (url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\" || url.hostname === \"::1\")) && url.protocol !== \"https:\" || url.username || url.password) throw new Error(`${name} must be a credential-free HTTPS URL.`);\n\tif (url.pathname !== \"\" && url.pathname !== \"/\" || url.search || url.hash) throw new Error(`${name} must be an origin without a path, query, or fragment.`);\n\treturn url.origin;\n}\nfunction createPlatformDiscoveryDocument(input) {\n\tif (!input.displayName.trim()) throw new Error(\"displayName must not be empty.\");\n\tif (!input.platformVersion.trim()) throw new Error(\"platformVersion must not be empty.\");\n\tif (input.applicationRouting) {\n\t\tconst application = readPlatformApplication({ PLATFORM_APPLICATION: JSON.stringify(input.applicationRouting) });\n\t\tif (!application.workersDev || application.baseDomain !== input.applicationDomain || application.workersDev.installationId !== input.installationId) throw new Error(\"Application routing must match the discovery domain and installation identity.\");\n\t}\n\tif (input.usageProtocolVersion !== void 0 && input.usageProtocolVersion !== 0 && input.usageProtocolVersion !== 1 && input.usageProtocolVersion !== 2) throw new Error(\"usageProtocolVersion must be 0, 1, or 2.\");\n\tconst authentication = input.authentication ? parseAuthentication(input.authentication) : void 0;\n\tif (!authentication && input.authenticationProviders.some((provider) => provider !== \"github\" && provider !== \"google\")) throw new Error(\"Named login methods require authentication discovery descriptors.\");\n\tif (new Set(input.authenticationProviders).size !== input.authenticationProviders.length) throw new Error(\"Authentication provider IDs must be unique.\");\n\tif (input.authenticationProviders.length === 0 && !authentication?.setupPending) throw new Error(\"At least one authentication provider is required.\");\n\tif (authentication && (authentication.methods.length !== input.authenticationProviders.length || authentication.methods.some((method, index) => method.id !== input.authenticationProviders[index]))) throw new Error(\"Authentication method descriptors must match the advertised provider IDs.\");\n\tif (input.authenticationProviders.includes(\"github\") !== input.capabilities.githubOAuth || input.authenticationProviders.includes(\"google\") !== input.capabilities.googleOAuth) throw new Error(\"Authentication providers and capabilities must agree.\");\n\treturn {\n\t\t...input,\n\t\tapiUrl: normalizeOrigin(input.apiUrl, \"apiUrl\"),\n\t\tapplicationDomain: normalizeApplicationDomain(input.applicationDomain),\n\t\tauthenticationProviders: [...input.authenticationProviders],\n\t\t...authentication ? { authentication } : {},\n\t\tdisplayName: input.displayName.trim(),\n\t\tinstallationId: input.installationId?.trim() || null,\n\t\tplatformVersion: input.platformVersion.trim(),\n\t\tproxyUrl: normalizeOrigin(input.proxyUrl, \"proxyUrl\"),\n\t\tschemaVersion: authentication ? 3 : input.applicationRouting?.workersDev ? 2 : 1,\n\t\tusageProtocolVersion: input.usageProtocolVersion ?? 0\n\t};\n}\nfunction parsePlatformDiscoveryDocument(value) {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"Platform discovery document must be an object.\");\n\tconst document = value;\n\tif (document.schemaVersion !== 1 && document.schemaVersion !== 2 && document.schemaVersion !== 3) throw new Error(`Unsupported platform discovery schema version: ${String(document.schemaVersion)}.`);\n\tconst capabilities = document.capabilities;\n\tif (document.schemaVersion === 1 && document.applicationRouting !== void 0) throw new Error(\"Application routing requires discovery schema version 2.\");\n\tif (document.schemaVersion === 2 && document.applicationRouting === void 0) throw new Error(\"Discovery schema version 2 requires application routing.\");\n\tif (!capabilities || typeof capabilities !== \"object\" || Array.isArray(capabilities)) throw new Error(\"capabilities must be an object.\");\n\tconst capabilityNames = [\n\t\t\"ai\",\n\t\t\"customDomains\",\n\t\t\"email\",\n\t\t\"githubActions\",\n\t\t\"githubOAuth\",\n\t\t\"googleOAuth\",\n\t\t\"managedBuilds\",\n\t\t\"sandbox\"\n\t];\n\tconst parsedCapabilities = {};\n\tfor (const name of capabilityNames) {\n\t\tconst enabled = capabilities[name];\n\t\tif (typeof enabled !== \"boolean\") throw new Error(`capabilities.${name} must be a boolean.`);\n\t\tparsedCapabilities[name] = enabled;\n\t}\n\tconst providers = document.authenticationProviders;\n\tif (!Array.isArray(providers) || providers.some((provider) => typeof provider !== \"string\" || document.schemaVersion !== 3 && provider !== \"github\" && provider !== \"google\")) throw new Error(\"authenticationProviders must contain only github or google.\");\n\tif (document.schemaVersion !== 3 && document.authentication !== void 0) throw new Error(\"Configurable authentication requires discovery schema version 3.\");\n\tconst authentication = document.schemaVersion === 3 ? parseAuthentication(document.authentication) : void 0;\n\tif (authentication) providers.forEach(parsePlatformLoginId);\n\tconst string = (name) => {\n\t\tconst entry = document[name];\n\t\tif (typeof entry !== \"string\" || !entry.trim()) throw new Error(`${name} must be a non-empty string.`);\n\t\treturn entry;\n\t};\n\tconst apiUrl = string(\"apiUrl\");\n\tconst proxyUrl = typeof document.proxyUrl === \"string\" && document.proxyUrl.trim() ? document.proxyUrl : apiUrl === \"https://api.void.cloud\" ? \"https://proxy.void.cloud\" : apiUrl === \"https://api.staging.void.cloud\" ? \"https://proxy.staging.void.cloud\" : string(\"proxyUrl\");\n\treturn createPlatformDiscoveryDocument({\n\t\tapiUrl,\n\t\tapplicationDomain: string(\"applicationDomain\"),\n\t\t...document.applicationRouting !== void 0 ? { applicationRouting: readPlatformApplication({ PLATFORM_APPLICATION: JSON.stringify(document.applicationRouting ?? null) }) } : {},\n\t\tauthenticationProviders: providers,\n\t\t...authentication ? { authentication } : {},\n\t\tcapabilities: parsedCapabilities,\n\t\tdisplayName: string(\"displayName\"),\n\t\tinstallationId: document.installationId === null ? null : string(\"installationId\"),\n\t\tplatformVersion: string(\"platformVersion\"),\n\t\tproxyUrl,\n\t\tusageProtocolVersion: parseUsageProtocolVersion(document.usageProtocolVersion)\n\t});\n}\nfunction parseAuthentication(value) {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"Authentication discovery must be an object.\");\n\tconst authentication = value;\n\tif (!Array.isArray(authentication.methods) || authentication.methods.length > 32 || typeof authentication.protectedByAccess !== \"boolean\" || authentication.setupPending !== void 0 && typeof authentication.setupPending !== \"boolean\") throw new Error(\"Authentication discovery requires login methods and a protection flag.\");\n\tconst methods = authentication.methods.map(parsePlatformLoginDescriptor);\n\tif (new Set(methods.map((method) => method.id)).size !== methods.length) throw new Error(\"Authentication connection IDs must be unique.\");\n\treturn {\n\t\tmethods,\n\t\tprotectedByAccess: authentication.protectedByAccess,\n\t\t...authentication.setupPending === true ? { setupPending: true } : {}\n\t};\n}\nfunction parseUsageProtocolVersion(value) {\n\tif (value === void 0 || value === 0) return 0;\n\tif (value === 1) return 1;\n\tif (value === 2) return 2;\n\tthrow new Error(\"usageProtocolVersion must be 0, 1, or 2.\");\n}\n//#endregion\n//#region src/worker-config.ts\nfunction createPlatformWorkerConfigs(input) {\n\tconst { accountId, apiUrl, deployment, healthProbeToken, installationId, ownershipNonce, platformVersion, proxyUrl, emailGatewayUrl, resources, runtimeEntrypoints } = input;\n\tconst publicEndpoints = input.publicEndpoints ?? true;\n\tconst trafficState = input.trafficState ?? \"enabled\";\n\tconst names = deployment.resources;\n\tconst sharedEmailIngress = deployment.emailSharedZoneId ? {\n\t\tEMAIL_SHARED_ACCOUNT_ID: accountId,\n\t\tEMAIL_SHARED_ZONE_ID: deployment.emailSharedZoneId,\n\t\tEMAIL_SHARED_INGRESS_NAME: names.emailGatewayWorker\n\t} : {};\n\tconst senderDomain = deployment.emailSenderDomain ? { EMAIL_SENDER_DOMAIN: deployment.emailSenderDomain } : {};\n\tconst ownershipVars = (resourceKey, resourceName) => ({ PLATFORM_OWNERSHIP_MARKER: JSON.stringify(createPlatformResourceOwnershipMarker({\n\t\taccountId,\n\t\tinstallationId,\n\t\townershipNonce,\n\t\tresourceId: resourceName,\n\t\tresourceKey,\n\t\tresourceKind: \"worker\",\n\t\tresourceName\n\t})) });\n\tconst common = {\n\t\taccount_id: accountId,\n\t\tcompatibility_date: \"2026-02-24\",\n\t\tobservability: { enabled: true },\n\t\tpreview_urls: publicEndpoints && !deployment.authentication.accessProtection,\n\t\tworkers_dev: publicEndpoints\n\t};\n\tconst kv = [\n\t\t{\n\t\t\tbinding: \"ROUTING\",\n\t\t\tid: resources.routingKv\n\t\t},\n\t\t{\n\t\t\tbinding: \"ISR_CACHE\",\n\t\t\tid: resources.isrCacheKv\n\t\t},\n\t\t{\n\t\t\tbinding: \"STATIC_ASSETS\",\n\t\t\tid: resources.legacyAssetsKv\n\t\t}\n\t];\n\tconst dispatchNamespace = [{\n\t\tbinding: \"DISPATCH\",\n\t\tnamespace: names.dispatchNamespace\n\t}];\n\tconst r2 = [{\n\t\tbinding: \"STATIC_ASSETS_R2\",\n\t\tbucket_name: names.assetsBucket\n\t}];\n\tconst fetchWorkersDev = Boolean(deployment.application.workersDev) || [\n\t\tapiUrl,\n\t\tproxyUrl,\n\t\t...deployment.capabilities.email ? [emailGatewayUrl] : []\n\t].some((url) => new URL(url).hostname.endsWith(\".workers.dev\"));\n\tconst api = {\n\t\t...common,\n\t\tversion_metadata: { binding: \"VERSION_METADATA\" },\n\t\tworkers_dev: publicEndpoints && (!deployment.authentication.accessProtection || new URL(apiUrl).hostname.endsWith(\".workers.dev\")),\n\t\tname: names.apiWorker,\n\t\tmain: runtimeEntrypoints.api,\n\t\tno_bundle: true,\n\t\t...input.runtimeApiAssetsDirectory ? { assets: { directory: input.runtimeApiAssetsDirectory } } : {},\n\t\tcompatibility_flags: [\"nodejs_compat\", ...fetchWorkersDev ? [\"global_fetch_strictly_public\"] : []],\n\t\tplacement: { mode: \"smart\" },\n\t\thyperdrive: [{\n\t\t\tbinding: \"HYPERDRIVE\",\n\t\t\tid: resources.hyperdrive\n\t\t}],\n\t\tkv_namespaces: kv,\n\t\t...deployment.capabilities.email ? { send_email: [{ name: \"EMAIL\" }] } : {},\n\t\tr2_buckets: r2,\n\t\tdispatch_namespaces: dispatchNamespace,\n\t\tdurable_objects: { bindings: [\n\t\t\t{\n\t\t\t\tname: \"USAGE_COUNTER\",\n\t\t\t\tclass_name: \"UsageCounter\"\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"CRON_SCHEDULER\",\n\t\t\t\tclass_name: \"CronScheduler\"\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"ERROR_ALERT_MONITOR\",\n\t\t\t\tclass_name: \"ErrorAlertMonitor\"\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"SANDBOX_CONCURRENCY_COUNTER\",\n\t\t\t\tclass_name: \"SandboxConcurrencyCounter\"\n\t\t\t}\n\t\t] },\n\t\tmigrations: [\n\t\t\t{\n\t\t\t\ttag: \"v1\",\n\t\t\t\tnew_sqlite_classes: [\"UsageCounter\"]\n\t\t\t},\n\t\t\t{\n\t\t\t\ttag: \"v2\",\n\t\t\t\tnew_sqlite_classes: [\"CronScheduler\"]\n\t\t\t},\n\t\t\t{\n\t\t\t\ttag: \"v3\",\n\t\t\t\tnew_sqlite_classes: [\"ErrorAlertMonitor\"]\n\t\t\t},\n\t\t\t{\n\t\t\t\ttag: \"v4\",\n\t\t\t\tnew_sqlite_classes: [\"SandboxConcurrencyCounter\"]\n\t\t\t}\n\t\t],\n\t\tqueues: {\n\t\t\tproducers: [{\n\t\t\t\tbinding: \"CRON_FIRES_QUEUE\",\n\t\t\t\tqueue: names.cronQueue\n\t\t\t}, {\n\t\t\t\tbinding: \"USAGE_EVENTS_QUEUE\",\n\t\t\t\tqueue: names.usageQueue\n\t\t\t}],\n\t\t\tconsumers: [{\n\t\t\t\tqueue: names.usageQueue,\n\t\t\t\tmax_batch_size: 100,\n\t\t\t\tmax_batch_timeout: 5\n\t\t\t}, {\n\t\t\t\tqueue: names.cronQueue,\n\t\t\t\tmax_batch_size: 50,\n\t\t\t\tmax_batch_timeout: 1,\n\t\t\t\tmax_retries: 3\n\t\t\t}]\n\t\t},\n\t\ttriggers: { crons: [\"0 * * * *\"] },\n\t\tvars: {\n\t\t\tAUTH_REDIRECT_URI: `${apiUrl}/auth/callback`,\n\t\t\tAI_GATEWAY_ID: names.aiGateway,\n\t\t\tCRON_FIRES_QUEUE_NAME: names.cronQueue,\n\t\t\tDISPATCH_NAMESPACE: names.dispatchNamespace,\n\t\t\tDISPATCH_WORKER_NAME: names.dispatchWorker,\n\t\t\tLOGS_DATASET: names.logsDataset,\n\t\t\tPLATFORM_CAPABILITIES: JSON.stringify(deployment.capabilities),\n\t\t\t...input.authenticationDatabaseUncached ? { PLATFORM_AUTH_DATABASE_UNCACHED: \"true\" } : {},\n\t\t\tPLATFORM_DISPLAY_NAME: deployment.displayName,\n\t\t\tPLATFORM_ENV: \"production\",\n\t\t\tPLATFORM_HEALTH_PROBE_TOKEN: healthProbeToken,\n\t\t\tPLATFORM_INSTALLATION_ID: installationId,\n\t\t\tPLATFORM_TRAFFIC_STATE: trafficState,\n\t\t\t...ownershipVars(\"api-worker\", names.apiWorker),\n\t\t\tPLATFORM_VERSION: platformVersion,\n\t\t\tPROXY_URL: proxyUrl,\n\t\t\tEMAIL_GATEWAY_ORIGIN: emailGatewayUrl,\n\t\t\t...sharedEmailIngress,\n\t\t\t...senderDomain,\n\t\t\tR2_STATIC_ASSETS_BUCKET: names.assetsBucket,\n\t\t\tREQUESTS_DATASET: names.requestsDataset,\n\t\t\tSITE_DOMAIN: deployment.application.baseDomain,\n\t\t\t...deployment.application.workersDev ? { PLATFORM_APPLICATION: JSON.stringify(deployment.application) } : {},\n\t\t\tTAIL_SERVICE_NAME: names.tailWorker,\n\t\t\tVOID_PROXY_SERVICE: names.proxyWorker,\n\t\t\tSANDBOX_CONTROL_SERVICE: names.apiWorker\n\t\t}\n\t};\n\tif (publicEndpoints && deployment.controlPlane.apiHostname) api.routes = [{\n\t\tpattern: deployment.controlPlane.apiHostname,\n\t\tcustom_domain: true\n\t}];\n\tconst proxy = {\n\t\t...common,\n\t\tworkers_dev: publicEndpoints && (!deployment.authentication.accessProtection || new URL(proxyUrl).hostname.endsWith(\".workers.dev\")),\n\t\tname: names.proxyWorker,\n\t\tmain: runtimeEntrypoints.proxy,\n\t\tno_bundle: true,\n\t\tcompatibility_flags: [\"nodejs_compat\"],\n\t\tai: { binding: \"AI\" },\n\t\tkv_namespaces: [{\n\t\t\tbinding: \"ROUTING\",\n\t\t\tid: resources.routingKv\n\t\t}],\n\t\tservices: [{\n\t\t\tbinding: \"API\",\n\t\t\tservice: names.apiWorker\n\t\t}],\n\t\tdispatch_namespaces: dispatchNamespace,\n\t\t...deployment.capabilities.email ? { send_email: [{ name: \"SEND_EMAIL\" }] } : {},\n\t\tvars: {\n\t\t\tAI_GATEWAY_ID: names.aiGateway,\n\t\t\tPLATFORM_CAPABILITIES: JSON.stringify(deployment.capabilities),\n\t\t\tPLATFORM_HEALTH_PROBE_TOKEN: healthProbeToken,\n\t\t\tPLATFORM_INSTALLATION_ID: installationId,\n\t\t\tPLATFORM_TRAFFIC_STATE: trafficState,\n\t\t\t...senderDomain,\n\t\t\t...ownershipVars(\"proxy-worker\", names.proxyWorker)\n\t\t}\n\t};\n\tif (publicEndpoints && deployment.controlPlane.proxyHostname) proxy.routes = [{\n\t\tpattern: deployment.controlPlane.proxyHostname,\n\t\tcustom_domain: true\n\t}];\n\treturn {\n\t\tapi,\n\t\tproxy,\n\t\temailGateway: {\n\t\t\t...common,\n\t\t\tworkers_dev: publicEndpoints,\n\t\t\tpreview_urls: false,\n\t\t\tname: names.emailGatewayWorker,\n\t\t\tmain: runtimeEntrypoints.emailGateway,\n\t\t\tno_bundle: true,\n\t\t\tcompatibility_flags: [\"nodejs_compat\"],\n\t\t\tkv_namespaces: [{\n\t\t\t\tbinding: \"ROUTING\",\n\t\t\t\tid: resources.routingKv\n\t\t\t}],\n\t\t\tservices: [{\n\t\t\t\tbinding: \"API\",\n\t\t\t\tservice: names.apiWorker\n\t\t\t}],\n\t\t\tdispatch_namespaces: dispatchNamespace,\n\t\t\t...deployment.capabilities.email ? { send_email: [{ name: \"SEND_EMAIL\" }] } : {},\n\t\t\tvars: {\n\t\t\t\tPLATFORM_CAPABILITIES: JSON.stringify(deployment.capabilities),\n\t\t\t\tPLATFORM_INSTALLATION_ID: installationId,\n\t\t\t\tPLATFORM_VERSION: platformVersion,\n\t\t\t\tPLATFORM_TRAFFIC_STATE: trafficState,\n\t\t\t\t...sharedEmailIngress,\n\t\t\t\t...senderDomain,\n\t\t\t\t...ownershipVars(\"email-gateway-worker\", names.emailGatewayWorker)\n\t\t\t}\n\t\t},\n\t\ttail: {\n\t\t\t...common,\n\t\t\tname: names.tailWorker,\n\t\t\tmain: runtimeEntrypoints.tail,\n\t\t\tno_bundle: true,\n\t\t\tanalytics_engine_datasets: [{\n\t\t\t\tbinding: \"ANALYTICS\",\n\t\t\t\tdataset: names.logsDataset\n\t\t\t}],\n\t\t\tvars: {\n\t\t\t\tPLATFORM_DISPATCH_WORKER_NAME: names.dispatchWorker,\n\t\t\t\t...ownershipVars(\"tail-worker\", names.tailWorker)\n\t\t\t}\n\t\t},\n\t\tdispatch: {\n\t\t\t...common,\n\t\t\tname: names.dispatchWorker,\n\t\t\tmain: runtimeEntrypoints.dispatch,\n\t\t\tno_bundle: true,\n\t\t\t...publicEndpoints ? { routes: createApplicationRoutes(deployment.application).map((route) => ({\n\t\t\t\tpattern: route.pattern,\n\t\t\t\tzone_name: route.zoneName\n\t\t\t})) } : {},\n\t\t\tdispatch_namespaces: dispatchNamespace,\n\t\t\tkv_namespaces: kv,\n\t\t\tr2_buckets: r2,\n\t\t\tanalytics_engine_datasets: [{\n\t\t\t\tbinding: \"ANALYTICS\",\n\t\t\t\tdataset: names.requestsDataset\n\t\t\t}, {\n\t\t\t\tbinding: \"LOGS\",\n\t\t\t\tdataset: names.logsDataset\n\t\t\t}],\n\t\t\tqueues: { producers: [{\n\t\t\t\tbinding: \"USAGE_QUEUE\",\n\t\t\t\tqueue: names.usageQueue\n\t\t\t}] },\n\t\t\ttail_consumers: [{ service: names.tailWorker }],\n\t\t\tvars: {\n\t\t\t\tBASE_HOSTNAME: deployment.application.baseDomain,\n\t\t\t\t...deployment.application.workersDev ? { PLATFORM_APPLICATION: JSON.stringify(deployment.application) } : {},\n\t\t\t\tPLATFORM_HEALTH_PROBE_TOKEN: healthProbeToken,\n\t\t\t\tPLATFORM_INSTALLATION_ID: installationId,\n\t\t\t\tPLATFORM_TRAFFIC_STATE: trafficState,\n\t\t\t\t...ownershipVars(\"dispatch-worker\", names.dispatchWorker)\n\t\t\t}\n\t\t}\n\t};\n}\n//#endregion\nexport { DEFAULT_PLATFORM_SESSION_SECONDS, GOOGLE_OIDC_ISSUER, PLATFORM_APPLICATION_KEY, PLATFORM_AUTH_SETUP_PROOF_PREFIX, PLATFORM_DEPLOYMENT_SCHEMA_VERSION, PLATFORM_DISABLED_KEY, PLATFORM_DISABLED_VALUE, PLATFORM_DISCOVERY_SCHEMA_VERSION, PLATFORM_INSTALLATION_SCHEMA_VERSION, PLATFORM_LOGIN_KINDS, PLATFORM_PROJECT_INGRESS_SOURCE, PLATFORM_R2_OWNERSHIP_MARKER_KEY, PLATFORM_REMOTE_INSTALLATION_MANIFEST_KEY, PLATFORM_RESOURCE_OWNERSHIP_SCHEMA_VERSION, PLATFORM_SANDBOX_DRAIN_KEY, PLATFORM_USAGE_PROTOCOL_VERSION, createApplicationRoutes, createPlatformDeploymentManifest, createPlatformDiscoveryDocument, createPlatformInstallationManifest, createPlatformResourceNames, createPlatformResourceOwnershipMarker, createPlatformWorkerConfigs, isPlatformSignupAllowed, normalizeApplicationDomain, normalizeInstallationSlug, parsePlatformAccessProtection, parsePlatformAdmissionPolicy, parsePlatformAuthenticationSetup, parsePlatformDeploymentManifest, parsePlatformDiscoveryDocument, parsePlatformIdentityUrl, parsePlatformInstallationManifest, parsePlatformLoginConfiguration, parsePlatformLoginDescriptor, parsePlatformLoginId, parsePlatformResourceOwnershipMarker, parsePlatformSignupAllowlistEntry, platformAuthenticationRecoveryMessage, platformProjectHostname, platformProjectHostnames, platformProjectIngressName, platformProjectWorkersDevHostname, platformProtectionProofMessage, platformWorkersDevAliasKey, readPlatformApplication, recordInstallationResource, recordInstallationStep, resolvePlatformApplicationEnvironment, setInstallationDesiredState, setInstallationEndpoints, transitionInstallation, validatePlatformAdmissionPolicy };\n", "const DEFAULT_FONT_STACK =\n 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif';\n\nfunction escapeHtml(value: string): string {\n return value\n .replaceAll('&', '&')\n .replaceAll('<', '<')\n .replaceAll('>', '>')\n .replaceAll('\"', '"');\n}\n\nfunction renderDefaultErrorPage(status: number, title: string): string {\n const heading = `${status}: ${title}`;\n const prefix = `${status}: `;\n\n return `<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <title>${escapeHtml(heading)}</title>\n <style>\n :root {\n color-scheme: light;\n font-family: ${DEFAULT_FONT_STACK};\n background: #f5f5f5;\n color: #171717;\n }\n\n * {\n box-sizing: border-box;\n }\n\n body {\n margin: 0;\n min-block-size: 100dvh;\n display: grid;\n place-items: center;\n padding: 24px;\n background:\n radial-gradient(circle at top, rgba(255, 255, 255, 0.96), rgba(245, 245, 245, 0.96) 52%),\n linear-gradient(180deg, #fafafa 0%, #f1f1f1 100%);\n font: 500 16px/1.5 ${DEFAULT_FONT_STACK};\n }\n\n main {\n inline-size: min(100%, 560px);\n padding: 32px 36px;\n border: 1px solid #d4d4d8;\n border-radius: 32px;\n corner-shape: squircle;\n background: rgba(255, 255, 255, 0.88);\n text-align: center;\n backdrop-filter: blur(12px);\n }\n\n h1 {\n margin: 0;\n font: 400 clamp(1.5rem, 1.2rem + 1vw, 2rem) / 1.1 ${DEFAULT_FONT_STACK};\n letter-spacing: -0.03em;\n }\n\n strong {\n font-weight: 600;\n }\n </style>\n </head>\n <body>\n <main>\n <h1><strong>${escapeHtml(prefix)}</strong>${escapeHtml(title)}</h1>\n </main>\n </body>\n</html>`;\n}\n\nexport function shouldServeHtmlErrorPage(request: Request): boolean {\n if (request.method !== 'GET' && request.method !== 'HEAD') {\n return false;\n }\n\n const url = new URL(request.url);\n if (url.pathname === '/api' || url.pathname.startsWith('/api/')) {\n return false;\n }\n if (/\\/[^/]+\\.[^/]+$/.test(url.pathname)) {\n return false;\n }\n\n const destination = request.headers.get('sec-fetch-dest');\n if (destination && destination !== 'document' && destination !== 'empty') {\n return false;\n }\n\n const accept = request.headers.get('accept');\n return !accept || accept.includes('text/html') || accept.includes('*/*');\n}\n\nexport function createErrorResponse(\n request: Request,\n status: number,\n title: string,\n headers?: HeadersInit,\n): Response {\n if (!shouldServeHtmlErrorPage(request)) {\n return new Response(title, { status, headers });\n }\n\n const responseHeaders = new Headers(headers);\n responseHeaders.set('content-type', 'text/html; charset=utf-8');\n return new Response(request.method === 'HEAD' ? null : renderDefaultErrorPage(status, title), {\n status,\n headers: responseHeaders,\n });\n}\n", "/**\n * Shared path-pattern compiler used by header rules and routing rules.\n *\n * Syntax:\n * `:name` \u2014 single path segment, captured as `name`\n * `:name*` \u2014 zero or more path segments, captured as `name`\n * `*` \u2014 zero or more path segments, captured as `splat` (legacy)\n *\n * When a legacy pattern contains multiple anonymous `*`, the first captures\n * as `splat` and later wildcards are non-capturing. Boolean matching remains\n * backward compatible for existing header/revalidate patterns.\n */\n\nconst MAX_CACHE = 256;\n\nexport type CompiledPattern = Readonly<{\n regex: RegExp;\n paramNames: ReadonlyArray<string>;\n}>;\n\nconst compileCache = new Map<string, CompiledPattern>();\n\nconst REGEX_SPECIAL = /[.+?^${}()|[\\]\\\\]/;\nconst PARAM_CHAR = /[A-Za-z0-9_]/;\n\nexport function compilePattern(source: string): CompiledPattern {\n const cached = compileCache.get(source);\n if (cached) {\n // LRU touch: re-inserting moves the entry to the most-recently-used end\n // of Map iteration order, so eviction below removes the true LRU.\n compileCache.delete(source);\n compileCache.set(source, cached);\n return cached;\n }\n\n const paramNames: Array<string> = [];\n let legacySplatCaptured = false;\n let pattern = '';\n let index = 0;\n while (index < source.length) {\n const character = source[index]!;\n if (character === ':') {\n let nameEnd = index + 1;\n while (nameEnd < source.length && PARAM_CHAR.test(source[nameEnd]!)) {\n nameEnd++;\n }\n const name = source.slice(index + 1, nameEnd);\n if (!name) {\n pattern += '\\\\:';\n index++;\n continue;\n }\n if (source[nameEnd] === '*') {\n paramNames.push(name);\n pattern += `(?<${name}>.*)`;\n index = nameEnd + 1;\n } else {\n paramNames.push(name);\n pattern += `(?<${name}>[^/]+)`;\n index = nameEnd;\n }\n } else if (character === '*') {\n if (legacySplatCaptured) {\n pattern += `.*`;\n } else {\n paramNames.push('splat');\n pattern += `(?<splat>.*)`;\n legacySplatCaptured = true;\n }\n index++;\n } else {\n if (REGEX_SPECIAL.test(character)) {\n pattern += '\\\\';\n }\n pattern += character;\n index++;\n }\n }\n\n const compiled: CompiledPattern = { regex: new RegExp(`^${pattern}$`), paramNames };\n if (compileCache.size >= MAX_CACHE) {\n const first = compileCache.keys().next();\n if (!first.done) {\n compileCache.delete(first.value);\n }\n }\n compileCache.set(source, compiled);\n return compiled;\n}\n\n/**\n * Match a pattern against a pathname. Returns captured params, or null.\n *\n * Returns null (rather than throwing) when the pattern itself is malformed \u2014\n * e.g. multiple `*` producing duplicate `splat` capture names. Framework and\n * API ingest both reject those, but a hand-crafted manifest could still reach\n * the edge, and a single bad rule shouldn't 500 unrelated traffic.\n */\nexport function matchPatternCaptures(\n pattern: string,\n pathname: string,\n): Record<string, string> | null {\n let compiled: CompiledPattern;\n try {\n compiled = compilePattern(pattern);\n } catch {\n return null;\n }\n const match = compiled.regex.exec(pathname);\n if (!match) {\n return null;\n }\n return match.groups ?? {};\n}\n\n/**\n * Match a pattern against a pathname (boolean form). Header-rule callers only\n * need a yes/no \u2014 they don't care about captures. Malformed patterns yield\n * `false` rather than throwing (see `matchPatternCaptures`).\n */\nexport function matchPattern(pattern: string, pathname: string): boolean {\n try {\n return compilePattern(pattern).regex.test(pathname);\n } catch {\n return false;\n }\n}\n\nconst literalRegexCache = new Map<string, RegExp>();\n\n/**\n * Match a pattern against a pathname using LITERAL semantics \u2014 no named\n * captures. Only `*` is special (matches any characters including `/`); every\n * other character (including `:`) is treated as a literal.\n *\n * This preserves the pre-`feat/rewrites` semantics of header rules,\n * `routing.revalidate` keys, and `routing.revalidateQueryAllowlist` keys \u2014\n * those callers never had `:name` capture syntax and existing tenant configs\n * may include literal `:` (e.g. `/api/v1:health`, `:batchGet`-style URLs).\n *\n * The capture-aware `matchPattern` above continues to be used by routing\n * rules (`redirects`/`rewrites`/`fallbacks`) where `:name` capture syntax was\n * intentionally introduced (see design-doc 0064).\n */\nexport function matchLiteralPattern(pattern: string, pathname: string): boolean {\n let regex = literalRegexCache.get(pattern);\n if (regex) {\n // LRU touch \u2014 same scheme as the legacy header matcher.\n literalRegexCache.delete(pattern);\n literalRegexCache.set(pattern, regex);\n } else {\n try {\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&').replaceAll('*', '.*');\n regex = new RegExp(`^${escaped}$`);\n } catch {\n return false;\n }\n if (literalRegexCache.size >= MAX_CACHE) {\n const first = literalRegexCache.keys().next();\n if (!first.done) {\n literalRegexCache.delete(first.value);\n }\n }\n literalRegexCache.set(pattern, regex);\n }\n try {\n return regex.test(pathname);\n } catch {\n return false;\n }\n}\n\nconst segmentRegexCache = new Map<string, RegExp>();\n\n/**\n * Match a REVALIDATE ROUTE pattern against a pathname using SEGMENT-ANCHORED\n * semantics. Like `matchLiteralPattern` except a WHOLE-SEGMENT `:name` (a `:`\n * right after `/` or at the start of the pattern, whose name is any non-empty\n * run of non-`/` characters \u2014 NOT just JS-identifier chars, so `:post-id`,\n * `:post.id`, etc. all anchor \u2014 running up to the next `/` or end of string)\n * matches exactly ONE non-empty path segment (`[^/]+`). A whole-segment NAMED\n * CATCH-ALL `:name{.+}` (a named catch-all page `[...path]` \u2192 `/docs/:path{.+}`)\n * matches ONE-OR-MORE characters that MAY cross `/` (`.+`, so `/docs/a` and\n * `/docs/a/b` both match, but bare `/docs` / `/docs/` do NOT). Only the exact\n * `{.+}` constraint widens \u2014 a REGEX-constrained param like `:path{[0-9]+}`\n * keeps its single-segment `[^/]+` meaning. `*` still expands to a catch-all\n * that crosses `/`. A mid-segment `:` (e.g. `/api/v1:health`,\n * `/api/documents:batchGet`) stays a LITERAL \u2014 only whole-segment `:name` /\n * `:name{.+}` anchors.\n *\n * This is for `routing.revalidate` keys ONLY. Those keys are machine-generated\n * from page routes on the deploy write side (`[slug]` \u2192 `/blog/:slug`,\n * `[...path]` \u2192 `/docs/:path{.+}`), so the `:name` here is a real route param\n * and MUST bind the same way the framework's own client route matcher\n * (`patternToRegex` in `pages/manifest.ts`) binds it \u2014 matching the write-side\n * matcher in `packages/api/src/routes/deploy.ts`.\n *\n * It is intentionally NOT used for user-authored header rules\n * (`applyHeaderRules`) or `revalidateQueryAllowlist` keys\n * (`buildVariantOriginalUrl`), where `:name` must stay a literal \u2014 those keep\n * using `matchLiteralPattern`. Sharing the segment behaviour there would make a\n * user rule like `/:batchGet` over-match every single-segment path.\n *\n * NOTE: this matcher has its OWN regex cache \u2014 the same pattern string compiles\n * to a DIFFERENT regex than `matchLiteralPattern` produces, so the caches must\n * not be shared or they would cross-contaminate.\n */\nexport function matchSegmentPattern(pattern: string, pathname: string): boolean {\n let regex = segmentRegexCache.get(pattern);\n if (regex) {\n // LRU touch \u2014 same scheme as the literal matcher.\n segmentRegexCache.delete(pattern);\n segmentRegexCache.set(pattern, regex);\n } else {\n try {\n // Two private-use sentinels stand in for route params so the regex-special\n // escape step below can't touch the classes we swap in last:\n // \\uE000 - a whole-segment `:name` -> one path segment (`[^/]+`)\n // \\uE001 - a named catch-all `:name{.+}` -> >=1 char, crosses `/` (`.+`)\n // The named-catch-all rule runs FIRST so `:name{.+}` is consumed as a unit\n // before the plain `:name` rule can grab `:name` and strand the `{.+}`. The\n // `{.+}` name class is `[^/{}]+` (excludes braces) so a REGEX-constrained\n // param like `:path{[0-9]+}` does NOT match and stays a single segment.\n const escaped = pattern\n .replace(/(^|\\/):[^/{}]+\\{\\.\\+\\}(?=\\/|$)/g, '$1\\uE001') // named catch-all :name{.+} -> catch-all sentinel\n .replace(/(^|\\/):[^/]+(?=\\/|$)/g, '$1\\uE000') // whole-segment :name -> segment sentinel\n .replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&') // escape regex specials\n .replaceAll('*', '.*') // legacy `*` crosses '/'\n .replaceAll('\\uE000', '[^/]+') // segment sentinel -> one segment\n .replaceAll('\\uE001', '.+'); // catch-all sentinel -> >=1 char, crosses '/'\n regex = new RegExp(`^${escaped}$`);\n } catch {\n return false;\n }\n if (segmentRegexCache.size >= MAX_CACHE) {\n const first = segmentRegexCache.keys().next();\n if (!first.done) {\n segmentRegexCache.delete(first.value);\n }\n }\n segmentRegexCache.set(pattern, regex);\n }\n try {\n return regex.test(pathname);\n } catch {\n return false;\n }\n}\n\n/**\n * Substitute `:name` and `:name*` tokens in a destination string with the\n * matching named captures from `params`. `:splat` works for legacy `*` patterns\n * because `compilePattern` captures anonymous `*` as `splat`.\n */\nexport function substituteParams(destination: string, params: Record<string, string>): string {\n return destination.replace(/:([A-Za-z0-9_]+)\\*?/g, (whole, name: string) => {\n return params[name] ?? whole;\n });\n}\n", "import type { HeaderRule } from '@void/deploy-core';\nimport { matchLiteralPattern } from './pattern.ts';\n\nexport type { HeaderRule } from '@void/deploy-core';\n\nexport type HeaderRulePolicy = Readonly<{\n /**\n * Protect unrelated tenants that share one registrable domain. Direct\n * deployments own their hostname and may safely use cookie header rules.\n */\n cookieIsolation?: 'shared-domain' | 'origin';\n}>;\n\n/**\n * Headers that user header rules may not set at all, because they are always a\n * cookie operation. On the shared *.void.app domain (not on the PSL) void.app\n * is the registrable domain, so a `Set-Cookie` with `Domain=.void.app` is\n * readable by every tenant's subdomain. Dropped wholesale.\n *\n * `Clear-Site-Data` is the other cookie trust-boundary header, but it is NOT a\n * blanket block \u2014 see {@link sanitizeClearSiteData}: only its cookie-clearing\n * directives are stripped, since its other directives are origin-scoped.\n *\n * HSTS and other per-host headers are safe \u2014 they don't cross subdomain\n * boundaries (includeSubDomains scopes to the responding host's subtree).\n *\n * TODO: Once void.app is registered on the Public Suffix List, these defenses\n * can be removed \u2014 browsers will scope cross-subdomain cookies automatically.\n */\nconst BLOCKED_HEADERS = new Set(['set-cookie']);\n\n/** A single member of a `Clear-Site-Data` list. */\nexport type ClearSiteDataMember = Readonly<{\n /** The member text, trimmed of surrounding whitespace; kept for re-serialization. */\n raw: string;\n /**\n * The quoted-string content (original case) when the member is a well-formed\n * quoted-string, else `null`. A browser ignores members that are not\n * well-formed quoted-strings.\n */\n directive: string | null;\n}>;\n\n/**\n * Parse one list member into its quoted-string content, or `null` when it is not\n * a well-formed quoted-string. Implements RFC 7230's\n * `quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE`: it must be wrapped\n * in double quotes, a backslash escapes the next character, and an unescaped\n * inner quote (or a dangling escape) is malformed.\n */\nfunction parseQuotedString(member: string): string | null {\n if (member.length < 2 || member[0] !== '\"' || member[member.length - 1] !== '\"') {\n return null;\n }\n let content = '';\n for (let i = 1; i < member.length - 1; i += 1) {\n const char = member[i];\n if (char === '\\\\') {\n // quoted-pair: take the next character literally.\n i += 1;\n if (i >= member.length - 1) {\n return null; // trailing backslash before the closing quote\n }\n content += member[i];\n } else if (char === '\"') {\n return null; // unescaped quote before the end\n } else {\n content += char;\n }\n }\n return content;\n}\n\n/**\n * Parse a `Clear-Site-Data` header value into its list members. The value is a\n * comma-separated list of quoted-strings (W3C Clear-Site-Data); a comma inside a\n * quoted-string does not split a member. Empty members are dropped.\n */\nexport function parseClearSiteData(value: string): Array<ClearSiteDataMember> {\n const members: Array<ClearSiteDataMember> = [];\n const pushMember = (slice: string): void => {\n const raw = slice.trim();\n if (raw.length > 0) {\n members.push({ raw, directive: parseQuotedString(raw) });\n }\n };\n\n let start = 0;\n let inQuotes = false;\n for (let i = 0; i < value.length; i += 1) {\n const char = value[i];\n if (inQuotes) {\n if (char === '\\\\') {\n i += 1; // skip the escaped character so an escaped quote stays in-string\n } else if (char === '\"') {\n inQuotes = false;\n }\n } else if (char === '\"') {\n inQuotes = true;\n } else if (char === ',') {\n pushMember(value.slice(start, i));\n start = i + 1;\n }\n }\n pushMember(value.slice(start));\n return members;\n}\n\n/**\n * Sanitize a `Clear-Site-Data` value so a tenant rule can't clear cookies across\n * the shared *.void.app boundary, while still allowing the safe directives.\n *\n * Only `\"cookies\"` and `\"*\"` clear cookies for the registrable domain (and thus\n * every tenant's subdomain). `\"cache\"`, `\"storage\"`, `\"executionContexts\"`, and\n * any future quoted directive are origin-scoped \u2014 each subdomain is its own\n * origin \u2014 so they are kept verbatim. Malformed members are dropped (a browser\n * ignores them, and dropping forecloses a lenient parser honoring them).\n *\n * Returns the filtered value, or `null` when nothing safe remains: a `\"*\"`\n * includes cookies and can't be expressed without them, and a value that is only\n * `\"cookies\"` collapses to empty.\n */\nexport function sanitizeClearSiteData(value: string): string | null {\n const kept: Array<string> = [];\n for (const { raw, directive } of parseClearSiteData(value)) {\n const normalized = directive?.toLowerCase();\n if (normalized === '*') {\n return null;\n }\n if (directive === null || normalized === 'cookies') {\n continue;\n }\n kept.push(raw);\n }\n return kept.length > 0 ? kept.join(', ') : null;\n}\n\n/**\n * Apply matching header rules to a response.\n * All matching rules merge; last match wins for same header name.\n * Returns the original response unchanged when no rules or no matches.\n */\nexport function applyHeaderRules(\n response: Response,\n pathname: string,\n rules?: ReadonlyArray<HeaderRule>,\n policy?: HeaderRulePolicy,\n): Response {\n if (!rules || rules.length === 0) {\n return response;\n }\n\n const matched: Array<[string, string]> = [];\n for (const rule of rules) {\n if (matchLiteralPattern(rule.pattern, pathname)) {\n matched.push(...rule.headers);\n }\n }\n\n if (matched.length === 0) {\n return response;\n }\n\n // Clone response to modify headers\n const newResponse = new Response(response.body, response);\n // Fallback for a Clear-Site-Data rule that sanitizes to nothing: last-match-wins\n // means such a rule discards an earlier rule's value, so we fall back to the\n // origin's own Clear-Site-Data rather than leaving the earlier rule's value\n // behind. It is sanitized too, so rule processing never *resurfaces* a\n // cross-tenant cookie directive \u2014 not from a rule, and not from the origin\n // response either. (The origin's own header is otherwise ungated here; gating\n // it across the board is a separate dispatch-layer concern.)\n const isolateSharedDomainCookies = policy?.cookieIsolation !== 'origin';\n const rawOriginClearSiteData = isolateSharedDomainCookies\n ? response.headers.get('clear-site-data')\n : null;\n const originClearSiteData =\n rawOriginClearSiteData === null ? null : sanitizeClearSiteData(rawOriginClearSiteData);\n for (const [name, value] of matched) {\n const lowerName = name.toLowerCase();\n if (isolateSharedDomainCookies && BLOCKED_HEADERS.has(lowerName)) {\n continue;\n }\n if (isolateSharedDomainCookies && lowerName === 'clear-site-data') {\n const safe = sanitizeClearSiteData(value);\n if (safe !== null) {\n newResponse.headers.set(name, safe);\n } else if (originClearSiteData !== null) {\n newResponse.headers.set(name, originClearSiteData);\n } else {\n newResponse.headers.delete(name);\n }\n continue;\n }\n newResponse.headers.set(name, value);\n }\n\n return newResponse;\n}\n", "import type { RedirectRule } from '@void/deploy-core';\nimport { compilePattern, substituteParams } from './pattern.ts';\n\nexport type { RedirectRule } from '@void/deploy-core';\n\nexport type RoutingRuleResult =\n | { type: 'redirect'; destination: string; status: number }\n | { type: 'rewrite'; destination: string };\n\n/**\n * Check routing rules (redirects + rewrites) against a request pathname.\n *\n * **First match wins** \u2014 matches Netlify `_redirects` and Vercel `vercel.json`\n * semantics: users put more-specific rules above more-general ones, and the\n * first rule whose source matches takes effect. (Header rules in this same\n * package use last-match-wins for compatibility with Netlify `_headers`,\n * which is the opposite of `_redirects`. The asymmetry is intentional.)\n *\n * `requestHost` is the WHATWG `url.hostname` (lowercase, port-stripped).\n * Rules with a `host` field are skipped when `rule.host !== requestHost`;\n * path-only rules apply to every host bound to the project.\n *\n * Returns a discriminated result. The caller is responsible for building the\n * actual `Response` for redirects (so it can merge the request's query string\n * into the `Location` header).\n */\nexport function applyRoutingRules(\n pathname: string,\n rules?: ReadonlyArray<RedirectRule>,\n requestHost?: string,\n): RoutingRuleResult | null {\n if (!rules?.length) {\n return null;\n }\n\n for (const rule of rules) {\n if (rule.host && rule.host !== requestHost) {\n continue;\n }\n let regex: RegExp;\n try {\n ({ regex } = compilePattern(rule.source));\n } catch (err) {\n // A malformed `source` (e.g. duplicate named params) throws inside\n // `new RegExp`. Framework validation rejects those at build, but a\n // hand-crafted manifest could still reach the edge. Skip the offending\n // rule and continue rather than 500ing the whole request.\n console.warn(\n `[dispatch] skipping routing rule with invalid source ${JSON.stringify(rule.source)}: ${err instanceof Error ? err.message : String(err)}`,\n );\n continue;\n }\n const match = regex.exec(pathname);\n if (!match) {\n continue;\n }\n\n const destination = substituteParams(rule.destination, match.groups ?? {});\n\n if (rule.status === 200) {\n return { type: 'rewrite', destination };\n }\n\n return { type: 'redirect', destination, status: rule.status };\n }\n\n return null;\n}\n\n/**\n * Merge a request's query string into a redirect destination.\n *\n * If the destination already contains a `?`, its parameters take precedence\n * over the request's. Otherwise the request's query is appended verbatim.\n *\n * A `#fragment` on the destination is stripped before the merge and\n * re-appended afterwards, so `/new#faq` + `?utm=x` becomes `/new?utm=x#faq`\n * rather than `/new#faq?utm=x` (which browsers treat as fragment text).\n */\nexport function mergeQueryIntoLocation(destination: string, requestSearch: string): string {\n if (!requestSearch || requestSearch === '?') {\n return destination;\n }\n const fragIdx = destination.indexOf('#');\n const base = fragIdx === -1 ? destination : destination.slice(0, fragIdx);\n const fragment = fragIdx === -1 ? '' : destination.slice(fragIdx);\n\n const destQueryIdx = base.indexOf('?');\n if (destQueryIdx === -1) {\n return base + requestSearch + fragment;\n }\n if (destQueryIdx === base.length - 1) {\n return base.slice(0, destQueryIdx) + fragment;\n }\n const reqParams = new URLSearchParams(requestSearch);\n const destParams = new URLSearchParams(base.slice(destQueryIdx + 1));\n for (const [key, value] of reqParams) {\n if (!destParams.has(key)) {\n destParams.append(key, value);\n }\n }\n return base.slice(0, destQueryIdx) + '?' + destParams.toString() + fragment;\n}\n", "import type { AssetConfig } from '@void/deploy-core';\n\nexport type { AssetConfig } from '@void/deploy-core';\n\nexport type ResolvedAsset = Readonly<{\n path: string;\n hash: string;\n redirect?: string;\n notFound?: boolean;\n spa?: boolean;\n}>;\n\n/**\n * Percent-decode a request pathname for a manifest lookup, honoring ONLY the\n * encodings a conformant URL is required to use. Returns the raw value\n * unchanged on a malformed sequence (e.g. a lone `%`) or on any non-canonical /\n * over-encoded spelling.\n *\n * Request pathnames arrive percent-encoded \u2014 WHATWG `URL.pathname` never\n * decodes \u2014 but manifest keys are the asset's decoded on-disk path (a file\n * named `oxc masthead.riv` is stored under `/assets/oxc masthead.riv`, not\n * `%20`). Callers try the raw key first, then this decoded form.\n *\n * The decoded form is accepted only when re-encoding it reproduces the request\n * path (up to percent-escape letter case) \u2014 i.e. the only encoded bytes were\n * characters a URL MUST encode (space, `#`, non-ASCII, \u2026). This rejects\n * over-encoded spellings of ordinary path text (`%2F`\u2192`/`, `%61`\u2192`a`, `%5F`\u2192`_`,\n * `%2e%2e`\u2192`..`), which a browser would never send and which would otherwise let\n * a request reconstruct a guarded path (`/assets%2Fx`, `/%61ssets/x`,\n * `/%5F%5Fvoid/x`) and serve the manifest entry while the raw-`url.pathname`\n * policy gates \u2014 the `/__void/*` reserved-route block, the hashed-asset prefix\n * gate, and the header/redirect rules \u2014 never fire. The URL pathname setter\n * applies exactly the WHATWG \"path percent-encode set\", making it the canonical\n * re-encoder.\n *\n * Known limitation: a file whose name contains a literal `%` (e.g. `logo%20.svg`,\n * requested as `logo%2520.svg`) is not resolved \u2014 the path encoder leaves `%`\n * as-is, so the round-trip can't reproduce the double-escaped request. Such\n * names 404'd before this change too, so this is not a regression.\n */\nexport function safeDecodePathname(pathname: string): string {\n let decoded: string;\n try {\n decoded = decodeURIComponent(pathname);\n } catch {\n return pathname;\n }\n if (decoded === pathname) {\n return pathname;\n }\n const canonical = reencodePathname(decoded);\n if (canonical === null) {\n return pathname;\n }\n // Compare up to percent-escape letter case: the URL encoder emits upper-case\n // (`%C3`), but a client may send lower-case (`%c3`), and both are valid.\n return normalizePercentCase(canonical) === normalizePercentCase(pathname) ? decoded : pathname;\n}\n\n/** Uppercase the hex digits of every `%xx` escape so encodings compare equal\n * regardless of the letter case a client used. */\nfunction normalizePercentCase(pathname: string): string {\n return pathname.replace(/%[0-9a-fA-F]{2}/g, (escape) => escape.toUpperCase());\n}\n\n/**\n * Serialize a decoded path back to a safe URL pathname via the WHATWG \"path\n * percent-encode set\" (the `URL.pathname` setter). Returns null if the value\n * can't be encoded. Used to canonicalize the decoded lookup key and to make a\n * redirect Location URL-safe.\n */\nfunction reencodePathname(pathname: string): string | null {\n try {\n const encoder = new URL('https://void.invalid/');\n encoder.pathname = pathname;\n return encoder.pathname;\n } catch {\n return null;\n }\n}\n\n/**\n * Match a pathname against the manifest via exact match + html_handling rules\n * (no not-found fallback). Returns null when nothing matches.\n */\nfunction matchManifestEntry(\n pathname: string,\n manifest: Record<string, string>,\n htmlHandling: NonNullable<AssetConfig['html_handling']>,\n): ResolvedAsset | null {\n // Exact match always wins\n if (manifest[pathname]) {\n return { path: pathname, hash: manifest[pathname] };\n }\n\n switch (htmlHandling) {\n case 'auto-trailing-slash': {\n // Try appending .html first (preferred over /index.html)\n const withHtml = pathname + '.html';\n if (manifest[withHtml]) {\n return { path: withHtml, hash: manifest[withHtml] };\n }\n // Try /index.html\n const withIndex = (pathname.endsWith('/') ? pathname : pathname + '/') + 'index.html';\n if (manifest[withIndex]) {\n return { path: withIndex, hash: manifest[withIndex] };\n }\n break;\n }\n case 'force-trailing-slash': {\n // If path doesn't end with /, redirect to trailing slash version\n if (!pathname.endsWith('/') && pathname !== '/') {\n const withIndex = pathname + '/index.html';\n if (manifest[withIndex]) {\n return {\n path: withIndex,\n hash: manifest[withIndex],\n redirect: pathname + '/',\n };\n }\n }\n // Serve /path/ from /path/index.html\n const indexPath = pathname + 'index.html';\n if (manifest[indexPath]) {\n return { path: indexPath, hash: manifest[indexPath] };\n }\n break;\n }\n case 'drop-trailing-slash': {\n // Root path: serve /index.html directly\n if (pathname === '/') {\n if (manifest['/index.html']) {\n return { path: '/index.html', hash: manifest['/index.html'] };\n }\n break;\n }\n // If path ends with /, redirect to non-trailing-slash version\n if (pathname.endsWith('/')) {\n const withoutSlash = pathname.slice(0, -1);\n const withHtml = withoutSlash + '.html';\n if (manifest[withHtml]) {\n return {\n path: withHtml,\n hash: manifest[withHtml],\n redirect: withoutSlash,\n };\n }\n }\n // Serve /path from /path.html\n const withHtml = pathname + '.html';\n if (manifest[withHtml]) {\n return { path: withHtml, hash: manifest[withHtml] };\n }\n break;\n }\n case 'none':\n break;\n }\n\n return null;\n}\n\n/**\n * Resolve a request pathname to a manifest entry using AssetConfig rules.\n * Replicates Cloudflare Workers Assets path resolution behavior.\n */\nexport function resolveStaticPath(\n pathname: string,\n manifest: Record<string, string>,\n config: AssetConfig,\n): ResolvedAsset | null {\n const htmlHandling = config.html_handling ?? 'auto-trailing-slash';\n\n // Try the raw (percent-encoded) path first \u2014 the fast path, and it lets a\n // filename that literally contains a `%` win. On a miss, retry with the\n // decoded path so a file named e.g. `a b.txt` resolves for an `a%20b.txt`\n // request (manifest keys are decoded on-disk paths).\n let matched = matchManifestEntry(pathname, manifest, htmlHandling);\n if (!matched) {\n const decoded = safeDecodePathname(pathname);\n if (decoded !== pathname) {\n matched = matchManifestEntry(decoded, manifest, htmlHandling);\n if (matched?.redirect !== undefined) {\n // The Location was derived from the decoded path; serialize it back to\n // a safe URL pathname (`/docs/a#b/` \u2192 `/docs/a%23b/`) so the client\n // doesn't read `#`/space/etc. as URL structure.\n const safeRedirect = reencodePathname(matched.redirect);\n if (safeRedirect !== null) {\n matched = { ...matched, redirect: safeRedirect };\n }\n }\n }\n }\n if (matched) {\n return matched;\n }\n\n // Not found handling\n switch (config.not_found_handling ?? 'none') {\n case 'single-page-application':\n if (manifest['/index.html']) {\n return {\n path: '/index.html',\n hash: manifest['/index.html'],\n spa: true,\n };\n }\n break;\n case '404-page':\n if (manifest['/404.html']) {\n return {\n path: '/404.html',\n hash: manifest['/404.html'],\n notFound: true,\n };\n }\n break;\n }\n\n return null;\n}\n\nconst MIME_TYPES: Record<string, string> = {\n html: 'text/html; charset=utf-8',\n htm: 'text/html; charset=utf-8',\n css: 'text/css; charset=utf-8',\n js: 'text/javascript; charset=utf-8',\n mjs: 'text/javascript; charset=utf-8',\n json: 'application/json; charset=utf-8',\n xml: 'application/xml; charset=utf-8',\n svg: 'image/svg+xml; charset=utf-8',\n txt: 'text/plain; charset=utf-8',\n csv: 'text/csv; charset=utf-8',\n md: 'text/markdown; charset=utf-8',\n markdown: 'text/markdown; charset=utf-8',\n yaml: 'text/yaml; charset=utf-8',\n yml: 'text/yaml; charset=utf-8',\n toml: 'application/toml',\n png: 'image/png',\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n gif: 'image/gif',\n ico: 'image/x-icon',\n webp: 'image/webp',\n avif: 'image/avif',\n woff: 'font/woff',\n woff2: 'font/woff2',\n ttf: 'font/ttf',\n otf: 'font/otf',\n eot: 'application/vnd.ms-fontobject',\n pdf: 'application/pdf',\n wasm: 'application/wasm',\n webmanifest: 'application/manifest+json; charset=utf-8',\n map: 'application/json; charset=utf-8',\n mp4: 'video/mp4',\n webm: 'video/webm',\n mp3: 'audio/mpeg',\n ogg: 'audio/ogg',\n};\n\n/**\n * Get the Content-Type header value for a given file path based on its extension.\n */\nexport function getContentType(path: string): string {\n const ext = path.split('.').pop()?.toLowerCase() ?? '';\n return MIME_TYPES[ext] ?? 'application/octet-stream';\n}\n\n/**\n * Resolve the Content-Type to serve for a stored asset, reconciling the value\n * persisted at upload time (R2 `httpMetadata.contentType` / KV `ct` metadata)\n * with a fresh path-based lookup. Returns `undefined` when no Content-Type\n * header should be emitted.\n *\n * `application/null` is a sentinel (matching Wrangler) meaning \"omit the\n * Content-Type header entirely\".\n *\n * `application/octet-stream` is the uploader's no-information default: older\n * CLI versions stamped it on any extension their MIME table did not recognize\n * (e.g. `.md`). Because assets are content-addressed and never re-uploaded,\n * those stale octet-stream values can't be corrected at the source, so we\n * treat a stored octet-stream as \"unknown\" and re-derive from the path here.\n * Any other stored value is authoritative and honored as-is.\n */\nexport function resolveAssetContentType(\n stored: string | null | undefined,\n path: string,\n): string | undefined {\n if (stored === 'application/null') {\n return undefined;\n }\n if (!stored || stored === 'application/octet-stream') {\n return getContentType(path);\n }\n return stored;\n}\n", "/**\n * Shared ISR key/URL helpers used by both the API (purge) and the dispatch\n * worker (read/write). These functions MUST produce byte-identical output:\n * the API purges KV keys and edge URLs that dispatch writes and reads.\n *\n * Dispatch derives the deployment id for its keys via\n * `routing.version ?? 'legacy'`, which allows any non-nullish value \u2014\n * including the empty string \u2014 to pass through unchanged. The helpers below\n * preserve that shape so the API can compute the exact same key for purge.\n */\n\nconst ISR_CACHE_KEY_VERSION = 'v3';\n\n/**\n * Previous key version. `v3` keys are ALWAYS host-scoped\n * (`<proj>/isr/v3/<D>/<host>/<path>`); `v2` keys are ALWAYS hostless\n * (`<proj>/isr/v2/<D>/<path>`) \u2014 the `<host>` segment did not exist yet.\n *\n * The bump to `v3` was forced by a real aliasing hazard: under a single\n * version, a host-scoped key `<D>/<host>/<path>` and a legacy hostless key\n * `<D>/<host>/<path>` are byte-identical whenever the legacy path's leading\n * segment happens to look like a hostname. Dotted leading path segments are\n * legal (`[domain]` \u2192 `:domain`, `[...slug]` \u2192 `(.+)`), so a hostless key for\n * the page `/example.com/about` collides exactly with the host-scoped key for\n * `(host=example.com, /about)`. The stored metadata is only `{s,c,t}` (no\n * path/host), so a reader cannot tell them apart and could serve one page's\n * body for the other. Encoding the shape in the version removes the ambiguity:\n * the version alone determines whether a `<host>` segment is present, so no\n * runtime heuristic (e.g. \"is the first segment an attached hostname?\") is\n * needed to classify a key. Package-internal, like `ISR_CACHE_KEY_VERSION`.\n */\nconst ISR_LEGACY_CACHE_KEY_VERSION = 'v2';\n\n/**\n * KV metadata stored alongside every ISR cache entry. This is the single\n * canonical shape shared by the dispatch worker (which writes it on a live\n * miss and reads it back on a hit \u2014 see `dispatch/src/isr.ts`) AND the API\n * prerender-warm path (`api/src/routes/deploy.ts`), which pre-populates the\n * same KV keys during deploy. Both writers MUST use these exact field names:\n * the reader requires `c` (createdAt) and `t` (ttl) and returns null without\n * them, so a writer that drifts (e.g. writes `context` instead of `c`) produces\n * a permanent cold miss that no typecheck would catch unless it is annotated\n * `satisfies IsrCacheMetadata`. Keep the fields terse \u2014 this is stored on every\n * KV entry.\n */\nexport type { IsrCacheMetadata } from './core.ts';\n\n/**\n * Build the normalized path segment for an ISR-cached page.\n * Root path `/` maps to `__index__` to avoid trailing-slash ambiguity.\n */\nexport function normalizeIsrPath(pathname: string): string {\n let normalized = pathname;\n if (normalized === '/') {\n normalized = '__index__';\n } else {\n // Strip leading slash\n normalized = normalized.startsWith('/') ? normalized.slice(1) : normalized;\n // Strip trailing slash\n if (normalized.endsWith('/')) {\n normalized = normalized.slice(0, -1);\n }\n }\n return normalized;\n}\n\n/**\n * Inverse of `normalizeIsrPath`: turn a normalized segment back into a\n * pathname starting with `/`.\n */\nexport function denormalizeIsrPath(normalized: string): string {\n return normalized === '__index__' ? '/' : `/${normalized}`;\n}\n\n/**\n * Canonicalize an inbound pathname to the form used inside edge cache URLs.\n * Equivalent to `denormalizeIsrPath(normalizeIsrPath(pathname))` \u2014 strips any\n * trailing slash except for root.\n */\nexport function canonicalIsrPathname(pathname: string): string {\n return denormalizeIsrPath(normalizeIsrPath(pathname));\n}\n\n/**\n * Prefix shared by every ISR key for a project at the current version \u2014\n * `<projectId>/isr/v3/`. Used internally by `isrCachePrefix`.\n */\nfunction isrCacheVersionPrefix(projectId: string): string {\n return `${projectId}/isr/${ISR_CACHE_KEY_VERSION}/`;\n}\n\n/**\n * Prefix shared by every LEGACY (hostless) ISR key for a project \u2014\n * `<projectId>/isr/v2/`. Used internally by `isrLegacyCachePrefix`.\n */\nfunction isrLegacyCacheVersionPrefix(projectId: string): string {\n return `${projectId}/isr/${ISR_LEGACY_CACHE_KEY_VERSION}/`;\n}\n\n/**\n * Prefix for listing/purging ISR keys.\n *\n * `deploymentId === ''` must still produce the versioned prefix with an\n * empty segment (`<projectId>/isr/v3//`) because dispatch uses\n * `routing.version ?? 'legacy'`, which allows empty strings and writes\n * keys at `<projectId>/isr/v3//<path>`. Only `undefined` selects the\n * legacy scan-all prefix (`<projectId>/isr/`).\n */\nexport function isrCachePrefix(projectId: string, deploymentId?: string): string {\n if (deploymentId !== undefined) {\n return `${isrCacheVersionPrefix(projectId)}${deploymentId}/`;\n }\n return `${projectId}/isr/`;\n}\n\n/**\n * Prefix for listing/purging LEGACY (pre-host-scoping) ISR keys \u2014 the `v2`\n * namespace `<projectId>/isr/v2/<deploymentId>/`. Mirrors `isrCachePrefix`'s\n * optional-`deploymentId` behavior exactly (empty string yields the versioned\n * prefix with an empty segment; only `undefined` selects the scan-all\n * `<projectId>/isr/` prefix).\n *\n * Exists SOLELY for the host-scoping rollout: the purger sweeps this namespace\n * to reap orphaned `v2` KV keys and purge their edge URLs. Current dispatch\n * neither reads nor writes `v2` keys. Transition-only \u2014 remove once `v2`\n * entries have aged out.\n */\nexport function isrLegacyCachePrefix(projectId: string, deploymentId?: string): string {\n if (deploymentId !== undefined) {\n return `${isrLegacyCacheVersionPrefix(projectId)}${deploymentId}/`;\n }\n return `${projectId}/isr/`;\n}\n\n/**\n * Separator that marks the rewrite-variant suffix on an ISR cache key or\n * the corresponding edge-cache URL parameter. `#` cannot appear in\n * `url.pathname` (fragments are stripped before the request reaches the\n * server) and does not survive `normalizeIsrPath`, so it unambiguously\n * identifies the variant suffix.\n */\nconst ISR_VARIANT_SEPARATOR = '#rw=';\n\n/**\n * Build the cache key for an ISR-cached page.\n * ISR is deployment-scoped so cached HTML cannot outlive the hashed assets\n * referenced by the deployment that produced it, and host-scoped (`<host>`\n * segment after the deployment id) so the same path served under different\n * hostnames \u2014 e.g. a project slug and a custom domain, or two custom\n * domains \u2014 never share a cache slot. `host` is the request hostname the\n * dispatch worker saw (`new URL(request.url).hostname`).\n *\n * Host-scoping is a `v3` key format: `<proj>/isr/v3/<D>/<host>/<path>`. The\n * version bump is load-bearing, not cosmetic \u2014 see `ISR_LEGACY_CACHE_KEY_VERSION`.\n * Under a single version, this key would be byte-identical to a legacy hostless\n * key for a page whose leading path segment looks like a hostname (e.g.\n * `(host=example.com, /about)` vs the hostless page `/example.com/about`, both\n * `<D>/example.com/about`). Dotted leading segments are legal, so the collision\n * is reachable. `v3` keys are ALWAYS host-scoped and `v2` keys ALWAYS hostless,\n * so the version segment alone disambiguates the two shapes.\n *\n * When `originalUrl` is provided, the request was served via a dispatch-side\n * rewrite (`redirectRules`/`fallbackRules` with status 200). The original\n * request URL is mixed into the key so a direct hit to `/en/docs` and a\n * rewrite from `/docs` to `/en/docs` do not collide \u2014 user code can branch\n * on `c.isRewritten()` / `c.originalUrl()`, and the cache must honor that.\n * A missing `originalUrl` means \"direct hit\" and produces the legacy\n * rewriteless key (backward-compatible with entries written before this\n * feature landed).\n */\nexport function isrCacheKey(\n projectId: string,\n deploymentId: string,\n host: string,\n pathname: string,\n originalUrl?: string | null,\n): string {\n const base = `${isrCachePrefix(projectId, deploymentId)}${host}/${normalizeIsrPath(pathname)}`;\n if (!originalUrl) {\n return base;\n }\n return `${base}${ISR_VARIANT_SEPARATOR}${hashOriginalUrl(originalUrl)}`;\n}\n\n/**\n * Prefix used to list/purge every variant of a given pathname under a\n * deployment \u2014 both the direct-hit key and any rewrite-variant keys.\n */\nexport function isrCacheVariantPrefix(\n projectId: string,\n deploymentId: string,\n host: string,\n pathname: string,\n): string {\n return `${isrCachePrefix(projectId, deploymentId)}${host}/${normalizeIsrPath(pathname)}${ISR_VARIANT_SEPARATOR}`;\n}\n\n/**\n * Build the exact LEGACY (pre-host-scoping) direct-hit key for a pathname under\n * a deployment: `<projectId>/isr/v2/<deploymentId>/<normalizedPath>` \u2014 the\n * hostless counterpart of `isrCacheKey` with no `<host>/` segment and no\n * rewrite-variant suffix. Used by the purger to reap the orphaned `v2`\n * direct-hit KV key for a requested path.\n *\n * Exists SOLELY for the host-scoping rollout \u2014 current dispatch neither writes\n * nor reads hostless keys. Transition-only. Do not use it on the hot path.\n */\nexport function isrLegacyCacheKey(\n projectId: string,\n deploymentId: string,\n pathname: string,\n): string {\n return `${isrLegacyCachePrefix(projectId, deploymentId)}${normalizeIsrPath(pathname)}`;\n}\n\n/**\n * Prefix used to list/purge the pre-host-scoped (\"legacy\") rewrite variants of\n * a given pathname under a deployment. Before ISR keys grew a `<host>` segment,\n * variant keys were written as\n * `<projectId>/isr/v2/<deploymentId>/<normalizedPath>#rw=<token>` \u2014 identical to\n * `isrCacheVariantPrefix` but with NO `<host>/` segment. Those entries still\n * persist during the host-scoping rollout (ISR puts set no `expirationTtl`),\n * so the purger must scan this hostless `v2` prefix in addition to the\n * host-scoped `v3` one to recover their variant tokens and purge the matching\n * edge URLs.\n *\n * Built off `isrLegacyCachePrefix` (the `v2` namespace), NOT `isrCachePrefix`\n * (now `v3`), so it targets the legacy hostless keys it is meant to sweep.\n *\n * Exists SOLELY for that rollout cleanup \u2014 current dispatch neither writes nor\n * reads hostless keys. Transition-only. Do not use it on the hot path.\n */\nexport function isrLegacyCacheVariantPrefix(\n projectId: string,\n deploymentId: string,\n pathname: string,\n): string {\n return `${isrLegacyCachePrefix(projectId, deploymentId)}${normalizeIsrPath(pathname)}${ISR_VARIANT_SEPARATOR}`;\n}\n\n/**\n * Hash an original-URL value into a fixed-length, opaque variant token.\n * Used as both the KV-key suffix and the `__void_orig` query value, so the\n * writer and purger paths see byte-identical tokens for the same URL.\n *\n * Properties:\n * - Sync (Workers `crypto.subtle.digest` is async; we don't want to push\n * async through every read/write path for this).\n * - 16 hex chars (64 bits) \u2014 bounds the KV key length regardless of input.\n * - Non-recoverable: KV is operator-readable, and the previous base64url\n * encoding let any operator with list access read the original URLs\n * (including sensitive query strings like `?token=\u2026`, `?email=\u2026`).\n * - Not cryptographic: collision resistance is ~2^32 (birthday). Fine for\n * the per-deployment, per-pathname variant set we ever store in one slot.\n *\n * Implementation: FNV-1a 64-bit over UTF-8 bytes. BigInt arithmetic for the\n * multiply (no native u64 in JS), but inputs are short (URLs, sub-1KB) and\n * this only runs once per ISR-touched request.\n */\nconst FNV_OFFSET_BASIS = 0xcbf29ce484222325n;\nconst FNV_PRIME = 0x100000001b3n;\nconst FNV_MASK = 0xffffffffffffffffn;\n\nexport function hashOriginalUrl(originalUrl: string): string {\n const bytes = new TextEncoder().encode(originalUrl);\n let h = FNV_OFFSET_BASIS;\n for (let i = 0; i < bytes.length; i++) {\n h = (h ^ BigInt(bytes[i]!)) & FNV_MASK;\n h = (h * FNV_PRIME) & FNV_MASK;\n }\n return h.toString(16).padStart(16, '0');\n}\n\n/**\n * Split a fully-qualified ISR KV key into the normalized pathname segment\n * and the optional rewrite-variant token. Returns `null` token when the\n * key has no `#rw=` suffix (direct hit).\n *\n * The token is opaque (a hash); the original URL it was derived from is not\n * recoverable. Callers that need to reproduce the matching edge-cache URL\n * pass the token through `isrEdgeCacheUrlForToken`.\n */\nexport function splitIsrCacheKey(fullKey: string): {\n normalizedPath: string;\n variantToken: string | null;\n} {\n const sepIdx = fullKey.indexOf(ISR_VARIANT_SEPARATOR);\n if (sepIdx === -1) {\n return { normalizedPath: fullKey, variantToken: null };\n }\n return {\n normalizedPath: fullKey.slice(0, sepIdx),\n variantToken: fullKey.slice(sepIdx + ISR_VARIANT_SEPARATOR.length),\n };\n}\n\n/**\n * Build the edge cache URL that dispatch uses as its `caches.default` key\n * (wrapped in a GET `Request`). The public URL stays clean; the internal\n * cache key carries the deployment id so a new deploy never reads HTML\n * produced by an older deploy. The `json` variant separates pages-protocol\n * JSON responses from HTML for the same path+deployment.\n *\n * This MUST match the URL dispatch writes. Dispatch builds the URL from\n * `new URL(request.url).hostname`; for standard-port HTTPS traffic (all CF\n * edge traffic) that yields the same origin as the one produced here.\n */\nexport function isrEdgeCacheUrl(\n hostname: string,\n pathname: string,\n deploymentId: string,\n variant: 'html' | 'json',\n originalUrl?: string | null,\n): string {\n return buildIsrEdgeCacheUrl(\n hostname,\n pathname,\n deploymentId,\n variant,\n originalUrl ? hashOriginalUrl(originalUrl) : null,\n );\n}\n\n/**\n * Like `isrEdgeCacheUrl`, but takes a pre-hashed variant token (from\n * `splitIsrCacheKey`). Used by the purger, which only knows the hashed\n * token: the original URL is not recoverable from a KV key.\n */\nexport function isrEdgeCacheUrlForToken(\n hostname: string,\n pathname: string,\n deploymentId: string,\n variant: 'html' | 'json',\n variantToken?: string | null,\n): string {\n return buildIsrEdgeCacheUrl(hostname, pathname, deploymentId, variant, variantToken ?? null);\n}\n\nfunction buildIsrEdgeCacheUrl(\n hostname: string,\n pathname: string,\n deploymentId: string,\n variant: 'html' | 'json',\n variantToken: string | null,\n): string {\n const normalizedPathname = canonicalIsrPathname(pathname);\n const url = new URL(`https://${hostname}${normalizedPathname}`);\n if (variant === 'json') {\n url.searchParams.set('__void', 'json');\n }\n url.searchParams.set('__void_isr', deploymentId);\n if (variantToken) {\n url.searchParams.set('__void_orig', variantToken);\n }\n return url.toString();\n}\n", "import { matchLiteralPattern, matchSegmentPattern } from '@void/edge';\n\n/**\n * Bump when a cached response accepted by an older writer can no longer be\n * proven safe to share. Readers reject entries from earlier policies instead\n * of replaying opaque bodies whose private headers were stripped at write time.\n */\nexport const SHARED_CACHE_POLICY_VERSION = 1 as const;\nexport const SHARED_CACHE_POLICY_HEADER = 'x-void-shared-cache-policy';\n\n/** Stamp an internal edge-cache representation with the policy that admitted it. */\nexport function markSharedCachePolicy(headers: Headers): void {\n headers.set(SHARED_CACHE_POLICY_HEADER, String(SHARED_CACHE_POLICY_VERSION));\n}\n\n/** Reject opaque edge entries admitted before the current privacy policy. */\nexport function hasCurrentSharedCachePolicy(response: Response): boolean {\n return response.headers.get(SHARED_CACHE_POLICY_HEADER) === String(SHARED_CACHE_POLICY_VERSION);\n}\n\nexport type IsrCacheMetadata = Readonly<{\n /** HTTP status code. */\n s: number;\n /** Creation time in milliseconds since the Unix epoch. */\n c: number;\n /** Freshness lifetime in seconds. */\n t: number;\n /** Shared-response privacy policy version. */\n p: typeof SHARED_CACHE_POLICY_VERSION;\n}>;\n\nexport type IsrCacheEntry = Readonly<{\n body: ReadableStream;\n status: number;\n headers: Record<string, string>;\n createdAt: number;\n ttl: number;\n}>;\n\nconst PAGE_DATA_SCRIPT_RE =\n /<script\\b[^>]*\\bid=([\"'])__VOID_PAGE_DATA__\\1[^>]*>([\\s\\S]*?)<\\/script>/i;\nconst SKIP_HEADERS = new Set(['cache-control', 'x-isr-cache', 'x-void-page-data', 'set-cookie']);\n\n/** Map of literal path pattern to the query names retained in an ISR cache variant. */\nexport type QueryAllowlist = Record<string, ReadonlyArray<string>>;\n\n/**\n * Normalize a request URL for cache-key use by retaining only query parameters\n * explicitly allowlisted for its user-facing pathname.\n */\nexport function buildVariantOriginalUrl(\n requestUrl: string,\n pathname: string,\n queryAllowlist: QueryAllowlist | undefined,\n): string {\n const url = new URL(requestUrl);\n if (!url.search) {\n return url.toString();\n }\n const allowed = resolveQueryAllowlist(queryAllowlist, pathname);\n if (allowed.size === 0) {\n url.search = '';\n return url.toString();\n }\n const keys = [...new Set(url.searchParams.keys())].filter((key) => allowed.has(key)).sort();\n const filtered = new URLSearchParams();\n for (const key of keys) {\n for (const value of url.searchParams.getAll(key)) {\n filtered.append(key, value);\n }\n }\n const filteredString = filtered.toString();\n url.search = filteredString ? `?${filteredString}` : '';\n return url.toString();\n}\n\n/** Keep only exact allowlist patterns for uncapped static-cache consumers. */\nexport function exactQueryAllowlist(\n allowlist: QueryAllowlist | undefined,\n): QueryAllowlist | undefined {\n if (!allowlist) {\n return undefined;\n }\n const exact = Object.fromEntries(\n Object.entries(allowlist).filter(([pattern]) => !pattern.includes('*')),\n );\n return Object.keys(exact).length > 0 ? exact : undefined;\n}\n\nfunction resolveQueryAllowlist(\n allowlist: QueryAllowlist | undefined,\n pathname: string,\n): Set<string> {\n if (!allowlist) {\n return new Set();\n }\n for (const [pattern, params] of Object.entries(allowlist)) {\n if (matchLiteralPattern(pattern, pathname)) {\n return new Set(params);\n }\n }\n return new Set();\n}\n\n/** Pack response headers and body into the canonical ISR binary value. */\nexport function packIsrValue(headers: Record<string, string>, body: ArrayBuffer): ArrayBuffer {\n const headerJson = new TextEncoder().encode(JSON.stringify(headers));\n const buffer = new ArrayBuffer(4 + headerJson.byteLength + body.byteLength);\n const view = new DataView(buffer);\n view.setUint32(0, headerJson.byteLength, true);\n new Uint8Array(buffer, 4, headerJson.byteLength).set(headerJson);\n new Uint8Array(buffer, 4 + headerJson.byteLength).set(new Uint8Array(body));\n return buffer;\n}\n\n/** Unpack a canonical ISR binary value, returning null for malformed bytes. */\nexport function unpackIsrValue(\n buffer: ArrayBuffer,\n): { headers: Record<string, string>; body: ArrayBuffer } | null {\n if (buffer.byteLength < 4) {\n return null;\n }\n const view = new DataView(buffer);\n const headerLength = view.getUint32(0, true);\n if (buffer.byteLength < 4 + headerLength) {\n return null;\n }\n try {\n const headerBytes = new Uint8Array(buffer, 4, headerLength);\n const parsed = JSON.parse(new TextDecoder().decode(headerBytes)) as unknown;\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return null;\n }\n const headers: Record<string, string> = {};\n for (const [name, value] of Object.entries(parsed)) {\n if (typeof value !== 'string') {\n return null;\n }\n headers[name] = value;\n }\n return { headers, body: buffer.slice(4 + headerLength) };\n } catch {\n return null;\n }\n}\n\n/** Decode and validate a KV value plus metadata into a safe cache entry. */\nexport function decodeIsrCacheEntry(\n value: ArrayBuffer | null,\n metadata: IsrCacheMetadata | null,\n): IsrCacheEntry | null {\n if (!value || !metadata) {\n return null;\n }\n const unpacked = unpackIsrValue(value);\n if (!unpacked) {\n return null;\n }\n if (!Number.isInteger(metadata.s) || metadata.s < 200 || metadata.s > 599) {\n return null;\n }\n if (\n !Number.isFinite(metadata.c) ||\n metadata.c <= 0 ||\n !Number.isFinite(metadata.t) ||\n metadata.t <= 0 ||\n metadata.p !== SHARED_CACHE_POLICY_VERSION\n ) {\n return null;\n }\n try {\n new Headers(unpacked.headers);\n } catch {\n return null;\n }\n return {\n body: new ReadableStream({\n start(controller): void {\n controller.enqueue(new Uint8Array(unpacked.body));\n controller.close();\n },\n }),\n status: metadata.s,\n headers: unpacked.headers,\n createdAt: metadata.c,\n ttl: metadata.t,\n };\n}\n\n/** Check whether an ISR cache entry has passed its freshness lifetime. */\nexport function isStale(entry: IsrCacheEntry, now: number = Date.now()): boolean {\n return now - entry.createdAt > entry.ttl * 1000;\n}\n\n/** Build an edge-cacheable response from a validated ISR cache entry. */\nexport function isrCacheResponse(\n entry: IsrCacheEntry,\n stale: boolean,\n now: number = Date.now(),\n): Response {\n const headers = new Headers(entry.headers);\n headers.set('x-isr-cache', stale ? 'STALE' : 'HIT');\n if (stale) {\n headers.set(\n 'Cache-Control',\n `public, s-maxage=${Math.min(10, entry.ttl)}, max-age=0, must-revalidate`,\n );\n } else {\n const remainingSeconds = Math.max(\n 0,\n Math.floor((entry.createdAt + entry.ttl * 1000 - now) / 1000),\n );\n headers.set(\n 'Cache-Control',\n `public, s-maxage=${remainingSeconds}, max-age=0, must-revalidate`,\n );\n }\n markSharedCachePolicy(headers);\n return new Response(entry.body, { status: entry.status, headers });\n}\n\n/** Resolve an x-revalidate override, falling back for absent or invalid values. */\nexport function resolveRevalidateTtl(response: Response, defaultTtl: number): number {\n const header = response.headers.get('x-revalidate');\n if (header === null) {\n return defaultTtl;\n }\n const value = Number.parseInt(header, 10);\n return Number.isNaN(value) || value < 0 ? defaultTtl : value;\n}\n\nfunction acceptsEventStream(request: Request): boolean {\n return (\n request.headers\n .get('Accept')\n ?.toLowerCase()\n .split(',')\n .some((part) => part.split(';', 1)[0]?.trim() === 'text/event-stream') ?? false\n );\n}\n\n/** Return whether credentials or EventSource semantics require an ISR bypass. */\nexport function shouldBypassIsr(request: Request): boolean {\n return (\n request.headers.has('Cookie') ||\n request.headers.has('Authorization') ||\n acceptsEventStream(request)\n );\n}\n\n/** Only document navigations may read a framework's shared HTML cache. */\nexport function isFrameworkDocumentRequest(request: Request): boolean {\n if (request.method !== 'GET' || request.headers.has('X-VoidPages')) {\n return false;\n }\n if (new URL(request.url).pathname.startsWith('/__void/')) {\n return false;\n }\n const acceptsHtml = request.headers\n .get('accept')\n ?.split(',')\n .some((value) => value.trim().toLowerCase().split(';', 1)[0] === 'text/html');\n if (!acceptsHtml) {\n return false;\n }\n const mode = request.headers.get('sec-fetch-mode')?.toLowerCase();\n if (mode && mode !== 'navigate') {\n return false;\n }\n const destination = request.headers.get('sec-fetch-dest')?.toLowerCase();\n if (destination && destination !== 'document') {\n return false;\n }\n if (request.headers.has('rsc') || request.headers.has('x-nextjs-data')) {\n return false;\n }\n return true;\n}\n\n/** Return whether a response explicitly forbids storage in a shared cache. */\nexport function hasSharedCacheOptOut(response: Response): boolean {\n if (response.headers.has('Set-Cookie')) {\n return true;\n }\n const cacheControl = response.headers.get('Cache-Control');\n if (!cacheControl) {\n return false;\n }\n return cacheControl.split(',').some((part) => {\n const directive = part.split('=', 1)[0]?.trim().toLowerCase();\n return directive === 'private' || directive === 'no-store' || directive === 'no-cache';\n });\n}\n\n/** Return whether a complete render may be persisted in the shared ISR cache. */\nexport function isSharedCacheableResponse(response: Response): boolean {\n return response.status === 200 && !hasSharedCacheOptOut(response);\n}\n\n/** Resolve the first matching path TTL using Void route-pattern semantics. */\nexport function resolvePathTtl(\n revalidate: number | Record<string, number> | undefined,\n pathname: string,\n): number {\n if (revalidate == null) {\n return 0;\n }\n if (typeof revalidate === 'number') {\n return revalidate;\n }\n for (const [pattern, ttl] of Object.entries(revalidate)) {\n if (matchSegmentPattern(pattern, pathname)) {\n return ttl;\n }\n }\n return 0;\n}\n\n/** One ordered page-route entry in the shared ISR TTL policy. */\nexport type IsrPageTtl = Readonly<{ pattern: string; revalidate?: number }>;\n\n/**\n * Resolve ISR TTL from the framework's ordered page table.\n *\n * The first matching page is authoritative. A baked positive TTL enables ISR,\n * a baked `0` opts out, and an absent TTL inherits from the raw per-path config.\n * Only requests that match no page fall back to the flattened revalidate config.\n */\nexport function resolvePageTtl(\n pages: ReadonlyArray<IsrPageTtl> | undefined,\n revalidate: number | Record<string, number> | undefined,\n pathRevalidate: Record<string, number> | undefined,\n pathname: string,\n): number {\n if (pages) {\n for (const page of pages) {\n if (!matchSegmentPattern(page.pattern, pathname)) {\n continue;\n }\n return page.revalidate === undefined\n ? resolvePathTtl(pathRevalidate, pathname)\n : page.revalidate > 0\n ? page.revalidate\n : 0;\n }\n }\n return resolvePathTtl(revalidate, pathname);\n}\n\n/** Extract response headers while removing ISR-managed and private headers. */\nexport function serializeHeaders(response: Response): Record<string, string> {\n const result: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n if (!SKIP_HEADERS.has(key.toLowerCase())) {\n result[key] = value;\n }\n });\n return result;\n}\n\n/** Validate page data before storing it as the JSON ISR variant. */\nexport function normalizePageDataForJsonCache(raw: string): string | null {\n try {\n const parsed = JSON.parse(raw) as { deferred?: unknown; deferredKeys?: unknown };\n return parsed.deferred === undefined && parsed.deferredKeys === undefined ? raw : null;\n } catch {\n return null;\n }\n}\n\n/** Extract validated Void Pages data embedded in an HTML response. */\nexport function extractPageDataFromHtml(html: string): string | null {\n const match = html.match(PAGE_DATA_SCRIPT_RE);\n return match ? normalizePageDataForJsonCache(match[2]!) : null;\n}\n", "import { isrCacheKey, isrCacheVariantPrefix, isrEdgeCacheUrl } from '@void/isr';\nimport {\n decodeIsrCacheEntry,\n extractPageDataFromHtml,\n isrCacheResponse,\n isStale,\n normalizePageDataForJsonCache,\n packIsrValue,\n resolvePathTtl,\n resolveRevalidateTtl,\n SHARED_CACHE_POLICY_VERSION,\n serializeHeaders,\n shouldBypassIsr,\n type IsrCacheEntry,\n type IsrCacheMetadata,\n} from '@void/isr/core';\nimport type { Env } from './env.ts';\nimport { matchSegmentPattern } from './pattern.ts';\n\n// Re-export so callers that import from `./isr` (tests, index.ts) still work.\nexport {\n extractPageDataFromHtml,\n isFrameworkDocumentRequest,\n hasCurrentSharedCachePolicy,\n hasSharedCacheOptOut,\n isrCacheResponse,\n isStale,\n normalizePageDataForJsonCache,\n packIsrValue,\n resolvePageTtl,\n resolvePathTtl,\n resolveRevalidateTtl,\n serializeHeaders,\n shouldBypassIsr,\n SHARED_CACHE_POLICY_HEADER,\n SHARED_CACHE_POLICY_VERSION,\n markSharedCachePolicy,\n unpackIsrValue,\n} from '@void/isr/core';\nexport { isrCacheKey } from '@void/isr';\nexport type { IsrCacheEntry, IsrCacheMetadata } from '@void/isr/core';\n\n/**\n * Hard cap on rewrite-variant ISR entries per (project, deployment, pathname).\n * The default `revalidateQueryAllowlist = {}` already drops every query param,\n * so most fanout vectors are closed at the variant-key level \u2014 but a path\n * with an allowlisted param (e.g. `/search` with `q`) can still be probed\n * with random `q` values. The cap is the second line of defense: once the\n * KV slot for a pathname holds this many variants, new variants stop being\n * written. The worker still renders fresh content; we simply refuse to\n * persist it, so KV growth and revalidation cost stay bounded.\n *\n * Existing variants continue to update so legitimate ISR refresh keeps\n * working; only NEW variants are rejected past the cap.\n */\nexport const MAX_ISR_VARIANTS_PER_PATH = 200;\n\n/**\n * Read an ISR cache entry from KV.\n * Returns null on cache miss, malformed metadata, or a KV read failure so the\n * caller renders the page live.\n */\nexport async function readIsrCache(\n env: Env,\n projectId: string,\n deploymentId: string,\n host: string,\n pathname: string,\n originalUrl?: string | null,\n): Promise<IsrCacheEntry | null> {\n const key = isrCacheKey(projectId, deploymentId, host, pathname, originalUrl);\n try {\n const { value, metadata } = await env.ISR_CACHE.getWithMetadata<IsrCacheMetadata>(\n key,\n 'arrayBuffer',\n );\n return decodeIsrCacheEntry(value, metadata);\n } catch {\n return null;\n }\n}\n\n/**\n * Delete an ISR cache entry from KV.\n * Used when a worker permanently opts out via x-revalidate: 0.\n */\nexport async function deleteIsrCache(\n env: Env,\n projectId: string,\n deploymentId: string,\n host: string,\n pathname: string,\n originalUrl?: string | null,\n): Promise<void> {\n const key = isrCacheKey(projectId, deploymentId, host, pathname, originalUrl);\n await env.ISR_CACHE.delete(key);\n}\n\n/**\n * Write an ISR cache entry to KV. Variant writes are gated by\n * `MAX_ISR_VARIANTS_PER_PATH` \u2014 past the cap, only updates to existing\n * variant slots go through. Direct-hit entries (no `originalUrl`) are\n * never gated.\n */\nexport async function writeIsrCache(\n env: Env,\n projectId: string,\n deploymentId: string,\n host: string,\n pathname: string,\n response: Response,\n ttl: number,\n originalUrl?: string | null,\n): Promise<void> {\n const key = isrCacheKey(projectId, deploymentId, host, pathname, originalUrl);\n // Clone synchronously so the cap-check `await` below cannot race with\n // callers (in `index.ts`) that consume `response.body` for the client\n // response after kicking us off via `ctx.waitUntil`. The clone has its\n // own independent body; the original is free to be consumed elsewhere.\n const responseClone = response.clone();\n const headers = serializeHeaders(responseClone);\n const status = responseClone.status;\n\n if (\n originalUrl &&\n !(await isVariantWriteAllowed(env, projectId, deploymentId, host, pathname, key))\n ) {\n return;\n }\n\n const body = await responseClone.arrayBuffer();\n const packed = packIsrValue(headers, body);\n\n await env.ISR_CACHE.put(key, packed, {\n metadata: {\n s: status,\n c: Date.now(),\n t: ttl,\n p: SHARED_CACHE_POLICY_VERSION,\n } satisfies IsrCacheMetadata,\n });\n}\n\n/**\n * Returns true if writing the given variant key is allowed under the\n * per-pathname cap. Always allows updates to existing variants (so ISR\n * revalidation keeps working after a path saturates).\n *\n * The KV list call is alphabetically ordered; we list up to `1000` entries\n * (the KV per-call max) which comfortably covers any realistic cap. If a\n * pathname has more variants than the listing returns, we conservatively\n * refuse new writes \u2014 that case shouldn't occur with the cap enforced.\n */\nasync function isVariantWriteAllowed(\n env: Env,\n projectId: string,\n deploymentId: string,\n host: string,\n pathname: string,\n key: string,\n): Promise<boolean> {\n const prefix = isrCacheVariantPrefix(projectId, deploymentId, host, pathname);\n const listed = await env.ISR_CACHE.list({ prefix, limit: 1000 });\n if (listed.keys.length < MAX_ISR_VARIANTS_PER_PATH) {\n return true;\n }\n // At or over cap: only allow updates to existing keys.\n return listed.keys.some((cacheKey) => cacheKey.name === key);\n}\n\n/**\n * Effective ISR TTL for a `pages` entry that ALREADY matched `pathname`,\n * decoding the 3-STATE table the framework's `collectPages` emits:\n * - a baked number is authoritative \u2014 `> 0` = ISR on, `0` = an EXPLICIT\n * opt-out (a per-page `export const revalidate = 0`, or a global-0 config);\n * - an ABSENT `revalidate` is INHERIT-eligible \u2014 resolve the RAW per-path\n * `pathRevalidate` OBJECT config against the ACTUAL path, so a per-path `0`\n * opt-out (or a wildcard / exact rule) that a dynamic page pattern straddles\n * is honored at the edge (build-time baking cannot \u2014 hence the split).\n * Keep in sync with `collectPages` (`packages/void/src/isr-config.ts`) and the api\n * prewarm mirror (`packages/api/src/routes/deploy.ts`).\n */\nfunction matchedPageTtl(\n page: { pattern: string; revalidate?: number },\n pathRevalidate: Record<string, number> | undefined,\n pathname: string,\n): number {\n if (page.revalidate === undefined) {\n return resolvePathTtl(pathRevalidate, pathname);\n }\n return page.revalidate > 0 ? page.revalidate : 0;\n}\n\n/**\n * A pattern is LITERAL when it has no param (`:name`), regex (`{...}`), or\n * wildcard (`*`) marker \u2014 so `matchSegmentPattern` matches ONLY the exact path,\n * never an arbitrary one. Used by `matchesLiteralPage` (applied to the whole\n * pattern).\n */\nexport function isLiteralPattern(pattern: string): boolean {\n return !/[:{*]/.test(pattern);\n}\n\n/**\n * True iff `target` EXACTLY matches a declared LITERAL ISR page (positive TTL).\n * A literal page pattern matches exactly one path, so a match POSITIVELY\n * identifies the fallback target as that specific author-declared ISR page.\n * A catch-all (`/:path{.+}`) or param page (`/:slug`) is NOT literal and never\n * vouches \u2014 it matches arbitrary paths, so it cannot certify an arbitrary\n * fallback target as public page content.\n */\nexport function matchesLiteralPage(\n pages: ReadonlyArray<{ pattern: string; revalidate?: number }> | undefined,\n target: string,\n pathRevalidate: Record<string, number> | undefined,\n): boolean {\n if (!pages) {\n return false;\n }\n for (const page of pages) {\n if (matchSegmentPattern(page.pattern, target)) {\n // First matching route WINS \u2014 mirror resolvePageTtl / the framework's\n // matchRoute order (0077's invariant: never re-order, never skip a matching\n // route). Authorize shared-caching of a fallback render only when that WINNING\n // route is an exact literal page with a positive effective TTL; a catch-all/param\n // winner means the framework renders this path dynamically, so it must NOT be\n // cached. `matchedPageTtl` resolves an inherit-eligible literal page against the\n // per-path config (a literal page maps to exactly one path \u2014 no straddle).\n return isLiteralPattern(page.pattern) && matchedPageTtl(page, pathRevalidate, target) > 0;\n }\n }\n return false;\n}\n\n/**\n * A pattern is a BROAD catch-all when it crosses segment boundaries \u2014 a named\n * catch-all `:name{.+}` (compiles to `.+`) or a `*` wildcard (compiles to `.*`).\n * Such a pattern matches ANY path, including genuine static assets, so it cannot\n * certify a dotted path as page ISR content. A single-segment param (`/blog/:slug`\n * \u2192 `[^/]+`) or a literal (`/feed.xml`) is NOT broad. See `pattern.ts`'s\n * catch-all syntax (`:[^/{}]+\\{\\.\\+\\}` and `*`).\n */\nexport function isBroadCatchAll(pattern: string): boolean {\n return pattern.includes('*') || pattern.includes('{.+}');\n}\n\n/**\n * A dotted request path is ISR page content (not a static asset) when it matches a\n * declared page route that is NOT a broad catch-all: a literal (`/feed.xml`) or a\n * single-segment param (`/blog/:slug`) that matches means the framework serves it\n * as that page, so `/blog/release.v2` gets ISR even though it has a dot. A broad\n * catch-all (`/:path{.+}`, `*`) matches everything including genuine static assets\n * (`/robots.txt`), so it does NOT make a dotted path ISR content. Mirrors\n * `resolvePageTtl`'s match order: pages first-match, then the flat map. A bare\n * global-NUMBER `revalidate` declares no pattern, so dotted paths under it are NOT\n * treated as ISR-eligible page content (documented narrow residual).\n */\nexport function isDottedPathIsrEligible(\n pages: ReadonlyArray<{ pattern: string; revalidate?: number }> | undefined,\n revalidate: number | Record<string, number> | undefined,\n pathRevalidate: Record<string, number> | undefined,\n pathname: string,\n): boolean {\n if (pages && pages.length > 0) {\n for (const page of pages) {\n if (matchSegmentPattern(page.pattern, pathname)) {\n // `matchedPageTtl` resolves an inherit-eligible page against the per-path\n // config; a broad catch-all winner never certifies a dotted path as page\n // content (it also matches genuine static assets like `/robots.txt`).\n return matchedPageTtl(page, pathRevalidate, pathname) > 0 && !isBroadCatchAll(page.pattern);\n }\n }\n // no page matched \u2192 fall through to the flat map (mirror resolvePageTtl)\n }\n if (revalidate && typeof revalidate === 'object') {\n for (const [pattern, ttl] of Object.entries(revalidate)) {\n if (matchSegmentPattern(pattern, pathname)) {\n return ttl > 0 && !isBroadCatchAll(pattern);\n }\n }\n }\n return false;\n}\n\n/**\n * Build a normalized cache key Request for the edge cache (caches.default).\n * The public URL stays clean; the internal cache key carries the deployment\n * id so a new deploy never reads HTML produced by an older deploy.\n *\n * When `originalUrl` is provided (the request was dispatch-rewritten), it is\n * mixed into the key so direct and rewritten requests to the same rewritten\n * pathname do not share a cache slot. See `isrCacheKey` for rationale.\n */\nexport function isrEdgeCacheKey(\n request: Request,\n pathname: string,\n deploymentId: string,\n originalUrl?: string | null,\n): Request {\n return new Request(\n isrEdgeCacheUrl(new URL(request.url).hostname, pathname, deploymentId, 'html', originalUrl),\n { method: 'GET' },\n );\n}\n\n/**\n * Build an edge cache key for the JSON variant (pages protocol navigation).\n * Uses `?__void=json` plus the deployment id to separate it from both HTML\n * and JSON generated by other deployments. `originalUrl` is mixed in under\n * the same rules as `isrEdgeCacheKey`.\n */\nexport function isrEdgeCacheKeyJson(\n request: Request,\n pathname: string,\n deploymentId: string,\n originalUrl?: string | null,\n): Request {\n return new Request(\n isrEdgeCacheUrl(new URL(request.url).hostname, pathname, deploymentId, 'json', originalUrl),\n { method: 'GET' },\n );\n}\n", "import { PLATFORM_USAGE_PROTOCOL_VERSION } from '@void/platform';\n\nexport const USAGE_PROTOCOL_VERSION = PLATFORM_USAGE_PROTOCOL_VERSION;\n\nexport const USAGE_SIGNING_KEY_KV_KEY = '__void:usage-signing-key:v1';\n/** Operational usage intervals and their replay receipts share one validity window. */\nexport const SANDBOX_USAGE_RETENTION_MS = 8 * 24 * 60 * 60_000;\n\nexport type UsageEventSource = 'dispatch' | 'sandbox-counter';\n\nexport type SignedUsageEnvelope<T = unknown> = Readonly<{\n version: 1 | typeof USAGE_PROTOCOL_VERSION;\n source: UsageEventSource;\n eventId: string;\n event: T;\n signature: string;\n}>;\n\nconst encoder = new TextEncoder();\nconst DERIVATION_CONTEXT = 'void-platform:usage-events:v1';\n\nfunction base64url(bytes: ArrayBuffer): string {\n let binary = '';\n for (const byte of new Uint8Array(bytes)) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nfunction decodeBase64url(value: string): Uint8Array {\n const normalized = value.replace(/-/g, '+').replace(/_/g, '/');\n const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, '=');\n const binary = atob(padded);\n return Uint8Array.from(binary, (character) => character.charCodeAt(0));\n}\n\nasync function hmac(data: string, secret: string): Promise<ArrayBuffer> {\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n return crypto.subtle.sign('HMAC', key, encoder.encode(data));\n}\n\n/**\n * Return the platform-only queue signing key, creating it on first use.\n *\n * Only the purpose-separated derivative is stored in ROUTING. Dispatch can\n * therefore sign request metering without receiving the API's JWT_SECRET.\n * Tenant Workers have neither ROUTING nor this derived value.\n */\nexport async function ensureUsageSigningKey(\n routing: KVNamespace,\n jwtSecret: string,\n): Promise<string> {\n const existing = await routing.get(USAGE_SIGNING_KEY_KV_KEY);\n if (existing) {\n return existing;\n }\n const derived = base64url(await hmac(DERIVATION_CONTEXT, jwtSecret));\n await routing.put(USAGE_SIGNING_KEY_KV_KEY, derived);\n return derived;\n}\n\nexport async function readUsageSigningKey(routing: KVNamespace): Promise<string | null> {\n return routing.get(USAGE_SIGNING_KEY_KV_KEY, { cacheTtl: 60 });\n}\n\nfunction signedPayload<T>(\n version: SignedUsageEnvelope['version'],\n source: UsageEventSource,\n eventId: string,\n event: T,\n): string {\n return JSON.stringify([version, source, eventId, event]);\n}\n\nexport async function signUsageEvent<T>(\n key: string,\n source: UsageEventSource,\n eventId: string,\n event: T,\n): Promise<SignedUsageEnvelope<T>> {\n return {\n version: USAGE_PROTOCOL_VERSION,\n source,\n eventId,\n event,\n signature: base64url(\n await hmac(signedPayload(USAGE_PROTOCOL_VERSION, source, eventId, event), key),\n ),\n };\n}\n\nexport async function verifyUsageEnvelope<T>(\n value: unknown,\n key: string,\n): Promise<SignedUsageEnvelope<T> | null> {\n if (typeof value !== 'object' || value === null) {\n return null;\n }\n const envelope = value as Record<string, unknown>;\n if (\n (envelope.version !== 1 && envelope.version !== USAGE_PROTOCOL_VERSION) ||\n (envelope.source !== 'dispatch' && envelope.source !== 'sandbox-counter') ||\n typeof envelope.eventId !== 'string' ||\n envelope.eventId.length === 0 ||\n envelope.eventId.length > 256 ||\n typeof envelope.signature !== 'string' ||\n !/^[A-Za-z0-9_-]{43}$/.test(envelope.signature) ||\n typeof envelope.event !== 'object' ||\n envelope.event === null ||\n Array.isArray(envelope.event)\n ) {\n return null;\n }\n try {\n const signingKey = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(key),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['verify'],\n );\n const signature = decodeBase64url(envelope.signature);\n const valid = await crypto.subtle.verify(\n 'HMAC',\n signingKey,\n signature.buffer as ArrayBuffer,\n encoder.encode(\n signedPayload(envelope.version, envelope.source, envelope.eventId, envelope.event),\n ),\n );\n return valid ? (envelope as SignedUsageEnvelope<T>) : null;\n } catch {\n return null;\n }\n}\n", "import { readUsageSigningKey, signUsageEvent } from '@voidcloud/api/usage-auth';\nimport type { Env } from './env.ts';\n\nexport type RequestType = 'api' | 'static' | 'ssr' | 'isr' | 'websocket';\nexport type FailureKind =\n | 'platform-static-asset-timeout'\n | 'platform-static-asset-error'\n | 'platform-static-asset-missing';\n\nexport function recordRequest(\n env: Env,\n data: {\n projectId: string;\n type: RequestType;\n method: string;\n status: number;\n responseBytes: number;\n durationMs: number;\n slug: string;\n failureKind?: FailureKind;\n },\n): void {\n env.ANALYTICS.writeDataPoint({\n indexes: [data.projectId],\n blobs: [\n data.projectId,\n data.type,\n data.method,\n String(data.status),\n data.slug,\n data.failureKind ?? '',\n ],\n doubles: [1, data.responseBytes, data.durationMs],\n });\n}\n\n/**\n * Split a WfP script name into the pieces the `void_logs` dataset is keyed on.\n *\n * Mirrors `parseScriptName` in `packages/tail/src/index.ts`, restricted to the\n * `user-*` names dispatch can attribute. This MUST agree with the tail worker:\n * `GET /projects/:id/logs` selects on `index1 = 'user-<slug>'`, so a key the\n * tail worker would not have produced is a row the user can never read.\n * `packages/dispatch/test/unit/platform-log.test.ts` asserts the agreement\n * against the tail implementation itself.\n *\n * Returns `null` for anything that is not a user worker, so a platform script\n * name can never be written under a project's key.\n */\nexport function splitWorkerName(\n workerName: string,\n): { projectKey: string; deployId: string } | null {\n if (!workerName.startsWith('user-')) {\n return null;\n }\n const dplIndex = workerName.lastIndexOf('-dpl_');\n if (dplIndex > 4) {\n return {\n projectKey: workerName.slice(0, dplIndex),\n deployId: workerName.slice(dplIndex + 1),\n };\n }\n return { projectKey: workerName, deployId: '' };\n}\n\n// Analytics Engine caps the SUM of a data point's blobs at 16 KB. There is no\n// per-blob limit, and a data point over the cap is DROPPED \u2014 which\n// `recordPlatformLog` would then swallow, silently losing the row it exists to\n// write. Neither budget is a guess: the longest URL already in `void_logs` is\n// 6,703 bytes against a p99 of 195, and this row would otherwise carry the URL\n// TWICE (raw in blob4, and as the pathname inside the blob2 message). Together\n// these two caps hold every blob set under ~3.5 KB no matter the input, which\n// is a deterministic bound rather than an average-case one.\nconst MAX_LOG_URL_BYTES = 2048;\nconst MAX_LOG_PATH_BYTES = 1024;\n\n/**\n * Cut `value` to at most `maxBytes` of UTF-8, on a character boundary.\n *\n * The budget must be measured in the bytes that actually go on the wire, not in\n * UTF-16 code units \u2014 one CJK character is 1 unit and 3 bytes. Cutting mid\n * sequence is worse than useless: the split tail decodes to U+FFFD, which is\n * itself 3 bytes and pushes the field back over its budget. So the slice walks\n * back over continuation bytes and drops an incomplete lead byte before\n * decoding. A truncated value ends in an ellipsis so the reader can tell.\n */\nexport function truncateUtf8(value: string, maxBytes: number): string {\n const encoded = new TextEncoder().encode(value);\n if (encoded.length <= maxBytes) {\n return value;\n }\n\n const ellipsis = '\u2026'; // 3 bytes in UTF-8\n if (maxBytes < 3) {\n return '';\n }\n\n // Provisional cut, leaving room for the ellipsis. `encoded.length > maxBytes`\n // here, so this index is always in range.\n let end = maxBytes - 3;\n\n // If the byte AT the cut is a continuation byte (0b10xxxxxx) then the cut\n // falls inside a character \u2014 walk back to that character's lead byte, which\n // `slice(0, end)` then excludes. A cut already on a boundary stops at once,\n // so a whole character is never dropped needlessly.\n while (end > 0 && (encoded[end]! & 0xc0) === 0x80) {\n end--;\n }\n\n return new TextDecoder().decode(encoded.slice(0, end)) + ellipsis;\n}\n\n/**\n * Write one row into `void_logs` explaining a 503 that dispatch generated.\n *\n * A worker cut at the dispatch budget never returns, so it emits no tail event\n * of its own worth reading: the runtime records the invocation as `canceled`,\n * which is indistinguishable from a real client hang-up. Only dispatch knows it\n * was the one that hung up, so only dispatch can say so. Without this row\n * `void project logs` is empty for exactly the failure the user most needs\n * explained.\n *\n * The row is the same seven-blob/two-double shape `packages/tail/src/index.ts`\n * writes, so the existing read path needs no change. `outcome` is `canceled` to\n * match the tail row for the same invocation rather than invent a status.\n *\n * Best effort by construction: every call site is already returning a 503, and\n * an uncaught throw there would surface to the client as a 500. A dropped log\n * line is strictly better than that, so all failures are swallowed.\n */\nexport function recordPlatformLog(\n env: Env,\n data: {\n workerName: string | undefined;\n method: string;\n url: string;\n status: number;\n timeoutMs: number;\n },\n): void {\n if (!data.workerName) {\n return;\n }\n const parsed = splitWorkerName(data.workerName);\n if (!parsed) {\n return;\n }\n\n let pathname = data.url;\n try {\n pathname = new URL(data.url).pathname;\n } catch {\n // Keep the raw string \u2014 a message is worth more than a thrown URL parse.\n }\n\n const message =\n `Void platform: your worker did not respond within ${data.timeoutMs} ms. ` +\n `${data.method} ${truncateUtf8(pathname, MAX_LOG_PATH_BYTES)} was cut short and ` +\n `returned ${data.status}. The operation may still have side effects; ` +\n `check its outcome before retrying.`;\n\n try {\n env.LOGS.writeDataPoint({\n // `projectKey` is NOT truncated. It is the read key, so a shortened one\n // would produce a row `GET /projects/:id/logs` can never select \u2014 worse\n // than no row. It is bounded upstream by the project slug, and the tail\n // worker writes the same value whole.\n indexes: [parsed.projectKey],\n blobs: [\n 'canceled',\n JSON.stringify([{ level: 'error', message: [message], timestamp: Date.now() }]),\n '[]',\n truncateUtf8(data.url, MAX_LOG_URL_BYTES),\n data.method,\n String(data.status),\n parsed.deployId,\n ],\n doubles: [Date.now(), data.status],\n });\n } catch {\n // See the doc comment: never turn the 503 being explained into a 500.\n }\n}\n\nexport async function sendUsageEvent(\n env: Env,\n data: {\n projectId: string;\n userId: string;\n slug: string;\n requests: number;\n responseBytes: number;\n status?: number;\n failureKind?: FailureKind;\n },\n): Promise<void> {\n const key = await readUsageSigningKey(env.ROUTING);\n if (!key) {\n // The API health check creates the key before installation traffic is\n // enabled. During a staged upgrade, fail closed rather than emitting an\n // unsigned frame the hardened consumer would (correctly) reject.\n throw new Error('Usage metering is not initialized. Check the platform API /health endpoint.');\n }\n const eventId = crypto.randomUUID();\n await env.USAGE_QUEUE.send(await signUsageEvent(key, 'dispatch', eventId, data));\n}\n", "// Keep these wire values aligned with @void/platform. This private runtime is\n// bundled into that package, but must not import the package being built.\nexport const PLATFORM_DISABLED_KEY = '__void/platform/disabled/v1';\nexport const PLATFORM_DISABLED_VALUE = 'disabled';\n", "export const SITE_DOMAIN = 'void.app';\n", "import { SITE_DOMAIN } from './constants.ts';\n\n/**\n * Extract the project slug from a hostname.\n * Returns null if the hostname doesn't match the expected pattern.\n *\n * Examples:\n * \"my-app.void.app\" \u2192 \"my-app\"\n * \"void.app\" \u2192 null\n * \"foo.bar.void.app\" \u2192 null (no subdomains)\n * \"example.com\" \u2192 null\n */\nexport function extractSlug(hostname: string, baseHostname: string = SITE_DOMAIN): string | null {\n const suffix = `.${baseHostname}`;\n if (!hostname.endsWith(suffix)) {\n return null;\n }\n\n const slug = hostname.slice(0, -suffix.length);\n\n // Must be non-empty and contain no dots (no nested subdomains)\n if (!slug || slug.includes('.')) {\n return null;\n }\n\n // Validate slug format: lowercase alphanumeric + dashes, no leading/trailing dash\n if (!/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(slug)) {\n return null;\n }\n\n return slug;\n}\n", "import {\n platformProjectWorkersDevHostname,\n platformWorkersDevAliasKey,\n readPlatformApplication,\n type PlatformApplicationProject,\n} from '@void/platform';\nimport type { Env } from './env.ts';\nimport { extractSlug } from './hostname.ts';\n\nexport async function resolveProjectHostname(\n hostname: string,\n env: Env,\n): Promise<{ slug: string | null; projectId?: string; workersDev: boolean }> {\n const application = readPlatformApplication(env);\n const isWorkersDev =\n !!application.workersDev &&\n hostname.endsWith(`.${application.workersDev.subdomain}.workers.dev`);\n if (!isWorkersDev) {\n return { slug: extractSlug(hostname, env.BASE_HOSTNAME), workersDev: false };\n }\n const raw = await env.ROUTING.get(platformWorkersDevAliasKey(hostname));\n if (raw) {\n const project = JSON.parse(raw) as PlatformApplicationProject;\n if (platformProjectWorkersDevHostname(project, application.workersDev!) === hostname) {\n return { slug: project.slug, projectId: project.id, workersDev: true };\n }\n }\n return { slug: null, workersDev: true };\n}\n\n/** workers.dev has no operator-owned zone to purge. Retain shared ISR and omit this edge layer. */\nfunction isTestHostname(request: RequestInfo | URL): boolean {\n return new URL(\n typeof request === 'string' || request instanceof URL ? request : request.url,\n ).hostname.endsWith('.workers.dev');\n}\n\nexport const applicationEdgeCache: Cache = {\n async match(request, options) {\n return isTestHostname(request) ? undefined : caches.default.match(request, options);\n },\n async put(request, response) {\n if (!isTestHostname(request)) {\n await caches.default.put(request, response);\n }\n },\n async delete(request, options) {\n return isTestHostname(request) ? false : caches.default.delete(request, options);\n },\n};\n", "import type { RequestType } from './metering.ts';\n\n/** True if the last path segment contains a `.` (has a file extension). */\nexport function hasExtension(pathname: string): boolean {\n return pathname.slice(pathname.lastIndexOf('/') + 1).includes('.');\n}\n\n/**\n * Classify a user-worker (dynamic) request for metering from its path and whether\n * the project is SSR. Returns 'api'/'ssr', or null to keep the caller's existing\n * default ('static'/'websocket'). Used on BOTH the success path and the dispatch\n * TIMEOUT path so timed-out /api and SSR requests are metered with the right type\n * instead of collapsing into the 'static' bucket.\n */\nexport function classifyDynamicRequestType(\n pathname: string,\n ssr: boolean | undefined,\n): RequestType | null {\n if (pathname.startsWith('/api/') || pathname === '/api') {\n return 'api';\n }\n if (ssr && !hasExtension(pathname)) {\n return 'ssr';\n }\n return null;\n}\n", "/**\n * Error thrown when a promise wrapped by {@link withTimeout} does not settle\n * within its allotted time. The `label` identifies which awaited operation\n * timed out (e.g. `'kv:get'`, `'r2:head'`) for logging/observability.\n */\nexport class DispatchTimeoutError extends Error {\n readonly label: string;\n\n constructor(label: string) {\n super(`Dispatch operation timed out: ${label}`);\n this.name = 'DispatchTimeoutError';\n this.label = label;\n }\n}\n\n/**\n * Bounds an awaited `promise` so the request path never blocks indefinitely.\n *\n * - When `ms` is not a positive finite number (`<= 0`, `NaN`, or `Infinity`),\n * the original `promise` is returned unchanged (escape hatch \u2014 no timer).\n * - Otherwise the `promise` races a timer that rejects with a\n * {@link DispatchTimeoutError} after `ms` milliseconds.\n * - The timer is cleared as soon as `promise` settles (resolve **or** reject),\n * so it never fires late and leaves no dangling handle. A fast rejection\n * propagates the ORIGINAL reason (not a timeout error).\n * - If the timer wins, the result rejects with a `DispatchTimeoutError`. The\n * underlying `promise` keeps running to completion in the background; we do\n * not attempt to cancel the in-flight KV/R2 work.\n */\nexport function withTimeout<T>(promise: Promise<T>, ms: number, label: string): Promise<T> {\n if (!(ms > 0) || !Number.isFinite(ms)) {\n return promise;\n }\n\n let timer: ReturnType<typeof setTimeout> | null = null;\n const timeout = new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => {\n reject(new DispatchTimeoutError(label));\n }, ms);\n });\n\n return Promise.race([promise, timeout]).finally(() => {\n clearTimeout(timer);\n });\n}\n\ntype HedgedOutcome<T> =\n | Readonly<{ ok: true; value: T | null }>\n | Readonly<{ ok: false; error: unknown }>;\n\ntype DelayedHedgeOptions<T> = Readonly<{\n delayMs: number;\n timeoutMs: number;\n label: string;\n discard?: (value: T) => void | Promise<void>;\n onHedge?: () => void;\n}>;\n\n/**\n * Run one operation and launch at most one fresh attempt if the first remains\n * pending after `delayMs`.\n *\n * - Both attempts share one absolute `timeoutMs` deadline.\n * - A fast success or miss (`null`) preserves the one-attempt fast path.\n * - A fast rejection retries immediately.\n * - Once hedged, the first non-null success wins. A miss/rejection from one\n * attempt waits for its peer instead of masking a usable result.\n * - `discard` cleans up every successful non-null loser, including results\n * which arrive after the absolute timeout (for R2-backed Responses this\n * cancels the unread body stream).\n * - Every attempt is internally settled, so late rejection cannot become\n * unhandled after the winner or timeout returns.\n * - A non-positive/non-finite delay disables hedging. A non-positive/non-\n * finite timeout disables the deadline.\n */\nexport async function withDelayedHedge<T>(\n operation: () => Promise<T | null>,\n options: DelayedHedgeOptions<T>,\n): Promise<T | null> {\n const hedgeEnabled = options.delayMs > 0 && Number.isFinite(options.delayMs);\n const timeoutEnabled = options.timeoutMs > 0 && Number.isFinite(options.timeoutMs);\n const run = async (): Promise<HedgedOutcome<T>> => {\n try {\n return { ok: true, value: await operation() };\n } catch (error) {\n return { ok: false, error };\n }\n };\n\n type Attempt = Readonly<{ id: number; promise: Promise<HedgedOutcome<T>> }>;\n const attempts: Array<Attempt> = [];\n const startAttempt = (): Attempt => {\n const attempt = { id: attempts.length + 1, promise: run() };\n attempts.push(attempt);\n return attempt;\n };\n\n let hedgeTimer: ReturnType<typeof setTimeout> | null = null;\n const hedgeSignal = hedgeEnabled\n ? new Promise<Readonly<{ kind: 'hedge' }>>((resolve) => {\n hedgeTimer = setTimeout(() => resolve({ kind: 'hedge' }), options.delayMs);\n })\n : null;\n\n let timeoutTimer: ReturnType<typeof setTimeout> | null = null;\n const timeoutSignal = timeoutEnabled\n ? new Promise<Readonly<{ kind: 'timeout' }>>((resolve) => {\n timeoutTimer = setTimeout(() => resolve({ kind: 'timeout' }), options.timeoutMs);\n })\n : null;\n\n const clearTimers = (): void => {\n clearTimeout(hedgeTimer);\n clearTimeout(timeoutTimer);\n };\n const discardAttempt = (attempt: Attempt): void => {\n // The storage binding itself is not abortable. Keep a handled continuation\n // so a late body is canceled and a late rejection is always observed.\n void attempt.promise\n .then(async (outcome) => {\n if (outcome.ok && outcome.value !== null) {\n await options.discard?.(outcome.value);\n }\n })\n .catch(() => {});\n };\n const finish = (winnerId?: number): void => {\n clearTimers();\n for (const attempt of attempts) {\n if (attempt.id !== winnerId) {\n discardAttempt(attempt);\n }\n }\n };\n const timeout = (): never => {\n finish();\n throw new DispatchTimeoutError(options.label);\n };\n const waitForAttempt = (attempt: Attempt) =>\n attempt.promise.then((outcome) => ({\n kind: 'attempt' as const,\n attempt,\n outcome,\n }));\n\n const first = startAttempt();\n const initial = await Promise.race([\n waitForAttempt(first),\n ...(hedgeSignal ? [hedgeSignal] : []),\n ...(timeoutSignal ? [timeoutSignal] : []),\n ]);\n\n if (initial.kind === 'timeout') {\n return timeout();\n }\n\n if (initial.kind === 'attempt') {\n clearTimeout(hedgeTimer);\n if (initial.outcome.ok) {\n finish(first.id);\n return initial.outcome.value;\n }\n if (!hedgeEnabled) {\n finish();\n throw initial.outcome.error;\n }\n\n // Binding errors are often transient. Retry one fast rejection without\n // waiting for the hedge delay; the same absolute deadline still applies.\n options.onHedge?.();\n const retry = startAttempt();\n const retried = await Promise.race([\n waitForAttempt(retry),\n ...(timeoutSignal ? [timeoutSignal] : []),\n ]);\n if (retried.kind === 'timeout') {\n return timeout();\n }\n finish(retry.id);\n if (retried.outcome.ok) {\n return retried.outcome.value;\n }\n throw retried.outcome.error;\n }\n\n // The timer fired, so attempt one is still pending. Launch exactly one\n // independent read and prefer the first usable (non-null) result.\n options.onHedge?.();\n const second = startAttempt();\n const winner = await Promise.race([\n waitForAttempt(first),\n waitForAttempt(second),\n ...(timeoutSignal ? [timeoutSignal] : []),\n ]);\n\n if (winner.kind === 'timeout') {\n return timeout();\n }\n if (winner.outcome.ok && winner.outcome.value !== null) {\n finish(winner.attempt.id);\n return winner.outcome.value;\n }\n\n const peer = winner.attempt.id === first.id ? second : first;\n const peerResult = await Promise.race([\n waitForAttempt(peer),\n ...(timeoutSignal ? [timeoutSignal] : []),\n ]);\n if (peerResult.kind === 'timeout') {\n return timeout();\n }\n\n if (peerResult.outcome.ok && peerResult.outcome.value !== null) {\n finish(peer.id);\n return peerResult.outcome.value;\n }\n finish();\n if (winner.outcome.ok || peerResult.outcome.ok) {\n return null;\n }\n throw winner.outcome.error;\n}\n\n/**\n * Resolve the timeout budget (ms) from the raw `DISPATCH_TIMEOUT_MS` env value.\n *\n * - Unset (`undefined`) \u2192 the `fallback` default (10s).\n * - Any explicitly-provided value is passed through via `Number(...)` UNCHANGED \u2014\n * including `'0'`, negatives, empty string, and non-numeric strings (`NaN`). This\n * preserves the escape hatch: {@link withTimeout} treats any non-positive/non-finite\n * budget as \"no timer\", so an operator can disable the bounded paths by setting\n * `DISPATCH_TIMEOUT_MS='0'` WITHOUT a redeploy. A blanket `|| fallback` would defeat\n * this by collapsing every disabling value back to the default.\n */\nexport function resolveTimeoutMs(raw: string | undefined, fallback = 10000): number {\n return raw === undefined ? fallback : Number(raw);\n}\n", "import { resolvePlatformApplicationEnvironment } from '@void/platform';\nimport type { Env } from './env.ts';\nimport { createErrorResponse } from './error-page.ts';\nimport { applyHeaderRules, type HeaderRule } from './headers.ts';\nimport {\n readIsrCache,\n writeIsrCache,\n deleteIsrCache,\n isStale,\n isrCacheResponse,\n isrEdgeCacheKey,\n isrEdgeCacheKeyJson,\n hasCurrentSharedCachePolicy,\n hasSharedCacheOptOut,\n SHARED_CACHE_POLICY_HEADER,\n markSharedCachePolicy,\n resolveRevalidateTtl,\n resolvePathTtl,\n resolvePageTtl,\n matchesLiteralPage,\n isDottedPathIsrEligible,\n shouldBypassIsr,\n isFrameworkDocumentRequest,\n extractPageDataFromHtml,\n normalizePageDataForJsonCache,\n} from './isr.ts';\nimport {\n recordPlatformLog,\n recordRequest,\n sendUsageEvent,\n type FailureKind,\n type RequestType,\n} from './metering.ts';\nimport { PLATFORM_DISABLED_KEY, PLATFORM_DISABLED_VALUE } from './platform-lifecycle.ts';\nimport { applicationEdgeCache, resolveProjectHostname } from './project-hostname.ts';\nimport { classifyDynamicRequestType, hasExtension } from './request-type.ts';\nimport { applyRoutingRules, mergeQueryIntoLocation, type RedirectRule } from './routing-rules.ts';\nimport { resolveStaticPath, resolveAssetContentType, safeDecodePathname } from './static.ts';\nimport type { AssetConfig } from './static.ts';\nimport {\n buildVariantOriginalUrl,\n exactQueryAllowlist,\n type QueryAllowlist,\n} from './variant-key.ts';\nimport {\n DispatchTimeoutError,\n resolveTimeoutMs,\n withDelayedHedge,\n withTimeout,\n} from './with-timeout.ts';\n\ntype RoutingEntry = Readonly<{\n workerName: string;\n projectId: string;\n userId?: string;\n type?: 'void' | 'spa' | 'static' | 'framework';\n ssr?: boolean;\n revalidate?: number | Record<string, number>;\n pages?: ReadonlyArray<{ pattern: string; revalidate?: number }>;\n // RAW per-path `routing.revalidate` OBJECT config (pages mode). Resolved at\n // the edge against the real request path for a matched inherit-eligible page\n // (a `pages` entry with no baked `revalidate`) \u2014 honors per-path `0` opt-outs\n // a dynamic pattern straddles. Distinct from the folded `revalidate` map.\n pathRevalidate?: Record<string, number>;\n version?: string;\n limits?: Record<string, number>;\n suspended?: string;\n hashedAssetsPrefix?: string;\n headerRules?: ReadonlyArray<HeaderRule>;\n // `redirectRules` fires pre-asset, `fallbackRules` fires post-asset.\n // List identity encodes the pre-vs-post-asset semantic.\n redirectRules?: ReadonlyArray<RedirectRule>;\n fallbackRules?: ReadonlyArray<RedirectRule>;\n // Per-pathname allowlist of query params that are part of the ISR variant\n // key on a rewrite. Default (no entry / no allowlist) drops every param,\n // so an attacker can't fan out the cache by varying `?utm`/`?cb`/etc.\n queryAllowlist?: QueryAllowlist;\n staticDeploymentId?: string;\n assetManifestId?: string;\n assetConfig?: AssetConfig;\n}>;\n\ntype QueueRoutingEntry = Readonly<{\n workerName: string;\n projectId: string;\n queueName: string;\n // HMAC-signed proxy token matching the user worker's __VOID_PROXY_TOKEN\n // binding. The framework-generated /__void/queue handler rejects relays\n // without a matching `x-void-internal` header with 401. Absent on entries\n // written by older API versions.\n proxyToken?: string;\n}>;\n\nconst CLIENT_REVALIDATE_CACHE_CONTROL = 'public, max-age=0, must-revalidate';\nconst STATIC_ASSET_HEDGE_DELAY_MS = 1000;\nconst PLATFORM_QUEUE_RETRY_DELAY_SECONDS = 300;\nconst PLATFORM_STATIC_ASSET_TIMEOUT: FailureKind = 'platform-static-asset-timeout';\nconst PLATFORM_STATIC_ASSET_ERROR: FailureKind = 'platform-static-asset-error';\nconst PLATFORM_STATIC_ASSET_MISSING: FailureKind = 'platform-static-asset-missing';\n\n// How long a STALE ISR entry may keep being served without a successful refresh\n// before a background revalidation evicts it. Measured from when the entry became\n// STALE (`createdAt + ttl`), NOT from creation \u2014 so an entry with a long TTL still\n// gets the full grace of STALE tolerance and a transient failure right after expiry\n// does not evict immediately. Bounds the \"serve stale forever\" window for a\n// permanently-removed page (origin now 404s and falls back to a non-cacheable shell,\n// so the entry can neither refresh nor authoritatively opt-out-evict) while staying\n// far above any transient deploy-race 404 so normal stale-while-revalidate is intact.\nconst ISR_STALE_EVICT_GRACE_SECONDS = 86_400; // 24h of STALE tolerance\n\nfunction clientRevalidateResponse(response: Response): Response {\n const res = new Response(response.body, response);\n res.headers.set('Cache-Control', CLIENT_REVALIDATE_CACHE_CONTROL);\n res.headers.delete(SHARED_CACHE_POLICY_HEADER);\n return res;\n}\n\n// Fast body-less response for an operation bounded by `withTimeout` that\n// stalled past the budget. `X-Void-Timeout` names the stalled operation for\n// observability; 503s advertise a short `Retry-After` so clients back off.\nfunction timeoutResponse(status: number, label: string): Response {\n return new Response(null, {\n status,\n headers: {\n 'X-Void-Timeout': label,\n ...(status === 503 ? { 'Retry-After': '5' } : {}),\n },\n });\n}\n\nfunction staticAssetFailureResponse(kind: FailureKind): Response {\n if (kind === PLATFORM_STATIC_ASSET_TIMEOUT) {\n return timeoutResponse(503, 'static-asset');\n }\n return new Response(null, {\n status: 503,\n headers: {\n 'X-Void-Storage-Error':\n kind === PLATFORM_STATIC_ASSET_MISSING ? 'static-asset-missing' : 'static-asset-read',\n 'Retry-After': '5',\n },\n });\n}\n\nexport function isEventStreamResponse(response: Response): boolean {\n return (\n response.headers.get('content-type')?.toLowerCase().split(';', 1)[0]?.trim() ===\n 'text/event-stream'\n );\n}\n\nexport function isHtmlResponse(response: Response): boolean {\n return (\n response.headers.get('content-type')?.toLowerCase().split(';', 1)[0]?.trim() === 'text/html'\n );\n}\n\nfunction jsonCacheResponse(pageData: string, ttl: number, state: 'HIT' | 'MISS'): Response {\n const response = new Response(pageData, {\n headers: {\n 'content-type': 'application/json',\n 'Cache-Control': `public, s-maxage=${ttl}, max-age=0, must-revalidate`,\n 'x-isr-cache': state,\n },\n });\n markSharedCachePolicy(response.headers);\n return response;\n}\n\nasync function populateJsonEdgeCache(\n cache: Cache,\n cacheKey: Request,\n response: Response,\n ttl: number,\n state: 'HIT' | 'MISS',\n): Promise<void> {\n const fromHeader = response.headers.get('x-void-page-data');\n const pageData = fromHeader\n ? normalizePageDataForJsonCache(fromHeader)\n : extractPageDataFromHtml(await response.clone().text());\n if (!pageData) {\n return;\n }\n await cache.put(cacheKey, jsonCacheResponse(pageData, ttl, state));\n}\n\ntype SharedIsrEntry = Readonly<{\n projectId: string;\n deploymentId: string;\n host: string;\n pathname: string;\n originalUrl?: string;\n htmlKey: Request;\n jsonKey: Request;\n}>;\n\nasync function deleteSharedIsrEntry(env: Env, entry: SharedIsrEntry): Promise<void> {\n await Promise.all([\n deleteIsrCache(\n env,\n entry.projectId,\n entry.deploymentId,\n entry.host,\n entry.pathname,\n entry.originalUrl,\n ),\n applicationEdgeCache.delete(entry.htmlKey),\n applicationEdgeCache.delete(entry.jsonKey),\n ]);\n}\n\nasync function applyWorkerFallbackRules(opts: {\n response: Response;\n worker: { fetch(request: Request): Promise<Response> };\n dispatchReq: Request;\n routing: RoutingEntry;\n pathname: string;\n url: URL;\n originalRequestUrl: string;\n originalUrlHeader?: string;\n originalUrlVariant?: string;\n deadline?: Readonly<{ startedAt: number; timeoutMs: number }>;\n}): Promise<{\n response: Response;\n pathname: string;\n originalUrlVariant?: string;\n applied: boolean;\n}> {\n if (opts.response.status !== 404 || !opts.routing.fallbackRules?.length) {\n return {\n response: opts.response,\n pathname: opts.pathname,\n originalUrlVariant: opts.originalUrlVariant,\n applied: false,\n };\n }\n if (opts.routing.type === 'void' && opts.response.headers.get('X-Void-No-Match') !== '1') {\n return {\n response: opts.response,\n pathname: opts.pathname,\n originalUrlVariant: opts.originalUrlVariant,\n applied: false,\n };\n }\n\n const fallback = applyRoutingRules(opts.pathname, opts.routing.fallbackRules, opts.url.hostname);\n if (fallback?.type !== 'rewrite') {\n return {\n response: opts.response,\n pathname: opts.pathname,\n originalUrlVariant: opts.originalUrlVariant,\n applied: false,\n };\n }\n\n const fallbackHeader = opts.originalUrlHeader ?? opts.originalRequestUrl;\n const originalUrlVariant =\n opts.originalUrlVariant ??\n buildVariantOriginalUrl(opts.originalRequestUrl, opts.pathname, opts.routing.queryAllowlist);\n const fallbackUrl = new URL(opts.url.toString());\n fallbackUrl.pathname = fallback.destination;\n const fallbackRequest = rebuildRequest(opts.dispatchReq, fallbackUrl.toString(), (headers) =>\n headers.set('X-Void-Original-URL', fallbackHeader),\n );\n\n return {\n response:\n opts.deadline === undefined\n ? await opts.worker.fetch(fallbackRequest)\n : await withTimeout(\n opts.worker.fetch(fallbackRequest),\n remainingTimeoutBudget(opts.deadline.startedAt, opts.deadline.timeoutMs, 'dispatch'),\n 'dispatch',\n ),\n pathname: fallback.destination,\n originalUrlVariant,\n applied: true,\n };\n}\n\nfunction buildFallbackOriginalUrlVariant(\n requestUrl: string,\n pathname: string,\n requestHost: string,\n routing: RoutingEntry,\n originalUrlVariant: string | undefined,\n): string | undefined {\n // Fallback rewrites are discovered after the first worker/static miss, but\n // ISR needs the read key before dispatching. If a fallback rule can handle\n // this pathname, use the same original-URL variant a later fallback dispatch\n // would expose via X-Void-Original-URL so query-allowlisted renders cannot\n // collide with the direct ISR key.\n if (originalUrlVariant || !routing.fallbackRules?.length) {\n return originalUrlVariant;\n }\n const fallback = applyRoutingRules(pathname, routing.fallbackRules, requestHost);\n if (fallback?.type !== 'rewrite') {\n return undefined;\n }\n return buildVariantOriginalUrl(requestUrl, pathname, routing.queryAllowlist);\n}\n\nfunction resolveCachedWfpFallbackPathname(\n pathname: string,\n routing: RoutingEntry,\n requestHost: string,\n): string | undefined {\n const fallback = applyRoutingRules(pathname, routing.fallbackRules, requestHost);\n return fallback?.type === 'rewrite' ? fallback.destination : undefined;\n}\n\n// CF's error text for WC-4511 asset dedupe poisoning. Not guaranteed\n// stable \u2014 monitor fallback telemetry if CF's worker-runtime changes.\nconst CF_ASSETS_STUB_MARKER = 'Assets have not yet been deployed to this script';\n\nfunction isLikelyCfAssetStub(response: Response): boolean {\n if (response.status !== 200) {\n return false;\n }\n const contentType = response.headers.get('content-type')?.toLowerCase();\n if (!contentType?.startsWith('text/plain')) {\n return false;\n }\n const contentLengthRaw = response.headers.get('content-length');\n if (!contentLengthRaw) {\n return false;\n }\n const contentLength = Number.parseInt(contentLengthRaw, 10);\n return contentLength > 0 && contentLength < 200;\n}\n\n// Serve the requested asset from platform R2/KV using the mirror written\n// on deploy. Returns null if the routing entry lacks a manifest, the\n// manifest is missing from KV, or the path/hash cannot be resolved. The\n// caller turns that confirmed poison-stub fallback miss into an attributed\n// platform 503 so no successful cache entry can be written.\nfunction remainingTimeoutBudget(\n startedAt: number,\n timeoutMs: number,\n label = 'static-asset',\n): number {\n if (!(timeoutMs > 0 && Number.isFinite(timeoutMs))) {\n return timeoutMs;\n }\n const remainingMs = timeoutMs - (Date.now() - startedAt);\n if (remainingMs <= 0) {\n throw new DispatchTimeoutError(label);\n }\n return remainingMs;\n}\n\nasync function fetchAssetManifest(\n env: Env,\n deploymentId: string,\n projectId: string,\n timeoutMs: number,\n): Promise<Record<string, string> | null> {\n const hedgeDelayMs =\n timeoutMs > 0 && Number.isFinite(timeoutMs)\n ? Math.min(STATIC_ASSET_HEDGE_DELAY_MS, timeoutMs / 2)\n : 0;\n try {\n const raw = await withDelayedHedge(\n () => env.ROUTING.get(`manifest:${deploymentId}`, { cacheTtl: 86400 }),\n {\n delayMs: hedgeDelayMs,\n timeoutMs,\n label: 'static-asset',\n onHedge: () => {\n console.warn(\n JSON.stringify({\n event: 'wfp-asset-manifest-read-hedge',\n projectId,\n deploymentId,\n delayMs: hedgeDelayMs,\n ts: Date.now(),\n }),\n );\n },\n },\n );\n if (!raw) {\n return null;\n }\n return JSON.parse(raw) as Record<string, string>;\n } catch (error) {\n console.error(\n JSON.stringify({\n event:\n error instanceof DispatchTimeoutError\n ? 'wfp-asset-manifest-timeout'\n : 'wfp-asset-manifest-read-error',\n projectId,\n deploymentId,\n error:\n error instanceof DispatchTimeoutError\n ? undefined\n : error instanceof Error\n ? error.message\n : String(error),\n ts: Date.now(),\n }),\n );\n if (error instanceof DispatchTimeoutError) {\n throw error;\n }\n throw new StaticAssetReadError(error);\n }\n}\n\nasync function serveWfpAssetFallback(\n env: Env,\n routing: RoutingEntry,\n pathname: string,\n timeoutMs = 10000,\n fallbackPathname?: string,\n): Promise<{ response: Response; pathname: string } | null> {\n if (!routing.assetManifestId) {\n return null;\n }\n const startedAt = Date.now();\n const assetManifest = await fetchAssetManifest(\n env,\n routing.assetManifestId,\n routing.projectId,\n remainingTimeoutBudget(startedAt, timeoutMs),\n );\n if (!assetManifest) {\n return null;\n }\n const assetConfig: AssetConfig = routing.assetConfig ?? { not_found_handling: 'none' };\n let resolvedPathname = pathname;\n let resolved = resolveStaticPath(pathname, assetManifest, assetConfig);\n if ((!resolved || resolved.notFound) && fallbackPathname && fallbackPathname !== pathname) {\n const fallbackResolved = resolveStaticPath(fallbackPathname, assetManifest, assetConfig);\n if (fallbackResolved && !fallbackResolved.notFound) {\n resolved = fallbackResolved;\n resolvedPathname = fallbackPathname;\n }\n }\n if (!resolved) {\n return null;\n }\n if (resolved.redirect) {\n return {\n response: new Response(null, {\n status: 308,\n headers: { Location: resolved.redirect },\n }),\n pathname: resolvedPathname,\n };\n }\n const assetResponse = await fetchStaticAsset(\n env,\n resolved.hash,\n resolved.path,\n routing.projectId,\n routing.assetManifestId,\n remainingTimeoutBudget(startedAt, timeoutMs),\n );\n if (!assetResponse) {\n return null;\n }\n return {\n response: new Response(assetResponse.body, {\n status: resolved.notFound ? 404 : 200,\n headers: assetResponse.headers,\n }),\n pathname: resolvedPathname,\n };\n}\n\nfunction logWfpAssetFallback(\n routing: RoutingEntry,\n pathname: string,\n userAgent: string | null,\n): void {\n console.log(\n JSON.stringify({\n event: 'wfp-asset-fallback',\n projectId: routing.projectId,\n deploymentId: routing.assetManifestId,\n pathname,\n userAgent,\n ts: Date.now(),\n }),\n );\n}\n\nasync function maybeServeWfpAssetFallback(opts: {\n env: Env;\n routing: RoutingEntry;\n pathname: string;\n response: Response;\n userAgent: string | null;\n timeoutMs?: number;\n deadline?: Readonly<{ startedAt: number; timeoutMs: number }>;\n fallbackPathname?: string;\n}): Promise<{ response: Response; failureKind?: FailureKind; pathname: string }> {\n const startedAt = opts.deadline?.startedAt ?? Date.now();\n const timeoutMs = opts.deadline?.timeoutMs ?? opts.timeoutMs ?? 10000;\n if (isEventStreamResponse(opts.response)) {\n return { response: opts.response, pathname: opts.pathname };\n }\n if (!isLikelyCfAssetStub(opts.response)) {\n return { response: opts.response, pathname: opts.pathname };\n }\n let stubConfirmed = false;\n let fallback: { response: Response; pathname: string } | null;\n try {\n const body = await withTimeout(\n opts.response.clone().text(),\n remainingTimeoutBudget(startedAt, timeoutMs),\n 'static-asset',\n );\n if (!body.includes(CF_ASSETS_STUB_MARKER)) {\n return { response: opts.response, pathname: opts.pathname };\n }\n stubConfirmed = true;\n fallback = await serveWfpAssetFallback(\n opts.env,\n opts.routing,\n opts.pathname,\n remainingTimeoutBudget(startedAt, timeoutMs),\n opts.fallbackPathname,\n );\n } catch (error) {\n // Once the CF poison stub is confirmed, never pass its HTTP 200 through:\n // callers may cache successful responses. Surface an attributed platform\n // 503 instead so the failure is retryable without poisoning edge/ISR caches.\n if (error instanceof DispatchTimeoutError) {\n if (!stubConfirmed) {\n return {\n response: timeoutResponse(503, 'dispatch'),\n pathname: opts.pathname,\n };\n }\n return {\n response: staticAssetFailureResponse(PLATFORM_STATIC_ASSET_TIMEOUT),\n failureKind: PLATFORM_STATIC_ASSET_TIMEOUT,\n pathname: opts.pathname,\n };\n }\n if (error instanceof StaticAssetReadError) {\n return {\n response: staticAssetFailureResponse(PLATFORM_STATIC_ASSET_ERROR),\n failureKind: PLATFORM_STATIC_ASSET_ERROR,\n pathname: opts.pathname,\n };\n }\n throw error;\n }\n if (!fallback) {\n console.error(\n JSON.stringify({\n event: 'wfp-asset-fallback-missing',\n projectId: opts.routing.projectId,\n deploymentId: opts.routing.assetManifestId,\n pathname: opts.pathname,\n ts: Date.now(),\n }),\n );\n return {\n response: staticAssetFailureResponse(PLATFORM_STATIC_ASSET_MISSING),\n failureKind: PLATFORM_STATIC_ASSET_MISSING,\n pathname: opts.pathname,\n };\n }\n logWfpAssetFallback(opts.routing, fallback.pathname, opts.userAgent);\n return fallback;\n}\n\n/**\n * Rebuild a `Request` with mutated headers, optionally under a new URL.\n * Handles the body-preservation cases we hit at three points in the fetch\n * handler (ingress header-strip, rewrite URL swap, post-ISR dispatch):\n *\n * - Body already consumed/locked: drop body and any stale framing headers\n * (`content-length` / `transfer-encoding`) \u2014 some runtimes reject bodiless\n * frames that still advertise a framing size.\n * - GET / HEAD: no body to forward; skip the body + duplex dance.\n * - Everything else: forward the streaming body with `duplex: 'half'`.\n */\nexport function rebuildRequest(\n request: Request,\n url: string,\n mutateHeaders: (headers: Headers) => void,\n): Request {\n const headers = new Headers(request.headers);\n mutateHeaders(headers);\n // `cf` (country, colo, botManagement, tlsClientAuth, \u2026) is populated by\n // the CF edge and read by user workers. A plain `new Request(url, init)`\n // does not propagate it; we have to thread it through init.cf explicitly.\n const cfProperties = request.cf;\n if (request.bodyUsed || request.body?.locked) {\n headers.delete('content-length');\n headers.delete('transfer-encoding');\n return new Request(url, { method: request.method, headers, cf: cfProperties });\n }\n if (request.method === 'GET' || request.method === 'HEAD') {\n return new Request(url, { method: request.method, headers, cf: cfProperties });\n }\n return new Request(url, {\n method: request.method,\n headers,\n body: request.body,\n cf: cfProperties,\n // @ts-expect-error -- duplex required for streaming bodies in CF Workers\n duplex: 'half',\n });\n}\n\nexport default {\n async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {\n env = await resolvePlatformApplicationEnvironment(env);\n const url = new URL(request.url);\n if (\n !env.PLATFORM_INSTALLATION_ID &&\n url.pathname === '/health' &&\n request.headers.get('X-Health-Check') === 'void-admin'\n ) {\n return Response.json({ ok: true });\n }\n // The installer proves the complete cutover while the public routing gate\n // remains closed. This endpoint exposes no application data and is already\n // reserved for the installer's exact health-check header.\n if (\n env.PLATFORM_HEALTH_PROBE_TOKEN &&\n url.pathname === '/health' &&\n request.headers.get('X-Void-Platform-Probe') === env.PLATFORM_HEALTH_PROBE_TOKEN\n ) {\n return Response.json({\n ok: true,\n ...(env.PLATFORM_APPLICATION ? { installationId: env.PLATFORM_INSTALLATION_ID } : {}),\n });\n }\n if (\n env.PLATFORM_TRAFFIC_STATE === 'staging' ||\n env.PLATFORM_TRAFFIC_STATE === 'sandbox-drain' ||\n (env.PLATFORM_INSTALLATION_ID &&\n (await env.ROUTING.get(PLATFORM_DISABLED_KEY)) === PLATFORM_DISABLED_VALUE)\n ) {\n return createErrorResponse(request, 503, 'Platform disabled', {\n 'Cache-Control': 'no-store',\n });\n }\n const startTime = Date.now();\n // Budget for the bounded hot paths (static-asset reads, primary dispatch).\n // Unset \u2192 the 10s default. An explicit `0`/negative/non-finite override is\n // passed through verbatim, disabling the timers via `withTimeout`'s escape\n // hatch (any non-positive/non-finite value = \"no timer\") \u2014 an operator kill\n // switch that works WITHOUT a redeploy.\n const timeoutMs = resolveTimeoutMs(env.DISPATCH_TIMEOUT_MS);\n\n // Block Void-internal routes from external HTTP access.\n // Only /__void/* is reserved by the platform \u2014 other __ prefixes\n // (e.g. /__nuxt_content, /__og-image__) are user/framework assets.\n if (\n url.pathname.startsWith('/__void/') ||\n // Legacy: old SDK versions register these top-level paths. Block them\n // at the edge so we don't rely solely on worker-side token checks.\n // TODO: remove once all deployed workers use /__void/* paths. See #88\n url.pathname === '/__scheduled' ||\n url.pathname === '/__queue'\n ) {\n return createErrorResponse(request, 404, 'Not Found');\n }\n\n const selected = await resolveProjectHostname(url.hostname, env);\n const slug = selected.slug;\n if (selected.workersDev && !selected.projectId) {\n return createErrorResponse(request, 404, 'Not Found');\n }\n const routingKey = slug ?? `domain:${url.hostname}`;\n\n const routingRaw = await env.ROUTING.get(routingKey, { cacheTtl: 60 });\n if (!routingRaw) {\n return createErrorResponse(request, 404, 'Not Found', {\n 'Cache-Control': 'public, max-age=30',\n });\n }\n\n const routing: RoutingEntry = JSON.parse(routingRaw);\n if (selected.projectId && selected.projectId !== routing.projectId) {\n return createErrorResponse(request, 404, 'Not Found');\n }\n\n // Check if project is suspended\n if (routing.suspended) {\n return Response.json(\n { error: 'usage limit exceeded', reason: routing.suspended },\n { status: 429, headers: { 'Cache-Control': 'public, s-maxage=30, max-age=0' } },\n );\n }\n\n // Strip any client-supplied X-Void-Original-URL on entry. Dispatch owns this\n // header: the only legitimate source is a dispatch-side rewrite below, which\n // sets it on `workerRequest` with the true original URL. Allowing a client\n // value to flow through would let callers spoof the \"original URL\" seen by\n // user workers that trust the header.\n if (request.headers.has('X-Void-Original-URL')) {\n request = rebuildRequest(request, request.url, (headers) =>\n headers.delete('X-Void-Original-URL'),\n );\n }\n let pathname = url.pathname;\n let sharedIsrEntry: SharedIsrEntry | undefined;\n let requestType: RequestType =\n request.headers.get('upgrade')?.toLowerCase() === 'websocket' ? 'websocket' : 'static';\n\n const meter = (response: Response, options?: { failureKind?: FailureKind }) => {\n const responseBytes = isEventStreamResponse(response)\n ? 0\n : Number(response.headers.get('content-length') ?? 0);\n recordRequest(env, {\n projectId: routing.projectId,\n type: requestType,\n method: request.method,\n status: response.status,\n responseBytes,\n durationMs: Date.now() - startTime,\n slug: slug ?? url.hostname,\n ...(options?.failureKind && { failureKind: options.failureKind }),\n });\n if (routing.userId) {\n ctx.waitUntil(\n sendUsageEvent(env, {\n projectId: routing.projectId,\n userId: routing.userId,\n slug: slug ?? url.hostname,\n requests: 1,\n responseBytes,\n ...(response.status >= 500 && { status: response.status }),\n ...(options?.failureKind && { failureKind: options.failureKind }),\n }),\n );\n }\n const res = new Response(response.body, response);\n res.headers.delete('X-Void-No-Match');\n // Cache API and upstream responses have immutable headers. Strip the\n // internal cache marker only from this writable client response.\n res.headers.delete(SHARED_CACHE_POLICY_HEADER);\n res.headers.set('X-Hosted-By', 'void.cloud');\n return res;\n };\n\n // The user's worker blew the dispatch budget. It returned nothing, so it\n // logged nothing, and its own tail event records only `canceled` \u2014 which a\n // real client hang-up produces too. Dispatch is the only party that knows\n // it was the one that hung up, so it says so in the project's log stream.\n // Metering is unchanged; this only adds the explanation.\n const meterWorkerTimeout = () => {\n recordPlatformLog(env, {\n workerName: routing.workerName,\n method: request.method,\n url: request.url,\n status: 503,\n timeoutMs,\n });\n return meter(timeoutResponse(503, 'dispatch'));\n };\n\n // Routing rules \u2014 redirects short-circuit, rewrites modify pathname\n // Two distinct values flow out of a rewrite:\n // - `originalUrlVariant`: feeds the ISR variant key. Normalized via\n // `routing.queryAllowlist` so an attacker can't fan out cache slots\n // by varying `?utm`/`?cb`/etc.\n // - `originalUrlHeader`: the X-Void-Original-URL surfaced to user\n // workers for `c.originalUrl()`. Carries the full request URL \u2014\n // user code expects to see the actual URL the client sent.\n let originalUrlVariant: string | undefined;\n let originalUrlHeader: string | undefined;\n if (routing.redirectRules?.length) {\n const result = applyRoutingRules(pathname, routing.redirectRules, url.hostname);\n if (result?.type === 'redirect') {\n const location = mergeQueryIntoLocation(result.destination, url.search);\n return meter(\n new Response(null, { status: result.status, headers: { Location: location } }),\n );\n }\n if (result?.type === 'rewrite') {\n // Destination shape (path-absolute, no `//`, no `?`) is enforced by\n // the framework validator and re-checked by the API on manifest ingest\n // (see `packages/api/src/routes/deploy.ts`). Dispatch trusts those two\n // gates and does not re-validate here.\n originalUrlHeader = request.url;\n originalUrlVariant = buildVariantOriginalUrl(request.url, pathname, routing.queryAllowlist);\n pathname = result.destination;\n url.pathname = pathname;\n }\n }\n\n // If rewritten, build the request the worker + ISR should see (rewritten\n // URL + original-URL header).\n let workerRequest = request;\n if (originalUrlHeader) {\n workerRequest = rebuildRequest(request, url.toString(), (headers) =>\n headers.set('X-Void-Original-URL', originalUrlHeader),\n );\n }\n\n // Edge-cache hashed static assets (immutable, content-addressed URLs)\n if (routing.hashedAssetsPrefix && isSharedStaticCacheRequestEligible(request)) {\n const prefix = '/' + routing.hashedAssetsPrefix + '/';\n if (pathname.startsWith(prefix)) {\n // Cache key tracks the post-rewrite (hash-bearing) URL, not the\n // request URL: hashed entries are stored with a 1-year immutable\n // Cache-Control, so a redirect rule that maps a stable path like\n // /logo to /assets/logo-<hash>.png must not cache content under\n // /logo \u2014 a future deploy that points /logo at a different hash\n // would keep serving the stale entry. Strip query: hashed\n // filenames are already content-addressed by their pathname.\n const cacheUrl = new URL(url.toString());\n cacheUrl.search = '';\n const cacheKey = new Request(cacheUrl.toString());\n\n // Hashed assets are served straight from the immutable edge cache. Apply\n // routing.headerRules on the way OUT \u2014 on both cache HIT and MISS \u2014 instead\n // of baking them into the cached body. This is what lets a cross-origin\n // isolated app put COOP/COEP/CORP on its hashed worker/wasm assets: browsers\n // fetch those over GET, and without per-serve header application the GET\n // response (unlike a HEAD, which falls through to the worker and is handled\n // by the dispatch path's applyHeaderRules) would ship with no COEP, so a\n // module worker spawned from a require-corp document would be blocked.\n // Applying per-serve rather than at cache-write also means a header-rule\n // change in a later deploy takes effect even when the content hash \u2014 and\n // thus the unversioned, immutable cache key \u2014 is unchanged.\n //\n // Tenant rules apply ADDITIVELY only. The platform/origin owns how a\n // content-addressed asset is cached, represented, and framed on the wire;\n // tenants may ADD headers (COOP/COEP/CORP, security) but must not rewrite\n // the headers below, so each is restored from the pre-rule response after\n // the rules run. The set is exactly the headers whose forgery would corrupt\n // the asset or break the immutable-cache / usage-metering contract:\n // cache-control immutable contract; the cache-HIT check above keys on it\n // content-type wrong MIME breaks ES-module / WebAssembly loading\n // content-encoding a false `gzip` makes the browser mis-decode the bytes\n // content-length meter() bills from it; clients frame the body by it\n // content-range } forging range/framing semantics truncates or\n // accept-ranges } mis-reads a body the platform did not range-encode\n // transfer-encoding hop-by-hop framing; must never come from a tenant rule\n // Cosmetic metadata (Vary, ETag, ...) is left overridable \u2014 on an immutable\n // URL-keyed asset it is neither a corruption nor a security risk. This\n // mirrors how the static-asset paths force their own Cache-Control after\n // applyHeaderRules via clientRevalidateResponse.\n const MANAGED_ASSET_HEADERS = [\n 'cache-control',\n 'content-type',\n 'content-encoding',\n 'content-length',\n 'content-range',\n 'accept-ranges',\n 'transfer-encoding',\n ] as const;\n const finalizeAsset = (assetResponse: Response, failureKind?: FailureKind): Response => {\n const ruled = applyHeaderRules(assetResponse, pathname, routing.headerRules);\n // applyHeaderRules returns the same object when nothing matched \u2014 then\n // there is no override to undo and we can skip the header restore.\n if (ruled !== assetResponse) {\n for (const name of MANAGED_ASSET_HEADERS) {\n const managed = assetResponse.headers.get(name);\n if (managed === null) {\n ruled.headers.delete(name);\n } else {\n ruled.headers.set(name, managed);\n }\n }\n }\n return meter(ruled, failureKind ? { failureKind } : undefined);\n };\n\n const cache = applicationEdgeCache;\n const cached = await cache.match(cacheKey);\n if (\n cached?.headers.get('Cache-Control')?.includes('immutable') &&\n isCurrentStaticCacheResponse(cached)\n ) {\n if (!routing.staticDeploymentId) {\n const repairResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname,\n response: cached,\n userAgent: request.headers.get('user-agent'),\n timeoutMs,\n });\n if (repairResult.response !== cached) {\n if (isStaticCacheResponseEligible(repairResult.response)) {\n const repaired = new Response(repairResult.response.body, repairResult.response);\n repaired.headers.set('Cache-Control', 'public, max-age=31536000, immutable');\n markSharedCachePolicy(repaired.headers);\n const repairedForCache = repaired.clone();\n ctx.waitUntil(\n cache.delete(cacheKey).then(() => cache.put(cacheKey, repairedForCache)),\n );\n return finalizeAsset(repaired, repairResult.failureKind);\n }\n ctx.waitUntil(cache.delete(cacheKey));\n return finalizeAsset(repairResult.response, repairResult.failureKind);\n }\n }\n return finalizeAsset(cached);\n }\n if (cached) {\n await cache.delete(cacheKey);\n }\n // Cache miss \u2014 fetch from KV/R2 for static deployments, or invoke worker\n if (routing.staticDeploymentId) {\n const staticAssetStartedAt = Date.now();\n let assetManifest: Record<string, string> | null;\n try {\n assetManifest = await fetchAssetManifest(\n env,\n routing.staticDeploymentId,\n routing.projectId,\n remainingTimeoutBudget(staticAssetStartedAt, timeoutMs),\n );\n } catch (err) {\n if (err instanceof DispatchTimeoutError) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_TIMEOUT), {\n failureKind: PLATFORM_STATIC_ASSET_TIMEOUT,\n });\n }\n if (err instanceof StaticAssetReadError) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_ERROR), {\n failureKind: PLATFORM_STATIC_ASSET_ERROR,\n });\n }\n throw err;\n }\n if (!assetManifest) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_MISSING), {\n failureKind: PLATFORM_STATIC_ASSET_MISSING,\n });\n }\n // Manifest keys are decoded on-disk paths, but `pathname` stays\n // percent-encoded. Try the raw key, then the decoded key (e.g. a\n // hashed file named `oxc masthead.riv` requested as `oxc%20masthead.riv`).\n let assetPath = pathname;\n let hash = assetManifest[pathname];\n if (!hash) {\n const decoded = safeDecodePathname(pathname);\n if (decoded !== pathname && assetManifest[decoded]) {\n assetPath = decoded;\n hash = assetManifest[decoded];\n }\n }\n let response: Response;\n if (hash) {\n try {\n const assetResponse = await fetchStaticAsset(\n env,\n hash,\n assetPath,\n routing.projectId,\n routing.staticDeploymentId,\n remainingTimeoutBudget(staticAssetStartedAt, timeoutMs),\n );\n if (!assetResponse) {\n logStaticAssetMissing(routing, assetPath, hash);\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_MISSING), {\n failureKind: PLATFORM_STATIC_ASSET_MISSING,\n });\n }\n response = assetResponse;\n } catch (err) {\n // No `resolved.notFound` in scope on this hashed-asset branch \u2014 a\n // storage failure is always a real asset read, so fast 503.\n if (err instanceof DispatchTimeoutError) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_TIMEOUT), {\n failureKind: PLATFORM_STATIC_ASSET_TIMEOUT,\n });\n }\n if (err instanceof StaticAssetReadError) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_ERROR), {\n failureKind: PLATFORM_STATIC_ASSET_ERROR,\n });\n }\n throw err;\n }\n } else {\n response = createErrorResponse(request, 404, 'Not Found');\n }\n if (isStaticCacheResponseEligible(response)) {\n const res = new Response(response.body, response);\n res.headers.set('Cache-Control', 'public, max-age=31536000, immutable');\n markSharedCachePolicy(res.headers);\n ctx.waitUntil(cache.put(cacheKey, res.clone()));\n return finalizeAsset(res);\n }\n return finalizeAsset(response);\n }\n try {\n const worker = getWorker(env, routing);\n const wfpAssetStartedAt = Date.now();\n let response = await withTimeout(\n worker.fetch(workerRequest),\n remainingTimeoutBudget(wfpAssetStartedAt, timeoutMs),\n 'static-asset',\n );\n // Safety net for CF asset dedupe poisoning (WC-4511). See\n // meta/design-docs/0066. Detection only triggers on the CF\n // stub's fingerprint; all other responses stream through.\n const fallbackResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname,\n response,\n userAgent: request.headers.get('user-agent'),\n deadline: { startedAt: wfpAssetStartedAt, timeoutMs },\n });\n response = fallbackResult.response;\n const failureKind = fallbackResult.failureKind;\n if (isStaticCacheResponseEligible(response)) {\n const res = new Response(response.body, response);\n res.headers.set('Cache-Control', 'public, max-age=31536000, immutable');\n markSharedCachePolicy(res.headers);\n ctx.waitUntil(cache.put(cacheKey, res.clone()));\n return finalizeAsset(res, failureKind);\n }\n return finalizeAsset(response, failureKind);\n } catch (err) {\n if (err instanceof DispatchTimeoutError) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_TIMEOUT), {\n failureKind: PLATFORM_STATIC_ASSET_TIMEOUT,\n });\n }\n if (err instanceof Error && err.message.includes('Worker exceeded')) {\n return meter(Response.json({ error: 'CPU limit exceeded' }, { status: 429 }));\n }\n throw err;\n }\n }\n }\n\n // ISR: stale-while-revalidate for configured paths\n // Two-layer cache: Edge (per-colo) \u2192 KV \u2192 Worker (render)\n // Pages protocol (X-VoidPages) uses a separate JSON edge cache; HTML uses KV+edge.\n // ISR applies to SSR page paths only. An API route or an asset-extension\n // path that happens to match a catch-all page pattern must render live and\n // never enter the ISR cache \u2014 mirrors the write-back guard (requestType ===\n // 'ssr') below and how meta-frameworks resolve API routes to non-ISR outputs.\n const isSsrPath =\n routing.ssr === true &&\n (routing.type !== 'framework' || isFrameworkDocumentRequest(request)) &&\n isIsrEligiblePath(pathname, routing.pages, routing.revalidate, routing.pathRevalidate);\n if (isSsrPath && (routing.revalidate || routing.pages?.length)) {\n const isrTtl = resolvePageTtl(\n routing.pages,\n routing.revalidate,\n routing.pathRevalidate,\n pathname,\n );\n // Range requests must render LIVE so the origin produces a correct partial\n // response (`206 Partial Content`) for the requested byte range. They must\n // never read the shared ISR entry (a full body for a partial request) nor\n // write it (a truncated 206 that a later full request would then be served),\n // so bail out of the ISR ladder entirely before any cache read or write.\n if (\n isrTtl > 0 &&\n request.method === 'GET' &&\n !request.headers.has('Range') &&\n !shouldBypassIsr(request)\n ) {\n const isPagesRequest = request.headers.has('X-VoidPages');\n const isrDeploymentId = routing.version ?? 'legacy';\n const cache = applicationEdgeCache;\n const isrOriginalUrlVariant = buildFallbackOriginalUrlVariant(\n request.url,\n pathname,\n url.hostname,\n routing,\n originalUrlVariant,\n );\n const cacheKey = isrEdgeCacheKey(request, pathname, isrDeploymentId, isrOriginalUrlVariant);\n const jsonCacheKey = isrEdgeCacheKeyJson(\n request,\n pathname,\n isrDeploymentId,\n isrOriginalUrlVariant,\n );\n sharedIsrEntry = {\n projectId: routing.projectId,\n deploymentId: isrDeploymentId,\n host: url.hostname,\n pathname,\n originalUrl: isrOriginalUrlVariant,\n htmlKey: cacheKey,\n jsonKey: jsonCacheKey,\n };\n\n // Pages protocol: check JSON edge cache, fall through on miss\n if (isPagesRequest) {\n const jsonCached = await cache.match(jsonCacheKey);\n if (jsonCached && hasCurrentSharedCachePolicy(jsonCached)) {\n requestType = 'isr';\n return meter(clientRevalidateResponse(jsonCached));\n }\n if (jsonCached) {\n await cache.delete(jsonCacheKey);\n }\n // Miss \u2014 fall through to general dispatch (worker returns JSON for X-VoidPages)\n } else {\n // HTML path: Edge \u2192 KV \u2192 Worker\n const purgePoisonedIsrEntry = async (): Promise<void> => {\n await deleteSharedIsrEntry(env, sharedIsrEntry!);\n };\n\n // L1: Edge cache (per-colo)\n const edgeCached = await cache.match(cacheKey);\n if (edgeCached && hasCurrentSharedCachePolicy(edgeCached)) {\n requestType = 'isr';\n const repairResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname,\n response: edgeCached,\n userAgent: request.headers.get('user-agent'),\n timeoutMs,\n fallbackPathname: resolveCachedWfpFallbackPathname(pathname, routing, url.hostname),\n });\n if (repairResult.response !== edgeCached) {\n ctx.waitUntil(purgePoisonedIsrEntry());\n return meter(\n repairResult.response.ok\n ? clientRevalidateResponse(repairResult.response)\n : repairResult.response,\n repairResult.failureKind ? { failureKind: repairResult.failureKind } : undefined,\n );\n }\n return meter(clientRevalidateResponse(edgeCached));\n }\n if (edgeCached) {\n await cache.delete(cacheKey);\n }\n\n // L2: KV\n const cached = await readIsrCache(\n env,\n routing.projectId,\n isrDeploymentId,\n url.hostname,\n pathname,\n isrOriginalUrlVariant,\n );\n if (cached) {\n const stale = isStale(cached);\n const cacheResponse = isrCacheResponse(cached, stale);\n const repairResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname,\n response: cacheResponse,\n userAgent: request.headers.get('user-agent'),\n timeoutMs,\n fallbackPathname: resolveCachedWfpFallbackPathname(pathname, routing, url.hostname),\n });\n if (repairResult.response !== cacheResponse) {\n ctx.waitUntil(purgePoisonedIsrEntry());\n requestType = 'isr';\n return meter(\n repairResult.response.ok\n ? clientRevalidateResponse(repairResult.response)\n : repairResult.response,\n repairResult.failureKind ? { failureKind: repairResult.failureKind } : undefined,\n );\n }\n if (stale) {\n const staleCacheResponse = cacheResponse.clone();\n ctx.waitUntil(\n revalidateInBackground(\n env,\n routing,\n workerRequest,\n url.hostname,\n pathname,\n isrTtl,\n cacheKey,\n jsonCacheKey,\n cached.createdAt + cached.ttl * 1000,\n isrOriginalUrlVariant,\n timeoutMs,\n ).then(async (sharedEntryChanged) => {\n if (!sharedEntryChanged) {\n await cache.put(cacheKey, staleCacheResponse);\n }\n }),\n );\n }\n requestType = 'isr';\n if (!stale) {\n ctx.waitUntil(cache.put(cacheKey, cacheResponse.clone()));\n }\n return meter(clientRevalidateResponse(cacheResponse));\n }\n\n // Cache miss: render via worker, cache in background\n requestType = 'isr';\n const worker = getWorker(env, routing);\n const isrWorkerStartedAt = Date.now();\n let workerResponse: Response;\n try {\n workerResponse = await withTimeout(\n worker.fetch(workerRequest),\n remainingTimeoutBudget(isrWorkerStartedAt, timeoutMs, 'dispatch'),\n 'dispatch',\n );\n } catch (error) {\n if (error instanceof DispatchTimeoutError) {\n return meterWorkerTimeout();\n }\n throw error;\n }\n let isWorkerEventStream = isEventStreamResponse(workerResponse);\n let workerResponseFailureKind: FailureKind | undefined;\n const cachePathname = pathname;\n const cacheOriginalUrlVariant = isrOriginalUrlVariant;\n const cacheKeyForWrite = cacheKey;\n const jsonCacheKeyForWrite = jsonCacheKey;\n // The pathname the ISR write is effectively for. A fallback rewrite can\n // turn a page 404 into a 200 from `/api/*` \u2014 a dynamic body that must\n // never be cached under the original page URL. `fallbackResult` is\n // block-scoped below, so capture its post-fallback pathname AND whether a\n // fallback fired here (the write gate needs both, out of that scope).\n let effectiveMissPathname = cachePathname;\n let missFallbackApplied = false;\n if (!isWorkerEventStream) {\n const assetFallbackResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname,\n response: workerResponse,\n userAgent: request.headers.get('user-agent'),\n deadline: { startedAt: isrWorkerStartedAt, timeoutMs },\n });\n workerResponse = assetFallbackResult.response;\n workerResponseFailureKind = assetFallbackResult.failureKind;\n isWorkerEventStream = isEventStreamResponse(workerResponse);\n }\n if (!isWorkerEventStream) {\n let fallbackResult: Awaited<ReturnType<typeof applyWorkerFallbackRules>>;\n try {\n fallbackResult = await applyWorkerFallbackRules({\n response: workerResponse,\n worker,\n dispatchReq: workerRequest,\n routing,\n pathname,\n url,\n originalRequestUrl: request.url,\n originalUrlHeader,\n originalUrlVariant: isrOriginalUrlVariant,\n deadline: { startedAt: isrWorkerStartedAt, timeoutMs },\n });\n } catch (error) {\n if (error instanceof DispatchTimeoutError) {\n return meterWorkerTimeout();\n }\n throw error;\n }\n if (fallbackResult.applied) {\n missFallbackApplied = true;\n effectiveMissPathname = fallbackResult.pathname;\n workerResponse = fallbackResult.response;\n isWorkerEventStream = isEventStreamResponse(workerResponse);\n if (!isWorkerEventStream) {\n const assetFallbackResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname: fallbackResult.pathname,\n response: workerResponse,\n userAgent: request.headers.get('user-agent'),\n deadline: { startedAt: isrWorkerStartedAt, timeoutMs },\n });\n workerResponse = assetFallbackResult.response;\n workerResponseFailureKind = assetFallbackResult.failureKind;\n isWorkerEventStream = isEventStreamResponse(workerResponse);\n }\n }\n }\n if (isWorkerEventStream) {\n return meter(workerResponse);\n }\n const ttl = resolveRevalidateTtl(workerResponse, isrTtl);\n // Only a full 200 may enter the shared full-response cache. `.ok` is\n // 200\u2013299 (INCLUDING 206 Partial Content), which would poison the entry.\n // Also gate on the POST-fallback pathname: a fallback that rewrote the\n // page 404 into a 200 from `/api/*` must never be cached under the\n // original page URL (an `/api` body is per-request dynamic). Never cache\n // a response that DECLARES itself uncacheable via Cache-Control\n // (private/no-store/no-cache). Finally \u2014 the shared-cache-safety gate \u2014\n // when a FALLBACK was APPLIED the render may enter the ORIGINAL page key\n // ONLY when the fallback TARGET is the WINNING EXACT declared literal ISR\n // page AND the render is HTML (see `isFallbackTargetCacheable`). Any other\n // target \u2014 a dotted `text/html` shell (`/account.html`), an undeclared\n // extensionless target (e.g. `/* \u2192 /graphql`), a catch-all/param page\n // match \u2014 is INDISTINGUISHABLE here from a per-user dynamic endpoint, so it\n // is NOT shared-cached (it is still SERVED live). Positive identification \u2014\n // never the mere ABSENCE of an opt-out header \u2014 is required: a\n // user-configured rewrite to a private endpoint must not be able to poison\n // the page key just by omitting Cache-Control.\n if (\n ttl > 0 &&\n workerResponse.status === 200 &&\n (routing.type !== 'framework' || isHtmlResponse(workerResponse)) &&\n !isApiPath(effectiveMissPathname) &&\n !hasSharedCacheOptOut(workerResponse) &&\n (!missFallbackApplied ||\n isFallbackTargetCacheable(\n routing.pages,\n effectiveMissPathname,\n workerResponse,\n routing.pathRevalidate,\n ))\n ) {\n ctx.waitUntil(\n writeIsrCache(\n env,\n routing.projectId,\n isrDeploymentId,\n url.hostname,\n cachePathname,\n workerResponse,\n ttl,\n cacheOriginalUrlVariant,\n ),\n );\n ctx.waitUntil(\n populateJsonEdgeCache(cache, jsonCacheKeyForWrite, workerResponse, ttl, 'MISS'),\n );\n const cacheHeaders = new Headers(workerResponse.headers);\n cacheHeaders.set(\n 'Cache-Control',\n `public, s-maxage=${ttl}, max-age=0, must-revalidate`,\n );\n cacheHeaders.set('x-isr-cache', 'MISS');\n markSharedCachePolicy(cacheHeaders);\n cacheHeaders.delete('x-void-page-data');\n cacheHeaders.delete('set-cookie');\n const cacheResponse = new Response(workerResponse.clone().body, {\n status: workerResponse.status,\n headers: cacheHeaders,\n });\n ctx.waitUntil(cache.put(cacheKeyForWrite, cacheResponse.clone()));\n\n const clientHeaders = new Headers(cacheHeaders);\n clientHeaders.set('Cache-Control', CLIENT_REVALIDATE_CACHE_CONTROL);\n clientHeaders.delete(SHARED_CACHE_POLICY_HEADER);\n const clientResponse = new Response(workerResponse.body, {\n status: workerResponse.status,\n headers: clientHeaders,\n });\n return meter(\n clientResponse,\n workerResponseFailureKind ? { failureKind: workerResponseFailureKind } : undefined,\n );\n }\n if (\n workerResponse.status === 200 &&\n !missFallbackApplied &&\n (ttl === 0 ||\n hasSharedCacheOptOut(workerResponse) ||\n (routing.type === 'framework' && !isHtmlResponse(workerResponse)))\n ) {\n ctx.waitUntil(purgePoisonedIsrEntry());\n }\n return meter(\n workerResponse,\n workerResponseFailureKind ? { failureKind: workerResponseFailureKind } : undefined,\n );\n }\n }\n }\n\n // Edge-cache non-hashed static assets using deploy-versioned cache keys.\n // The same request gate feeds both cache reads and writes. Credentialed,\n // Range, and Pages-protocol requests must reach the worker instead of a\n // shared representation. For SSR deployments, a dotted path is only a\n // candidate when the emitted asset manifest positively identifies it.\n const staticCachePathname = pathname;\n const isStaticCandidate =\n isStaticCacheRequestEligible(request, staticCachePathname, routing) &&\n (await isKnownStaticAssetPath(env, staticCachePathname, routing, timeoutMs));\n\n let staticCacheKey: Request | undefined;\n if (isStaticCandidate) {\n // Project allowlisted query params into the key so a dynamic extensioned\n // route whose body depends on the query (e.g. an image/badge endpoint that\n // declares `queryAllowlist`) caches per-variant instead of collapsing to the\n // first render. Only EXACT (wildcard-free) allowlist patterns opt in: this\n // static-candidate cache has no per-path variant cap (unlike ISR), so a broad\n // `*` / prefix-wildcard entry here could let a cache-buster query fan out\n // true static assets. `buildVariantOriginalUrl` drops the query entirely when\n // no pattern matches, so a route with no exact match keeps its pathname-only\n // key \u2014 unchanged behavior. The allowlist is authored against the user-facing\n // path, so match on the original request pathname (a rewrite above may have\n // reassigned `pathname` to a destination).\n const cacheUrl = new URL(\n buildVariantOriginalUrl(\n request.url,\n new URL(request.url).pathname,\n exactQueryAllowlist(routing.queryAllowlist),\n ),\n );\n cacheUrl.searchParams.set('_v', String(routing.version));\n const candidateCacheKey = new Request(cacheUrl.toString());\n staticCacheKey = candidateCacheKey;\n const staticCache = applicationEdgeCache;\n const cached = await staticCache.match(candidateCacheKey);\n if (cached && isCurrentStaticCacheResponse(cached)) {\n requestType = 'static';\n if (!routing.staticDeploymentId) {\n const repairResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname,\n response: cached,\n userAgent: request.headers.get('user-agent'),\n timeoutMs,\n fallbackPathname: resolveCachedWfpFallbackPathname(pathname, routing, url.hostname),\n });\n if (repairResult.response !== cached) {\n if (isStaticCacheResponseEligible(repairResult.response)) {\n const finalRes = applyHeaderRules(\n repairResult.response,\n repairResult.pathname,\n routing.headerRules,\n );\n const repaired = new Response(finalRes.clone().body, finalRes);\n repaired.headers.set(\n 'Cache-Control',\n 'public, s-maxage=31536000, max-age=0, must-revalidate',\n );\n markSharedCachePolicy(repaired.headers);\n const repairedForCache = repaired.clone();\n ctx.waitUntil(\n staticCache\n .delete(candidateCacheKey)\n .then(() => staticCache.put(candidateCacheKey, repairedForCache)),\n );\n return meter(clientRevalidateResponse(finalRes));\n }\n ctx.waitUntil(staticCache.delete(candidateCacheKey));\n return meter(\n repairResult.response,\n repairResult.failureKind ? { failureKind: repairResult.failureKind } : undefined,\n );\n }\n }\n return meter(clientRevalidateResponse(cached));\n }\n if (cached) {\n // Entries written by older dispatch versions may contain an unverified\n // dynamic response. Do not serve it, and remove it opportunistically.\n await staticCache.delete(candidateCacheKey);\n }\n }\n\n // KV/R2-backed static serving \u2014 no WfP worker needed\n if (routing.staticDeploymentId) {\n const staticAssetStartedAt = Date.now();\n let assetManifest: Record<string, string> | null;\n try {\n assetManifest = await fetchAssetManifest(\n env,\n routing.staticDeploymentId,\n routing.projectId,\n remainingTimeoutBudget(staticAssetStartedAt, timeoutMs),\n );\n } catch (err) {\n if (err instanceof DispatchTimeoutError) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_TIMEOUT), {\n failureKind: PLATFORM_STATIC_ASSET_TIMEOUT,\n });\n }\n if (err instanceof StaticAssetReadError) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_ERROR), {\n failureKind: PLATFORM_STATIC_ASSET_ERROR,\n });\n }\n throw err;\n }\n if (!assetManifest) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_MISSING), {\n failureKind: PLATFORM_STATIC_ASSET_MISSING,\n });\n }\n const assetConfig: AssetConfig = routing.assetConfig ?? {};\n\n // Capture pathname before the fallback rewrite potentially mutates it.\n // The edge cache must be keyed on the path seen here (what the client\n // requested, post any pre-asset rewrites), not the rewrite target \u2014\n // otherwise future requests to this path miss the cache entry.\n const fallbackOriginPathname = pathname;\n let resolved = resolveStaticPath(pathname, assetManifest, assetConfig);\n\n // Fallback rules \u2014 fire only when nothing matched in static resolution.\n // Single-pass: re-resolve with rewritten path, no further fallbacks.\n // `fallbackRules` are status-200-only (enforced at API ingest), so\n // `applyRoutingRules` only ever yields `type: 'rewrite'` here.\n if (!resolved && routing.fallbackRules?.length) {\n const fallback = applyRoutingRules(pathname, routing.fallbackRules, url.hostname);\n if (fallback?.type === 'rewrite') {\n // Same trust model as the redirectRules rewrite above \u2014 framework +\n // API both validate destination shape before the manifest lands here.\n pathname = fallback.destination;\n url.pathname = pathname;\n resolved = resolveStaticPath(pathname, assetManifest, assetConfig);\n }\n }\n\n if (!resolved) {\n return meter(createErrorResponse(request, 404, 'Not Found'));\n }\n\n if (resolved.redirect) {\n return meter(\n new Response(null, {\n status: 308,\n headers: { Location: resolved.redirect },\n }),\n );\n }\n\n let assetResponse: Response | null;\n try {\n assetResponse = await fetchStaticAsset(\n env,\n resolved.hash,\n resolved.path,\n routing.projectId,\n routing.staticDeploymentId,\n remainingTimeoutBudget(staticAssetStartedAt, timeoutMs),\n );\n } catch (err) {\n // A stalled read of the not-found asset was always going to 404, so\n // return a fast 404 (must not trip the 5xx alert); a real asset read\n // that stalled \u2192 fast 503.\n if (err instanceof DispatchTimeoutError) {\n return meter(\n timeoutResponse(resolved.notFound ? 404 : 503, 'static-asset'),\n resolved.notFound ? undefined : { failureKind: PLATFORM_STATIC_ASSET_TIMEOUT },\n );\n }\n if (err instanceof StaticAssetReadError) {\n return meter(\n resolved.notFound\n ? createErrorResponse(request, 404, 'Not Found')\n : staticAssetFailureResponse(PLATFORM_STATIC_ASSET_ERROR),\n resolved.notFound ? undefined : { failureKind: PLATFORM_STATIC_ASSET_ERROR },\n );\n }\n throw err;\n }\n if (!assetResponse) {\n if (resolved.notFound) {\n return meter(createErrorResponse(request, 404, 'Not Found'));\n }\n logStaticAssetMissing(routing, resolved.path, resolved.hash);\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_MISSING), {\n failureKind: PLATFORM_STATIC_ASSET_MISSING,\n });\n }\n\n const status = resolved.notFound ? 404 : 200;\n const response = new Response(assetResponse.body, {\n status,\n headers: assetResponse.headers,\n });\n const finalRes = applyHeaderRules(response, pathname, routing.headerRules);\n\n // Populate edge cache (same pattern as existing deploy-versioned static cache).\n // Key on the ORIGINAL pathname the client requested, not the post-fallback\n // rewrite target \u2014 otherwise future requests to the original path miss.\n const edgeCacheKey =\n staticCacheKey ??\n (isSharedStaticCacheRequestEligible(request)\n ? new Request(`${url.origin}${fallbackOriginPathname}?_v=${routing.staticDeploymentId}`)\n : undefined);\n if (edgeCacheKey && isStaticCacheResponseEligible(finalRes)) {\n const cached = new Response(finalRes.clone().body, finalRes);\n cached.headers.set(\n 'Cache-Control',\n 'public, s-maxage=31536000, max-age=0, must-revalidate',\n );\n markSharedCachePolicy(cached.headers);\n ctx.waitUntil(applicationEdgeCache.put(edgeCacheKey, cached.clone()));\n }\n\n return meter(clientRevalidateResponse(finalRes));\n }\n\n // Dispatch to user worker \u2014 CF handles static assets transparently\n const worker = getWorker(env, routing);\n try {\n let dispatchReq = workerRequest;\n if (dispatchReq.bodyUsed) {\n dispatchReq = rebuildRequest(dispatchReq, dispatchReq.url, () => {});\n }\n // If a worker-backed fallbackRule could fire on a 404, the inner\n // re-dispatch needs the original body \u2014 but `worker.fetch` consumes\n // the body stream and `rebuildRequest` on a `bodyUsed` request drops\n // it (silently). Clone here so the fallback path has a replayable\n // copy. `Request.clone()` tees the stream on CF Workers. Skip the\n // clone when there are no fallback rules or the method has no body\n // (GET/HEAD) \u2014 the common case stays free.\n const hasBodyMethod = dispatchReq.method !== 'GET' && dispatchReq.method !== 'HEAD';\n const dispatchReqForFallback =\n hasBodyMethod && routing.fallbackRules?.length ? dispatchReq.clone() : dispatchReq;\n const workerDispatchStartedAt = Date.now();\n let response = await withTimeout(\n worker.fetch(dispatchReq),\n remainingTimeoutBudget(workerDispatchStartedAt, timeoutMs, 'dispatch'),\n 'dispatch',\n );\n let isEventStream = isEventStreamResponse(response);\n let responseFailureKind: FailureKind | undefined;\n\n // Safety net for CF asset dedupe poisoning (WC-4511). See\n // meta/design-docs/0066. Pre-check gates body read so non-asset\n // responses stream through untouched.\n if (!isEventStream) {\n const assetFallbackResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname,\n response,\n userAgent: request.headers.get('user-agent'),\n deadline: { startedAt: workerDispatchStartedAt, timeoutMs },\n });\n response = assetFallbackResult.response;\n responseFailureKind = assetFallbackResult.failureKind;\n isEventStream = isEventStreamResponse(response);\n }\n\n // routing.fallbackRules \u2014 for static deployments these fire post-asset\n // (line ~533). The user worker is the equivalent path resolver here, so\n // a 404 is the analogue of a static-asset miss. Single-pass: the\n // rewrite target's response is returned as-is even if it's also 404.\n //\n // `fallbackResult` is block-scoped below, but the ISR write-back gate\n // needs to know whether a fallback fired (the fallback-target positive-ID\n // check). Hoist the flag out here \u2014 mirrors the miss-write's\n // `missFallbackApplied`.\n let writebackFallbackApplied = false;\n if (!isEventStream) {\n const fallbackResult = await applyWorkerFallbackRules({\n response,\n worker,\n dispatchReq: dispatchReqForFallback,\n routing,\n pathname,\n url,\n originalRequestUrl: request.url,\n originalUrlHeader,\n originalUrlVariant,\n deadline: { startedAt: workerDispatchStartedAt, timeoutMs },\n });\n if (fallbackResult.applied) {\n writebackFallbackApplied = true;\n pathname = fallbackResult.pathname;\n url.pathname = pathname;\n originalUrlVariant = fallbackResult.originalUrlVariant;\n response = fallbackResult.response;\n isEventStream = isEventStreamResponse(response);\n if (!isEventStream) {\n const assetFallbackResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname,\n response,\n userAgent: request.headers.get('user-agent'),\n deadline: { startedAt: workerDispatchStartedAt, timeoutMs },\n });\n response = assetFallbackResult.response;\n responseFailureKind = assetFallbackResult.failureKind;\n isEventStream = isEventStreamResponse(response);\n }\n }\n }\n\n if (\n sharedIsrEntry &&\n response.status === 200 &&\n !writebackFallbackApplied &&\n (resolveRevalidateTtl(\n response,\n resolvePageTtl(\n routing.pages,\n routing.revalidate,\n routing.pathRevalidate,\n sharedIsrEntry.pathname,\n ),\n ) === 0 ||\n hasSharedCacheOptOut(response) ||\n (routing.type === 'framework' && !isHtmlResponse(response)))\n ) {\n ctx.waitUntil(deleteSharedIsrEntry(env, sharedIsrEntry));\n }\n\n // Cache static asset at edge if eligible. Require a full 200 \u2014 `.ok` is\n // 200\u2013299 and would admit a `206 Partial Content` (a Range request to a\n // dotted SSR path skips the ISR ladder and falls through here), poisoning\n // the shared `<path>?_v=` key with a partial body that a later full request\n // could then be served. Mirrors the `status === 200` guard at the ISR sites.\n if (staticCacheKey && !writebackFallbackApplied && isStaticCacheResponseEligible(response)) {\n const res = new Response(response.body, response);\n res.headers.delete('x-void-page-data');\n const finalRes = applyHeaderRules(res, pathname, routing.headerRules);\n const cacheRes = new Response(finalRes.clone().body, finalRes);\n cacheRes.headers.set(\n 'Cache-Control',\n 'public, s-maxage=31536000, max-age=0, must-revalidate',\n );\n markSharedCachePolicy(cacheRes.headers);\n ctx.waitUntil(applicationEdgeCache.put(staticCacheKey, cacheRes.clone()));\n return meter(\n clientRevalidateResponse(finalRes),\n responseFailureKind ? { failureKind: responseFailureKind } : undefined,\n );\n }\n\n // Classify for metering\n const dynamicType = classifyDynamicRequestType(pathname, routing.ssr);\n if (dynamicType) {\n requestType = dynamicType;\n }\n\n // Write ISR cache on miss \u2014 skip pages protocol responses (JSON, not HTML)\n // Guard: only cache GET requests without credentials, and respect worker x-revalidate\n // Range requests are excluded here too: a partial (206) response must never\n // be written into the shared full-response ISR cache. Mirrors the ISR-ladder\n // guard above.\n if (\n (routing.revalidate || routing.pages?.length) &&\n !isEventStream &&\n !request.headers.has('X-VoidPages') &&\n request.method === 'GET' &&\n !request.headers.has('Range') &&\n (routing.type !== 'framework' || isFrameworkDocumentRequest(request)) &&\n !shouldBypassIsr(request)\n ) {\n const configTtl = resolvePageTtl(\n routing.pages,\n routing.revalidate,\n routing.pathRevalidate,\n pathname,\n );\n // Config TTL is the gatekeeper \u2014 worker x-revalidate can reduce but not enable ISR\n const isrTtl = configTtl > 0 ? resolveRevalidateTtl(response, configTtl) : 0;\n // Only a full 200 is cacheable \u2014 `.ok` (200\u2013299) would let a 206 poison the entry.\n // `requestType` was reclassified above from the POST-fallback pathname, so\n // `=== 'ssr'` already skips a fallback that rewrote to `/api` \u2014 the same\n // `/api` exclusion the miss-write and background-revalidation sites spell out\n // with `!isApiPath(effective\u2026)`. (This SSR-path gate is stricter than those two:\n // it also skips extension targets, but requests reaching this branch are not\n // the ssr+revalidate ISR-ladder path where SPA `/index.html` fallbacks cache.)\n //\n // Fallback positive-ID gate \u2014 the same one the miss-write and background sites\n // enforce: when a FALLBACK rewrote this request, the render may enter the shared\n // cache under the fallback TARGET key ONLY when that target is a positively\n // identified declared literal ISR page rendering HTML (`isFallbackTargetCacheable`).\n // A non-fallback SSR render is unaffected. This makes all three ISR write sites\n // apply identical fallback policy: a rewrite to an undeclared dynamic target\n // (e.g. `/api/* \u2192 /graphql`) is served LIVE but never shared-cached, even when it\n // omits a Cache-Control opt-out. (Without this, such a write is unreadable \u2014\n // keyed `<target>#rw=hash(<original non-ISR-eligible path>)`, which no later\n // request recomputes \u2014 but it is still a wasted KV write and a defense-in-depth\n // gap, so the gate is correct as both consistency and hardening.)\n if (\n isrTtl > 0 &&\n response.status === 200 &&\n requestType === 'ssr' &&\n (routing.type !== 'framework' || isHtmlResponse(response)) &&\n !hasSharedCacheOptOut(response) &&\n (!writebackFallbackApplied ||\n isFallbackTargetCacheable(routing.pages, pathname, response, routing.pathRevalidate))\n ) {\n const isrDeploymentId = routing.version ?? 'legacy';\n ctx.waitUntil(\n writeIsrCache(\n env,\n routing.projectId,\n isrDeploymentId,\n url.hostname,\n pathname,\n response,\n isrTtl,\n originalUrlVariant,\n ),\n );\n const jsonCacheKey = isrEdgeCacheKeyJson(\n request,\n pathname,\n isrDeploymentId,\n originalUrlVariant,\n );\n ctx.waitUntil(\n populateJsonEdgeCache(applicationEdgeCache, jsonCacheKey, response, isrTtl, 'MISS'),\n );\n }\n }\n\n // Strip internal header before returning to client\n if (response.headers.has('x-void-page-data')) {\n const stripped = new Response(response.body, response);\n stripped.headers.delete('x-void-page-data');\n return meter(\n applyHeaderRules(stripped, pathname, routing.headerRules),\n responseFailureKind ? { failureKind: responseFailureKind } : undefined,\n );\n }\n return meter(\n applyHeaderRules(response, pathname, routing.headerRules),\n responseFailureKind ? { failureKind: responseFailureKind } : undefined,\n );\n } catch (err) {\n if (err instanceof DispatchTimeoutError) {\n if (err.label === 'static-asset') {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_TIMEOUT), {\n failureKind: PLATFORM_STATIC_ASSET_TIMEOUT,\n });\n }\n const dynamicType = classifyDynamicRequestType(pathname, routing.ssr);\n if (dynamicType) {\n requestType = dynamicType;\n }\n return meterWorkerTimeout();\n }\n if (err instanceof StaticAssetReadError) {\n return meter(staticAssetFailureResponse(PLATFORM_STATIC_ASSET_ERROR), {\n failureKind: PLATFORM_STATIC_ASSET_ERROR,\n });\n }\n if (err instanceof Error && err.message.includes('Worker exceeded')) {\n return meter(Response.json({ error: 'CPU limit exceeded' }, { status: 429 }));\n }\n throw err;\n }\n },\n\n async queue(batch: MessageBatch, env: Env): Promise<void> {\n if (\n env.PLATFORM_TRAFFIC_STATE === 'staging' ||\n env.PLATFORM_TRAFFIC_STATE === 'sandbox-drain'\n ) {\n console.warn(\n `[queue-relay] platform traffic is staging; retrying queue=\"${batch.queue}\" in ${PLATFORM_QUEUE_RETRY_DELAY_SECONDS}s`,\n );\n batch.retryAll({ delaySeconds: PLATFORM_QUEUE_RETRY_DELAY_SECONDS });\n return;\n }\n if (env.PLATFORM_INSTALLATION_ID) {\n let disabled: string | null;\n try {\n disabled = await env.ROUTING.get(PLATFORM_DISABLED_KEY);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(\n `[queue-relay] platform traffic gate read failed; retrying queue=\"${batch.queue}\" in ${PLATFORM_QUEUE_RETRY_DELAY_SECONDS}s error=${JSON.stringify(message)}`,\n );\n batch.retryAll({ delaySeconds: PLATFORM_QUEUE_RETRY_DELAY_SECONDS });\n return;\n }\n if (disabled === PLATFORM_DISABLED_VALUE) {\n console.warn(\n `[queue-relay] platform traffic is disabled; retrying queue=\"${batch.queue}\" in ${PLATFORM_QUEUE_RETRY_DELAY_SECONDS}s`,\n );\n batch.retryAll({ delaySeconds: PLATFORM_QUEUE_RETRY_DELAY_SECONDS });\n return;\n }\n }\n\n // Look up which user worker handles this queue\n const routingRaw = await env.ROUTING.get(`queue:${batch.queue}`, { cacheTtl: 60 });\n if (!routingRaw) {\n console.error(\n `[queue-relay] missing routing entry for queue=\"${batch.queue}\"; retrying all messages`,\n );\n batch.retryAll();\n return;\n }\n const { workerName, queueName, proxyToken } = JSON.parse(routingRaw) as QueueRoutingEntry;\n\n // Serialize batch for relay\n const messages = Array.from(batch.messages, (message) => ({\n id: message.id,\n timestamp: message.timestamp.toISOString(),\n body: message.body,\n attempts: message.attempts,\n }));\n\n const worker = env.DISPATCH.get(workerName);\n try {\n const body = JSON.stringify({ queue: queueName, messages });\n const queueHeaders: Record<string, string> = { 'Content-Type': 'application/json' };\n if (proxyToken) {\n queueHeaders['x-void-internal'] = proxyToken;\n }\n let res = await worker.fetch(\n new Request('https://internal/__void/queue', {\n method: 'POST',\n headers: queueHeaders,\n body,\n }),\n );\n // Legacy: fall back for workers deployed before the /__void/ migration.\n // TODO: remove once all deployed workers use /__void/* paths.\n if (res.status === 404) {\n res = await worker.fetch(\n new Request('https://internal/__queue', {\n method: 'POST',\n headers: queueHeaders,\n body,\n }),\n );\n }\n\n if (!res.ok) {\n // Preserve observability: dispatch tail ingests this under the\n // __platform-dispatch project key so operators can query who is\n // rejecting relays and why.\n let snippet = '';\n try {\n snippet = (await res.clone().text()).slice(0, 200);\n } catch {\n /* body may be unreadable \u2014 status alone is still useful */\n }\n console.error(\n `[queue-relay] relay failed queue=\"${queueName}\" worker=\"${workerName}\" status=${res.status} body=${JSON.stringify(snippet)}`,\n );\n batch.retryAll();\n return;\n }\n\n let result: {\n ok?: boolean;\n decisions?: Record<string, { action: string; delaySeconds?: number }>;\n };\n try {\n result = await res.json();\n } catch {\n // Non-JSON 2xx = legacy framework, treat as success\n batch.ackAll();\n return;\n }\n\n if (!result.decisions) {\n // No decisions = legacy protocol, batch fallback\n if (result.ok !== false) {\n batch.ackAll();\n } else {\n batch.retryAll();\n }\n return;\n }\n\n // Apply per-message decisions\n const messageMap = new Map(batch.messages.map((message) => [message.id, message]));\n for (const [id, decision] of Object.entries(result.decisions)) {\n const cfMessage = messageMap.get(id);\n if (!cfMessage) {\n continue;\n }\n if (decision.action === 'ack') {\n cfMessage.ack();\n } else if (decision.action === 'retry') {\n cfMessage.retry(\n decision.delaySeconds != null ? { delaySeconds: decision.delaySeconds } : undefined,\n );\n }\n }\n\n // Undecided messages: if handler failed, retry all (individual decisions survive per CF)\n if (result.ok === false) {\n batch.retryAll();\n }\n // If ok=true, undecided messages get implicit ack (CF default on successful consumer return)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(\n `[queue-relay] relay threw queue=\"${queueName}\" worker=\"${workerName}\" error=${JSON.stringify(msg)}`,\n );\n batch.retryAll();\n }\n },\n} satisfies ExportedHandler<Env>;\n\nclass StaticAssetReadError extends Error {\n constructor(cause: unknown) {\n super('Static asset storage read failed', { cause });\n this.name = 'StaticAssetReadError';\n }\n}\n\nfunction logStaticAssetMissing(routing: RoutingEntry, pathname: string, hash: string): void {\n console.error(\n JSON.stringify({\n event: 'static-asset-missing',\n store: hash.startsWith('!') ? 'r2' : 'kv',\n projectId: routing.projectId,\n deploymentId: routing.staticDeploymentId ?? routing.assetManifestId,\n pathname,\n ts: Date.now(),\n }),\n );\n}\n\n/**\n * Fetch a static asset from KV (legacy small files) or R2 (`!`-prefixed modern\n * direct uploads and legacy large files).\n *\n * The complete scoped\u2192legacy sequence gets one delayed hedge and one absolute\n * timeout. Hedging the sequence (rather than each binding result) means a KV\n * `{ value: null }` miss has the same semantics as an R2 `null` miss.\n *\n * Each sequence tries the project-scoped key first\n * (`assets/{projectId}/{hash}`), then the legacy shared key (`assets/{hash}`)\n * for backward compatibility with deployments created before asset key\n * scoping.\n * Returns null if the asset is not found.\n */\nasync function fetchStaticAsset(\n env: Env,\n hash: string,\n path: string,\n projectId?: string,\n deploymentId?: string,\n timeoutMs = 10000,\n): Promise<Response | null> {\n const hedgeDelayMs =\n timeoutMs > 0 && Number.isFinite(timeoutMs)\n ? Math.min(STATIC_ASSET_HEDGE_DELAY_MS, timeoutMs / 2)\n : 0;\n const startedAt = Date.now();\n let hedged = false;\n\n try {\n const result = await withDelayedHedge(() => fetchStaticAssetOnce(env, hash, path, projectId), {\n delayMs: hedgeDelayMs,\n timeoutMs,\n label: 'static-asset',\n discard: async (late) => {\n await late.body?.cancel();\n },\n onHedge: () => {\n hedged = true;\n console.warn(\n JSON.stringify({\n event: 'static-asset-read-hedge',\n store: hash.startsWith('!') ? 'r2' : 'kv',\n projectId,\n deploymentId,\n pathname: path,\n delayMs: hedgeDelayMs,\n ts: Date.now(),\n }),\n );\n },\n });\n\n if (hedged) {\n console.warn(\n JSON.stringify({\n event: 'static-asset-read-hedge-result',\n store: hash.startsWith('!') ? 'r2' : 'kv',\n projectId,\n deploymentId,\n pathname: path,\n outcome: result === null ? 'miss' : 'hit',\n elapsedMs: Date.now() - startedAt,\n ts: Date.now(),\n }),\n );\n }\n return result;\n } catch (error) {\n console.error(\n JSON.stringify({\n event:\n error instanceof DispatchTimeoutError\n ? 'static-asset-timeout'\n : 'static-asset-read-error',\n store: hash.startsWith('!') ? 'r2' : 'kv',\n projectId,\n deploymentId,\n pathname: path,\n hedged,\n elapsedMs: Date.now() - startedAt,\n error:\n error instanceof DispatchTimeoutError\n ? undefined\n : error instanceof Error\n ? error.message\n : String(error),\n ts: Date.now(),\n }),\n );\n if (error instanceof DispatchTimeoutError) {\n throw error;\n }\n throw new StaticAssetReadError(error);\n }\n}\n\nasync function fetchStaticAssetOnce(\n env: Env,\n hash: string,\n path: string,\n projectId?: string,\n): Promise<Response | null> {\n const isLarge = hash.startsWith('!');\n const cleanHash = isLarge ? hash.slice(1) : hash;\n const scopedKey = projectId ? `assets/${projectId}/${cleanHash}` : null;\n const legacyKey = `assets/${cleanHash}`;\n\n if (isLarge) {\n // Try scoped key first, then legacy\n const obj = scopedKey\n ? ((await env.STATIC_ASSETS_R2.get(scopedKey)) ?? (await env.STATIC_ASSETS_R2.get(legacyKey)))\n : await env.STATIC_ASSETS_R2.get(legacyKey);\n if (!obj) {\n return null;\n }\n const contentType = resolveAssetContentType(obj.httpMetadata?.contentType, path);\n const headers: HeadersInit = {\n ETag: obj.httpEtag,\n ...(obj.size ? { 'Content-Length': String(obj.size) } : {}),\n };\n if (contentType) {\n (headers as Record<string, string>)['Content-Type'] = contentType;\n }\n return new Response(obj.body, { headers });\n }\n\n // Try scoped key first, then legacy\n if (scopedKey) {\n const scoped = await env.STATIC_ASSETS.getWithMetadata<{ ct: string }>(scopedKey, {\n type: 'arrayBuffer',\n cacheTtl: 86400,\n });\n if (scoped.value) {\n const contentType = resolveAssetContentType(scoped.metadata?.ct, path);\n const headers: HeadersInit = {\n 'Content-Length': String((scoped.value as ArrayBuffer).byteLength),\n };\n if (contentType) {\n (headers as Record<string, string>)['Content-Type'] = contentType;\n }\n return new Response(scoped.value, { headers });\n }\n }\n\n const { value, metadata } = await env.STATIC_ASSETS.getWithMetadata<{ ct: string }>(legacyKey, {\n type: 'arrayBuffer',\n cacheTtl: 86400,\n });\n if (!value) {\n return null;\n }\n const contentType = resolveAssetContentType(metadata?.ct, path);\n const headers: HeadersInit = {\n 'Content-Length': String((value as ArrayBuffer).byteLength),\n };\n if (contentType) {\n (headers as Record<string, string>)['Content-Type'] = contentType;\n }\n return new Response(value, { headers });\n}\n\n/** Get a dispatch worker, applying custom limits if configured. */\nfunction getWorker(env: Env, routing: RoutingEntry): Fetcher {\n if (routing.limits) {\n return env.DISPATCH.get(routing.workerName, {}, { limits: routing.limits });\n }\n return env.DISPATCH.get(routing.workerName);\n}\n\n/**\n * Revalidate an ISR page in the background.\n * Dispatches to the user worker (always as HTML, no X-VoidPages), writes HTML\n * to KV + HTML edge cache, and populates JSON edge cache from embedded page data.\n * Errors are caught and logged \u2014 serve stale, don't retry.\n */\nasync function revalidateInBackground(\n env: Env,\n routing: RoutingEntry,\n request: Request,\n host: string,\n pathname: string,\n defaultTtl: number,\n cacheKey: Request,\n jsonCacheKey: Request,\n staleSinceMs: number,\n originalUrl?: string | null,\n timeoutMs = 10000,\n): Promise<boolean> {\n try {\n const worker = getWorker(env, routing);\n const revalidationStartedAt = Date.now();\n // Strip X-VoidPages so the worker always returns HTML.\n // Use rebuildRequest so request.cf (country/colo/botManagement/tlsClientAuth)\n // survives the rebuild \u2014 otherwise the background re-render runs with\n // cf === undefined and writes wrong-geo/wrong-bot HTML into the ISR cache.\n const cleanRequest = rebuildRequest(request, request.url, (headers) =>\n headers.delete('X-VoidPages'),\n );\n let response = await withTimeout(\n worker.fetch(cleanRequest),\n remainingTimeoutBudget(revalidationStartedAt, timeoutMs, 'dispatch'),\n 'dispatch',\n );\n if (isEventStreamResponse(response)) {\n return false;\n }\n // Capture the ORIGIN page's OWN pre-fallback status. Only a genuine removal\n // signal (404/410 Gone) may later drive grace-eviction; a transient 5xx / 429 /\n // timeout must PRESERVE the stale entry (stale-while-revalidate). Read it here,\n // before `applyWorkerFallbackRules` reassigns `response` to a fallback target.\n const originalStatus = response.status;\n const fallbackResult = await applyWorkerFallbackRules({\n response,\n worker,\n dispatchReq: cleanRequest,\n routing,\n pathname,\n url: new URL(cleanRequest.url),\n originalRequestUrl: request.url,\n originalUrlHeader: request.headers.get('X-Void-Original-URL') ?? undefined,\n originalUrlVariant: originalUrl ?? undefined,\n deadline: { startedAt: revalidationStartedAt, timeoutMs },\n });\n response = fallbackResult.response;\n if (isEventStreamResponse(response)) {\n return false;\n }\n const assetFallbackResult = await maybeServeWfpAssetFallback({\n env,\n routing,\n pathname: fallbackResult.pathname,\n response,\n userAgent: request.headers.get('user-agent'),\n deadline: { startedAt: revalidationStartedAt, timeoutMs },\n });\n response = assetFallbackResult.response;\n if (isEventStreamResponse(response)) {\n return false;\n }\n const ttl = resolveRevalidateTtl(response, defaultTtl);\n const cache = applicationEdgeCache;\n // Evict every shared representation of this entry: KV + HTML edge + JSON edge.\n const evictSharedEntry = async () => {\n await deleteIsrCache(\n env,\n routing.projectId,\n routing.version ?? 'legacy',\n host,\n pathname,\n originalUrl,\n );\n await cache.delete(cacheKey);\n await cache.delete(jsonCacheKey);\n };\n // The pathname this background re-render effectively resolved to. A fallback\n // rewrite (page 404 \u2192 200 from `/api/*`) must not overwrite the page's ISR\n // entry with a dynamic API body \u2014 same guard as the miss-write.\n const effectiveBgPathname = fallbackResult.applied ? fallbackResult.pathname : pathname;\n // Only a full 200 may refresh the shared cache \u2014 a background re-render that\n // returns 206/etc. (`.ok` is 200\u2013299) must not overwrite the good entry.\n // A re-render that falls back to `/api/*` must not overwrite the page's entry\n // with a dynamic API body. And \u2014 the shared-cache-safety gate mirrored from the\n // miss-write \u2014 when a FALLBACK was APPLIED the re-render may refresh the ORIGINAL\n // page key ONLY when its TARGET is the winning EXACT declared literal ISR page\n // and the render is HTML; any other target (a dotted shell, an undeclared\n // extensionless `/graphql`) is not shared-cached and must not overwrite the entry.\n if (\n ttl > 0 &&\n response.status === 200 &&\n (routing.type !== 'framework' || isHtmlResponse(response)) &&\n !isApiPath(effectiveBgPathname) &&\n !hasSharedCacheOptOut(response) &&\n (!fallbackResult.applied ||\n isFallbackTargetCacheable(\n routing.pages,\n effectiveBgPathname,\n response,\n routing.pathRevalidate,\n ))\n ) {\n await writeIsrCache(\n env,\n routing.projectId,\n routing.version ?? 'legacy',\n host,\n pathname,\n response,\n ttl,\n originalUrl,\n );\n // Update HTML edge cache with fresh response\n const headers = new Headers(response.headers);\n headers.set('x-isr-cache', 'HIT');\n headers.set('Cache-Control', `public, s-maxage=${ttl}, max-age=0, must-revalidate`);\n markSharedCachePolicy(headers);\n headers.delete('set-cookie');\n headers.delete('x-void-page-data');\n await cache.put(\n cacheKey,\n new Response(response.clone().body, {\n status: response.status,\n headers,\n }),\n );\n await populateJsonEdgeCache(cache, jsonCacheKey, response, ttl, 'HIT');\n return true;\n } else if (\n response.status === 200 &&\n !isApiPath(effectiveBgPathname) &&\n !fallbackResult.applied &&\n (ttl === 0 ||\n hasSharedCacheOptOut(response) ||\n (routing.type === 'framework' && !isHtmlResponse(response)))\n ) {\n // Evict the stale shared entry ONLY on an AUTHORITATIVE opt-out render of the\n // ORIGIN page itself: a successful render (200, NOT an `/api/*` fallback, and\n // NOT ANY applied fallback) that has withdrawn its public representation \u2014\n // either a permanent `x-revalidate: 0` opt-out OR a `Cache-Control` opt-out\n // (private/no-store/no-cache). A FALLBACK firing means the ORIGIN page 404'd\n // (often transiently \u2014 deploy race); the fallback TARGET's cache intent must\n // NOT delete the origin page's last-known-good entry, so `!fallbackResult.applied`\n // gates eviction to an authoritative render of the origin page. A transient\n // non-200 (even one carrying `x-revalidate: 0`) likewise must NOT evict \u2014 keep\n // serving the last known-good entry (stale-while-revalidate resilience). The\n // write gate already refuses to cache non-authoritative content, so eviction\n // must mirror it. Removes KV + HTML + JSON edge.\n try {\n await evictSharedEntry();\n } catch (error) {\n console.error('ISR privacy eviction failed:', error);\n }\n return true;\n } else if (\n (originalStatus === 404 || originalStatus === 410) &&\n Date.now() - staleSinceMs > ISR_STALE_EVICT_GRACE_SECONDS * 1000\n ) {\n // Convergence \u2014 ONLY on positive removal evidence: the ORIGIN page's OWN\n // pre-fallback render returned 404 or 410 (gone). Such a re-render could neither\n // refresh this entry nor trigger the authoritative opt-out eviction above (a\n // permanent origin 404 that falls back to a non-declared shell \u2014 C12 refuses to\n // cache it). It has now been STALE (since `createdAt + ttl`) beyond the bounded\n // grace \u2014 far past any transient deploy-race 404 \u2014 so the page is permanently\n // removed: evict it rather than serve its last cached body forever. A 5xx / 429 /\n // timeout / any other status is a DEGRADED DEPENDENCY, not a removal \u2014 it MUST\n // keep serving stale (stale-while-revalidate is exactly what protects that\n // request), so it never reaches this branch. Measuring from stale-onset (not\n // creation) means a long-TTL entry still gets the full grace and a transient\n // failure right after expiry keeps serving stale within the grace.\n try {\n await evictSharedEntry();\n } catch (error) {\n console.error('ISR stale-entry eviction failed:', error);\n }\n return true;\n }\n return false;\n } catch (err) {\n console.error('ISR revalidation failed:', err);\n return false;\n }\n}\n\n// An `/api` route (worker-dynamic). Such a path must never enter the shared\n// page ISR cache \u2014 directly, or via a fallback that rewrites a page 404 into a\n// 200 from `/api/*`. A `/api` response is per-request dynamic (cookies, auth,\n// live data); caching it under a page URL would serve one caller's response to\n// everyone. Used at every ISR write site on the effective post-fallback path.\nfunction isApiPath(pathname: string): boolean {\n return pathname === '/api' || pathname.startsWith('/api/');\n}\n\n// ISR eligibility for a REQUEST's own pathname: SSR page paths only \u2014 never an\n// `/api` route. A dotted path is ISR-eligible only when it matches a declared\n// page route that is NOT a broad catch-all \u2014 a literal (`/feed.xml`) or a\n// single-segment param (`/blog/:slug`, so `/blog/release.v2` gets ISR). A broad\n// catch-all (`/:path{.+}`, `*`) that merely happens to match a static asset like\n// `/robots.txt` does NOT make it page-ISR content. This is the read-gate\n// predicate; it deliberately does NOT gate the fallback WRITE sites, which key\n// off the fallback TARGET (see `isFallbackTargetCacheable`).\nfunction isIsrEligiblePath(\n pathname: string,\n pages: ReadonlyArray<{ pattern: string; revalidate?: number }> | undefined,\n revalidate: number | Record<string, number> | undefined,\n pathRevalidate: Record<string, number> | undefined,\n): boolean {\n if (isApiPath(pathname)) {\n return false;\n }\n if (!hasExtension(pathname)) {\n return true;\n }\n return isDottedPathIsrEligible(pages, revalidate, pathRevalidate, pathname);\n}\n\n// A fallback render may enter the shared ORIGINAL page key ONLY when the target is\n// the WINNING EXACT declared literal ISR page AND the render is HTML. There is no\n// safe path-shape signal for a \"static shell\": a dotted `text/html` target\n// (`/account.html`) is indistinguishable here from a dynamic per-user endpoint, so\n// path shape is NOT trusted. A static SPA shell reached via fallback is still\n// SERVED live; it is simply no longer opportunistically ISR-cached under a page key\n// (its cache home is the static-asset path). Full metadata-verified shell caching\n// would need an async asset-manifest lookup this write path does not have.\nfunction isFallbackTargetCacheable(\n pages: ReadonlyArray<{ pattern: string; revalidate?: number }> | undefined,\n targetPathname: string,\n response: Response,\n pathRevalidate: Record<string, number> | undefined,\n): boolean {\n return isHtmlResponse(response) && matchesLiteralPage(pages, targetPathname, pathRevalidate);\n}\n\n/**\n * Every static cache shares one representation across callers, so credentials,\n * EventSource semantics, partial requests, and Pages-protocol requests bypass it.\n */\nfunction isSharedStaticCacheRequestEligible(request: Request): boolean {\n return Boolean(\n request.method === 'GET' &&\n !request.headers.has('Range') &&\n !request.headers.has('X-VoidPages') &&\n !shouldBypassIsr(request),\n );\n}\n\n/** Shared request-side eligibility for the deploy-versioned static cache. */\nfunction isStaticCacheRequestEligible(\n request: Request,\n pathname: string,\n routing: RoutingEntry,\n): boolean {\n return Boolean(\n isSharedStaticCacheRequestEligible(request) &&\n routing.version &&\n !isApiPath(pathname) &&\n (hasExtension(pathname) || !routing.ssr),\n );\n}\n\nasync function isKnownStaticAssetPath(\n env: Env,\n pathname: string,\n routing: RoutingEntry,\n timeoutMs: number,\n): Promise<boolean> {\n if (routing.staticDeploymentId) {\n return true;\n }\n if (!routing.ssr) {\n return true;\n }\n if (!routing.assetManifestId) {\n return false;\n }\n try {\n const manifest = await fetchAssetManifest(\n env,\n routing.assetManifestId,\n routing.projectId,\n Math.min(timeoutMs, STATIC_ASSET_HEDGE_DELAY_MS),\n );\n if (!manifest) {\n return false;\n }\n if (Object.hasOwn(manifest, pathname)) {\n return true;\n }\n const decoded = safeDecodePathname(pathname);\n return decoded !== pathname && Object.hasOwn(manifest, decoded);\n } catch {\n // Asset identity is an optimization gate. If the manifest is unavailable,\n // dispatch the request live instead of guessing from the URL or response.\n return false;\n }\n}\n\n/** Apply the same origin/cached response policy to static reads and writes. */\nfunction isStaticCacheResponseEligible(response: Response): boolean {\n return (\n response.status === 200 && !isEventStreamResponse(response) && !hasSharedCacheOptOut(response)\n );\n}\n\n/** Only entries written under the current shared-cache policy are safe to serve. */\nfunction isCurrentStaticCacheResponse(response: Response): boolean {\n return hasCurrentSharedCachePolicy(response) && isStaticCacheResponseEligible(response);\n}\n"],
|
|
6
|
+
"mappings": "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",
|
|
7
7
|
"names": ["encoder", "withHtml", "worker", "contentType", "headers"]
|
|
8
8
|
}
|