From f4a241175957402cf1fea6c3b7c67aa302bc16d7 Mon Sep 17 00:00:00 2001 From: Programmable <309941960+0xprogrammable@users.noreply.github.com> Date: Mon, 3 Aug 2026 08:58:25 +0200 Subject: [PATCH] fix: verify Vercel production alias directly --- scripts/data-pipeline/cutover-http.mjs | 17 ++++++++---- scripts/data-pipeline/cutover-http.test.mjs | 29 ++++++++++++++++++--- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/scripts/data-pipeline/cutover-http.mjs b/scripts/data-pipeline/cutover-http.mjs index 1f3edc7..e60e0d5 100644 --- a/scripts/data-pipeline/cutover-http.mjs +++ b/scripts/data-pipeline/cutover-http.mjs @@ -187,7 +187,8 @@ export async function inspectUnexposedStagedDeployment(input) { throw new Error("production domain is invalid"); } const lookup = input.fetchDeployment ?? fetchVercelDeployment; - const [candidate, production] = await Promise.all([ + const resolveAlias = input.resolveAlias ?? resolveVercelAlias; + const [candidate, production, productionAlias] = await Promise.all([ lookup({ idOrUrl: input.deploymentId, token: input.token, @@ -200,6 +201,12 @@ export async function inspectUnexposedStagedDeployment(input) { teamId: input.teamId, fetchImpl: input.fetchImpl, }), + resolveAlias({ + alias: productionDomain, + token: input.token, + teamId: input.teamId, + fetchImpl: input.fetchImpl, + }), ]); const candidateHost = String(candidate?.url ?? "") .replace(/^https?:\/\//u, "") @@ -210,7 +217,7 @@ export async function inspectUnexposedStagedDeployment(input) { token: input.token, teamId: input.teamId, fetchImpl: input.fetchImpl, - resolveAlias: input.resolveAlias, + resolveAlias, }); const projectMatches = candidate?.projectId === input.projectId || @@ -218,8 +225,8 @@ export async function inspectUnexposedStagedDeployment(input) { const productionProjectMatches = production?.projectId === input.projectId || production?.project?.id === input.projectId; - const productionAliases = deploymentAliases(production); - const productionDomainAssigned = aliases.includes(productionDomain); + const productionDomainAssigned = productionAlias?.deploymentId === input.deploymentId; + const productionDomainCurrent = productionAlias?.deploymentId === production?.id; const schedulerExposure = candidate?.id === production?.id; if ( candidate?.id !== input.deploymentId || @@ -234,7 +241,7 @@ export async function inspectUnexposedStagedDeployment(input) { production?.readyState !== "READY" || production?.target !== "production" || !productionProjectMatches || - !productionAliases.includes(productionDomain) || + !productionDomainCurrent || !/^[0-9a-f]{40}$/u.test(deploymentCommit(production) ?? "") ) { throw new Error("staged deployment is exposed, aliased or not exactly bound"); diff --git a/scripts/data-pipeline/cutover-http.test.mjs b/scripts/data-pipeline/cutover-http.test.mjs index 32159c6..a663842 100644 --- a/scripts/data-pipeline/cutover-http.test.mjs +++ b/scripts/data-pipeline/cutover-http.test.mjs @@ -232,15 +232,20 @@ test("staged exposure gate accepts only the exact unaliased deployment", async ( readyState: "READY", target: "production", projectId, - alias: ["programmable.family"], + alias: [], meta: { githubCommitSha: productionCommit }, }; const fetchDeployment = async ({ idOrUrl }) => idOrUrl === DEPLOYMENT ? candidate : production; - const resolveAlias = async ({ alias }) => - candidate.alias.includes(alias) - ? { alias, deploymentId: DEPLOYMENT } + let productionAliasDeploymentId = production.id; + const resolveAlias = async ({ alias }) => { + if (candidate.alias.includes(alias)) { + return { alias, deploymentId: DEPLOYMENT }; + } + return alias === "programmable.family" + ? { alias, deploymentId: productionAliasDeploymentId } : undefined; + }; const result = await inspectUnexposedStagedDeployment({ targetUrl: "https://launcher-abc.vercel.app/", deploymentId: DEPLOYMENT, @@ -270,7 +275,23 @@ test("staged exposure gate accepts only the exact unaliased deployment", async ( ); candidate.alias = []; + productionAliasDeploymentId = "dpl_11111111111111111111"; + await assert.rejects( + inspectUnexposedStagedDeployment({ + targetUrl: "https://launcher-abc.vercel.app/", + deploymentId: DEPLOYMENT, + productCommit: candidateCommit, + projectId, + token: "v".repeat(32), + teamId: "team_123", + fetchDeployment, + resolveAlias, + }), + /exposed, aliased or not exactly bound/u, + ); + production.id = DEPLOYMENT; + productionAliasDeploymentId = production.id; await assert.rejects( inspectUnexposedStagedDeployment({ targetUrl: "https://launcher-abc.vercel.app/",