feat(world-vercel): support new env vars for Vercel Deployment Protection - #1824

Merged
TooTallNate merged 6 commits into
mainfrom
world-vercel-protection-bypass
Apr 22, 2026
Merged

feat(world-vercel): support new env vars for Vercel Deployment Protection#1824
TooTallNate merged 6 commits into
mainfrom
world-vercel-protection-bypass

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Apr 21, 2026

Copy link
Copy Markdown
Member

Summary

Adds two new environment variables to @workflow/world-vercel for use with Vercel Deployment Protection.

VERCEL_WORKFLOW_SERVER_PROTECTION_BYPASS

When set, the value is sent as the x-vercel-protection-bypass header on every outbound HTTP request made by the Vercel world (via makeRequest, the streamer, refs, and direct api.vercel.com calls in resolve-latest-deployment.ts and encryption.ts).

Needed because workflow-server is getting Vercel Deployment Protection enabled, so external callers need a way to authenticate bypass.

VERCEL_WORKFLOW_SERVER_URL

Replaces the need to edit source to change the workflow-server URL. When set, requests bypass the default production host (https://vercel-workflow.com) and use the override instead. When going through the api.vercel.com/v1/workflow proxy, the value is forwarded via the x-vercel-workflow-api-url header so the proxy routes accordingly.

The existing inline WORKFLOW_SERVER_URL_OVERRIDE const is preserved as an empty-string literal so external CI rewrite tooling continues to work unmodified; the inline const wins over the env var when non-empty.

Implementation

  • New getProtectionBypassHeader() helper in utils.ts returns the bypass header when the env var is set.
  • getHeaders() applies the bypass header automatically (covers makeRequest, streamer, refs).
  • Direct api.vercel.com fetches in resolve-latest-deployment.ts and encryption.ts spread the helper into their headers.
  • New getWorkflowServerUrlOverride() function prefers the inline const, falls back to VERCEL_WORKFLOW_SERVER_URL.
  • The bypass header passes through the api.vercel.com/v1/workflow proxy transparently — http-proxy-middleware forwards all request headers by default, so no proxy-side changes needed.

Testing

  • pnpm --filter @workflow/world-vercel typecheck
  • pnpm --filter @workflow/world-vercel test — 79 tests pass ✅

Allows sending a Vercel Deployment Protection bypass secret via the
`x-vercel-protection-bypass` header on all outbound requests made by
the Vercel world, enabling use against protected deployments (e.g.
previews, or workflow-server once protection is enabled).
CopilotAI review requested due to automatic review settings April 21, 2026 21:49
@TooTallNate
TooTallNate requested a review from a team as a code ownerApril 21, 2026 21:49
@vercel

vercelBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

@changeset-bot

changeset-botBot commented Apr 21, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 515010b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 18 packages
NameType
@workflow/world-vercelMinor
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
workflowPatch
@workflow/world-testingPatch
@workflow/buildersPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/vitestPatch
@workflow/web-sharedPatch
@workflow/aiPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actionsBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ 💻 Local Development10540861140
✅ 📦 Local Production10540861140
❌ 🐘 Local Postgres10522861140
✅ 🪟 Windows950095
✅ 📋 Other267018285
Total352222763800

❌ Failed Tests

🐘 Local Postgres (2 failed)

nuxt-stable (2 failed):

  • fibonacciWorkflow - recursive workflow composition via start()
  • health check (queue-based) - workflow and step endpoints respond to health check messages

Details by Category

✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
❌ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
❌ nuxt-stable8726
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9500
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8906
✅ e2e-local-postgres-nest-stable8906
✅ e2e-local-prod-nest-stable8906

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: success
  • Local Prod: success
  • Local Postgres: failure
  • Windows: success

Check the workflow run for details.

@github-actions

github-actionsBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.033s (-25.1% 🟢)1.004s (~)0.971s101.00x
💻 LocalNitro0.043s (~)1.005s (~)0.962s101.30x
🐘 PostgresNext.js (Turbopack)0.046s1.009s0.963s101.39x
💻 LocalNext.js (Turbopack)0.048s1.006s0.957s101.45x
🐘 PostgresExpress0.059s (+2.4%)1.012s (~)0.953s101.79x
🐘 PostgresNitro0.064s (-33.1% 🟢)1.010s (-3.1%)0.947s101.92x
workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.105s (-1.8%)2.005s (~)0.900s101.00x
🐘 PostgresNext.js (Turbopack)1.116s2.009s0.893s101.01x
💻 LocalNext.js (Turbopack)1.123s2.007s0.884s101.02x
💻 LocalNitro1.125s (-0.5%)2.006s (~)0.881s101.02x
🐘 PostgresExpress1.144s (~)2.009s (~)0.865s101.03x
🐘 PostgresNitro1.152s (+1.0%)2.012s (~)0.860s101.04x
workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)10.694s11.020s0.326s31.00x
💻 LocalExpress10.758s (-1.5%)11.022s (~)0.264s31.01x
💻 LocalNext.js (Turbopack)10.827s11.025s0.198s31.01x
🐘 PostgresExpress10.847s (-1.1%)11.020s (~)0.173s31.01x
💻 LocalNitro10.934s (~)11.023s (~)0.089s31.02x
🐘 PostgresNitro10.955s (+0.8%)11.026s (~)0.070s31.02x
workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)14.091s15.020s0.929s41.00x
🐘 PostgresExpress14.532s (~)15.020s (~)0.488s41.03x
💻 LocalExpress14.548s (-2.8%)15.029s (~)0.481s41.03x
💻 LocalNext.js (Turbopack)14.628s15.029s0.401s41.04x
🐘 PostgresNitro14.704s (+0.7%)15.028s (~)0.324s41.04x
💻 LocalNitro14.960s (-0.7%)15.030s (-6.2% 🟢)0.070s41.06x
workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)13.144s13.881s0.737s71.00x
🐘 PostgresExpress13.862s (-1.0%)14.024s (-3.9%)0.162s71.05x
🐘 PostgresNitro14.311s (+2.5%)15.021s (+5.0%)0.710s61.09x
💻 LocalExpress15.112s (-9.0% 🟢)16.028s (-5.9% 🟢)0.916s61.15x
💻 LocalNext.js (Turbopack)16.172s17.031s0.859s61.23x
💻 LocalNitro16.642s (-0.8%)17.029s (~)0.387s61.27x
Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.185s2.008s0.823s151.00x
🐘 PostgresExpress1.263s (~)2.010s (~)0.747s151.07x
🐘 PostgresNitro1.282s (+0.6%)2.010s (~)0.728s151.08x
💻 LocalExpress1.436s (-3.6%)2.008s (~)0.573s151.21x
💻 LocalNext.js (Turbopack)1.525s2.005s0.481s151.29x
💻 LocalNitro1.873s (+14.8% 🔺)2.392s (+15.3% 🔺)0.519s131.58x
Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)2.349s3.008s0.659s101.00x
🐘 PostgresExpress2.363s (~)3.009s (~)0.646s101.01x
🐘 PostgresNitro2.400s (+2.1%)3.011s (~)0.611s101.02x
💻 LocalExpress2.521s (-14.6% 🟢)3.007s (-12.9% 🟢)0.486s101.07x
💻 LocalNext.js (Turbopack)2.837s3.565s0.728s91.21x
💻 LocalNitro3.050s (-3.0%)3.760s (-3.2%)0.711s81.30x
Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express3.466s (-0.6%)4.010s (~)0.544s81.00x
🐘 PostgresNitro3.476s (~)4.011s (~)0.536s81.00x
🐘 PostgresNext.js (Turbopack)3.514s4.010s0.495s81.01x
💻 LocalExpress6.216s (-25.5% 🟢)6.814s (-24.5% 🟢)0.599s51.79x
💻 LocalNitro8.493s (+1.7%)9.025s (~)0.532s42.45x
💻 LocalNext.js (Turbopack)8.680s9.271s0.591s42.50x
Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.170s2.007s0.837s151.00x
🐘 PostgresExpress1.265s (+0.6%)2.008s (~)0.743s151.08x
🐘 PostgresNitro1.279s (+1.8%)2.009s (~)0.730s151.09x
💻 LocalNitro1.526s (-18.2% 🟢)2.005s (-14.3% 🟢)0.479s151.30x
💻 LocalNext.js (Turbopack)1.553s2.005s0.452s151.33x
💻 LocalExpress1.583s (-16.4% 🟢)2.109s (-10.8% 🟢)0.526s151.35x
Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.345s (~)3.009s (~)0.664s101.00x
🐘 PostgresNitro2.368s (+1.2%)3.011s (~)0.643s101.01x
🐘 PostgresNext.js (Turbopack)2.418s3.010s0.592s101.03x
💻 LocalExpress2.505s (-20.0% 🟢)3.007s (-20.1% 🟢)0.502s101.07x
💻 LocalNext.js (Turbopack)2.934s3.759s0.825s81.25x
💻 LocalNitro3.017s (-1.6%)3.759s (-3.3%)0.742s81.29x
Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express3.473s (-0.7%)4.011s (~)0.538s81.00x
🐘 PostgresNitro3.525s (+1.3%)4.010s (~)0.485s81.01x
🐘 PostgresNext.js (Turbopack)3.556s4.010s0.454s81.02x
💻 LocalExpress6.601s (-25.0% 🟢)7.222s (-22.1% 🟢)0.621s51.90x
💻 LocalNext.js (Turbopack)8.335s8.518s0.183s42.40x
💻 LocalNitro8.823s (-3.5%)9.273s (-7.5% 🟢)0.450s42.54x
workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.618s1.006s0.388s601.00x
🐘 PostgresExpress0.836s (~)1.041s (+1.7%)0.205s581.35x
💻 LocalNext.js (Turbopack)0.851s1.021s0.170s591.38x
🐘 PostgresNitro0.856s (+4.4%)1.023s (+1.7%)0.167s591.39x
💻 LocalExpress0.871s (-11.5% 🟢)1.095s (+1.7%)0.224s551.41x
💻 LocalNitro0.983s (~)1.076s (-1.6%)0.094s561.59x
workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.513s2.008s0.495s451.00x
🐘 PostgresExpress1.920s (-2.9%)2.053s (-9.1% 🟢)0.133s441.27x
🐘 PostgresNitro2.079s (+7.9% 🔺)2.945s (+40.2% 🔺)0.866s311.37x
💻 LocalExpress2.691s (-10.8% 🟢)3.110s (-13.3% 🟢)0.420s291.78x
💻 LocalNext.js (Turbopack)2.691s3.008s0.317s301.78x
💻 LocalNitro3.040s (~)3.842s (+2.2%)0.802s242.01x
workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)3.056s3.822s0.766s321.00x
🐘 PostgresExpress3.863s (-3.2%)4.077s (-6.7% 🟢)0.214s301.26x
🐘 PostgresNitro4.238s (+3.3%)5.013s (+8.9% 🔺)0.775s241.39x
💻 LocalExpress7.711s (-16.3% 🟢)8.214s (-18.0% 🟢)0.503s152.52x
💻 LocalNext.js (Turbopack)8.787s9.161s0.374s142.87x
💻 LocalNitro9.222s (-0.8%)9.787s (-2.3%)0.566s133.02x
workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.195s1.006s0.811s601.00x
🐘 PostgresExpress0.285s (+1.1%)1.007s (~)0.722s601.46x
🐘 PostgresNitro0.300s (+6.0% 🔺)1.008s (~)0.708s601.54x
💻 LocalExpress0.505s (-10.0% 🟢)1.004s (~)0.499s602.59x
💻 LocalNext.js (Turbopack)0.560s1.004s0.445s602.87x
💻 LocalNitro0.604s (~)1.022s (~)0.417s593.10x
workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.406s1.006s0.599s901.00x
🐘 PostgresExpress0.488s (-4.2%)1.006s (~)0.518s901.20x
🐘 PostgresNitro0.532s (+7.1% 🔺)1.007s (~)0.475s901.31x
💻 LocalExpress2.239s (-10.9% 🟢)3.013s (~)0.774s305.51x
💻 LocalNitro2.539s (~)3.009s (~)0.471s306.25x
💻 LocalNext.js (Turbopack)2.644s3.009s0.365s306.50x
workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.621s1.006s0.385s1201.00x
🐘 PostgresExpress0.800s (-2.3%)1.008s (-0.9%)0.208s1201.29x
🐘 PostgresNitro0.880s (+11.4% 🔺)1.021s (+1.3%)0.140s1181.42x
💻 LocalExpress8.989s (-19.7% 🟢)9.483s (-20.6% 🟢)0.494s1314.48x
💻 LocalNext.js (Turbopack)10.772s11.392s0.620s1117.36x
💻 LocalNitro11.168s (~)11.756s (+0.8%)0.588s1118.00x
Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.166s1.000s0.001s1.010s0.844s101.00x
💻 LocalNext.js (Turbopack)0.171s1.003s0.013s1.019s0.848s101.03x
🐘 PostgresExpress0.200s (-2.6%)0.998s (~)0.001s (-12.5% 🟢)1.010s (~)0.810s101.20x
💻 LocalNitro0.201s (-5.9% 🟢)1.004s (~)0.012s (-4.0%)1.018s (~)0.817s101.21x
💻 LocalExpress0.202s (+1.3%)1.003s (~)0.008s (-35.5% 🟢)1.013s (-0.5%)0.811s101.21x
🐘 PostgresNitro0.224s (+9.2% 🔺)0.997s (~)0.001s (-13.3% 🟢)1.011s (~)0.787s101.35x
stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.541s1.026s0.003s1.037s0.496s581.00x
🐘 PostgresExpress0.609s (-3.3%)1.005s (~)0.011s (+194.7% 🔺)1.031s (+0.8%)0.422s591.13x
💻 LocalExpress0.663s (-12.4% 🟢)1.028s (~)0.007s (-28.4% 🟢)1.036s (~)0.373s581.23x
🐘 PostgresNitro0.682s (+9.3% 🔺)1.022s (+1.6%)0.004s (+8.4% 🔺)1.041s (+1.8%)0.359s581.26x
💻 LocalNext.js (Turbopack)0.770s1.030s0.010s1.137s0.367s531.42x
💻 LocalNitro0.957s (+14.1% 🔺)1.012s (~)0.009s (-2.9%)1.212s (+8.6% 🔺)0.255s531.77x
10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.888s1.071s0.000s1.077s0.189s571.00x
🐘 PostgresExpress0.964s (~)1.239s (-3.0%)0.000s (-6.1% 🟢)1.253s (-4.1%)0.289s491.09x
🐘 PostgresNitro1.040s (+7.3% 🔺)1.604s (+28.6% 🔺)0.000s (-36.8% 🟢)1.616s (+28.5% 🔺)0.576s381.17x
💻 LocalExpress1.106s (-9.7% 🟢)1.951s (-3.4%)0.000s (+35.5% 🔺)1.953s (-3.4%)0.848s311.25x
💻 LocalNext.js (Turbopack)1.263s2.020s0.000s2.023s0.760s301.42x
💻 LocalNitro1.397s (+14.2% 🔺)2.020s (~)0.000s (+221.4% 🔺)2.200s (+8.8% 🔺)0.803s281.57x
fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.751s2.105s0.000s2.120s0.369s291.00x
🐘 PostgresExpress1.761s (-0.6%)2.102s (-3.5%)0.000s (NaN%)2.113s (-3.9%)0.352s291.01x
🐘 PostgresNitro1.904s (+6.3% 🔺)2.293s (+7.1% 🔺)0.000s (+3.7%)2.307s (+6.1% 🔺)0.403s271.09x
💻 LocalExpress3.308s (-4.6%)3.779s (-6.3% 🟢)0.001s (-21.9% 🟢)3.781s (-6.3% 🟢)0.474s161.89x
💻 LocalNitro3.557s (+5.0% 🔺)4.097s (+1.6%)0.001s (+12.5% 🔺)4.100s (+1.6%)0.543s152.03x
💻 LocalNext.js (Turbopack)3.594s4.233s0.001s4.236s0.643s152.05x

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress18/21
🐘 PostgresNext.js (Turbopack)18/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres18/21
Next.js (Turbopack)🐘 Postgres21/21
Nitro🐘 Postgres17/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run


Some benchmark jobs failed:

  • Local: success
  • Postgres: success
  • Vercel: failure

Check the workflow run for details.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support in @workflow/world-vercel for sending Vercel Deployment Protection bypass credentials via WORKFLOW_VERCEL_PROTECTION_BYPASS, ensuring outbound requests can access protected preview/production deployments.

Changes:

  • Introduces getProtectionBypassHeader() helper to conditionally produce the x-vercel-protection-bypass header.
  • Injects the bypass header into the shared getHeaders() path (covers makeRequest/streamer/refs).
  • Spreads the bypass header into direct fetch() calls in resolve-latest-deployment.ts and encryption.ts.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

FileDescription
packages/world-vercel/src/utils.tsAdds bypass-header helper and includes bypass header in shared header construction.
packages/world-vercel/src/resolve-latest-deployment.tsAdds bypass header to direct Vercel API request headers.
packages/world-vercel/src/encryption.tsAdds bypass header to direct Vercel API request headers.
.changeset/world-vercel-protection-bypass.mdDeclares a minor release for the new env var behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadpackages/world-vercel/src/resolve-latest-deployment.ts Outdated
Comment threadpackages/world-vercel/src/encryption.ts Outdated
Comment threadpackages/world-vercel/src/utils.ts Outdated
Comment threadpackages/world-vercel/src/utils.ts
Replace hard-coded WORKFLOW_SERVER_URL_OVERRIDE constant with a function
that reads from the VERCEL_WORKFLOW_SERVER_URL env var. Allows configuring
the workflow-server URL per-deployment (e.g. workbench Preview envs
pointing to a branch deployment) without editing source.
Set VERCEL_WORKFLOW_SERVER_URL and VERCEL_WORKFLOW_SERVER_PROTECTION_BYPASS
on PR runs so e2e tests hit the protected workflow-server preview; leave
unset on main so production runs use the public default URL.

@karthikscale3karthikscale3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good. the codex review comments are worth addressing

- Consolidate bypass header logic in getHeaders() to reuse
getProtectionBypassHeader() instead of duplicating env lookup.
- Use consistent 'Authorization' casing in direct fetch() calls.
- Add unit tests for getProtectionBypassHeader, getHttpUrl, and getHeaders
covering env var toggling and proxy/override combinations.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-stableCherry-pick this PR to the stable branch when merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@TooTallNate@karthikscale3
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(world-vercel): support new env vars for Vercel Deployment Protection - #1824

Merged
TooTallNate merged 6 commits into
mainfrom
world-vercel-protection-bypass
Apr 22, 2026
Merged

feat(world-vercel): support new env vars for Vercel Deployment Protection#1824
TooTallNate merged 6 commits into
mainfrom
world-vercel-protection-bypass

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Apr 21, 2026

Copy link
Copy Markdown
Member

Summary

Adds two new environment variables to @workflow/world-vercel for use with Vercel Deployment Protection.

VERCEL_WORKFLOW_SERVER_PROTECTION_BYPASS

When set, the value is sent as the x-vercel-protection-bypass header on every outbound HTTP request made by the Vercel world (via makeRequest, the streamer, refs, and direct api.vercel.com calls in resolve-latest-deployment.ts and encryption.ts).

Needed because workflow-server is getting Vercel Deployment Protection enabled, so external callers need a way to authenticate bypass.

VERCEL_WORKFLOW_SERVER_URL

Replaces the need to edit source to change the workflow-server URL. When set, requests bypass the default production host (https://vercel-workflow.com) and use the override instead. When going through the api.vercel.com/v1/workflow proxy, the value is forwarded via the x-vercel-workflow-api-url header so the proxy routes accordingly.

The existing inline WORKFLOW_SERVER_URL_OVERRIDE const is preserved as an empty-string literal so external CI rewrite tooling continues to work unmodified; the inline const wins over the env var when non-empty.

Implementation

  • New getProtectionBypassHeader() helper in utils.ts returns the bypass header when the env var is set.
  • getHeaders() applies the bypass header automatically (covers makeRequest, streamer, refs).
  • Direct api.vercel.com fetches in resolve-latest-deployment.ts and encryption.ts spread the helper into their headers.
  • New getWorkflowServerUrlOverride() function prefers the inline const, falls back to VERCEL_WORKFLOW_SERVER_URL.
  • The bypass header passes through the api.vercel.com/v1/workflow proxy transparently — http-proxy-middleware forwards all request headers by default, so no proxy-side changes needed.

Testing

  • pnpm --filter @workflow/world-vercel typecheck
  • pnpm --filter @workflow/world-vercel test — 79 tests pass ✅

Allows sending a Vercel Deployment Protection bypass secret via the
`x-vercel-protection-bypass` header on all outbound requests made by
the Vercel world, enabling use against protected deployments (e.g.
previews, or workflow-server once protection is enabled).
CopilotAI review requested due to automatic review settings April 21, 2026 21:49
@TooTallNate
TooTallNate requested a review from a team as a code ownerApril 21, 2026 21:49
@vercel

vercelBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

@changeset-bot

changeset-botBot commented Apr 21, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 515010b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 18 packages
NameType
@workflow/world-vercelMinor
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
workflowPatch
@workflow/world-testingPatch
@workflow/buildersPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/vitestPatch
@workflow/web-sharedPatch
@workflow/aiPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actionsBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ 💻 Local Development10540861140
✅ 📦 Local Production10540861140
❌ 🐘 Local Postgres10522861140
✅ 🪟 Windows950095
✅ 📋 Other267018285
Total352222763800

❌ Failed Tests

🐘 Local Postgres (2 failed)

nuxt-stable (2 failed):

  • fibonacciWorkflow - recursive workflow composition via start()
  • health check (queue-based) - workflow and step endpoints respond to health check messages

Details by Category

✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
❌ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
❌ nuxt-stable8726
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9500
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8906
✅ e2e-local-postgres-nest-stable8906
✅ e2e-local-prod-nest-stable8906

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: success
  • Local Prod: success
  • Local Postgres: failure
  • Windows: success

Check the workflow run for details.

@github-actions

github-actionsBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.033s (-25.1% 🟢)1.004s (~)0.971s101.00x
💻 LocalNitro0.043s (~)1.005s (~)0.962s101.30x
🐘 PostgresNext.js (Turbopack)0.046s1.009s0.963s101.39x
💻 LocalNext.js (Turbopack)0.048s1.006s0.957s101.45x
🐘 PostgresExpress0.059s (+2.4%)1.012s (~)0.953s101.79x
🐘 PostgresNitro0.064s (-33.1% 🟢)1.010s (-3.1%)0.947s101.92x
workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.105s (-1.8%)2.005s (~)0.900s101.00x
🐘 PostgresNext.js (Turbopack)1.116s2.009s0.893s101.01x
💻 LocalNext.js (Turbopack)1.123s2.007s0.884s101.02x
💻 LocalNitro1.125s (-0.5%)2.006s (~)0.881s101.02x
🐘 PostgresExpress1.144s (~)2.009s (~)0.865s101.03x
🐘 PostgresNitro1.152s (+1.0%)2.012s (~)0.860s101.04x
workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)10.694s11.020s0.326s31.00x
💻 LocalExpress10.758s (-1.5%)11.022s (~)0.264s31.01x
💻 LocalNext.js (Turbopack)10.827s11.025s0.198s31.01x
🐘 PostgresExpress10.847s (-1.1%)11.020s (~)0.173s31.01x
💻 LocalNitro10.934s (~)11.023s (~)0.089s31.02x
🐘 PostgresNitro10.955s (+0.8%)11.026s (~)0.070s31.02x
workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)14.091s15.020s0.929s41.00x
🐘 PostgresExpress14.532s (~)15.020s (~)0.488s41.03x
💻 LocalExpress14.548s (-2.8%)15.029s (~)0.481s41.03x
💻 LocalNext.js (Turbopack)14.628s15.029s0.401s41.04x
🐘 PostgresNitro14.704s (+0.7%)15.028s (~)0.324s41.04x
💻 LocalNitro14.960s (-0.7%)15.030s (-6.2% 🟢)0.070s41.06x
workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)13.144s13.881s0.737s71.00x
🐘 PostgresExpress13.862s (-1.0%)14.024s (-3.9%)0.162s71.05x
🐘 PostgresNitro14.311s (+2.5%)15.021s (+5.0%)0.710s61.09x
💻 LocalExpress15.112s (-9.0% 🟢)16.028s (-5.9% 🟢)0.916s61.15x
💻 LocalNext.js (Turbopack)16.172s17.031s0.859s61.23x
💻 LocalNitro16.642s (-0.8%)17.029s (~)0.387s61.27x
Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.185s2.008s0.823s151.00x
🐘 PostgresExpress1.263s (~)2.010s (~)0.747s151.07x
🐘 PostgresNitro1.282s (+0.6%)2.010s (~)0.728s151.08x
💻 LocalExpress1.436s (-3.6%)2.008s (~)0.573s151.21x
💻 LocalNext.js (Turbopack)1.525s2.005s0.481s151.29x
💻 LocalNitro1.873s (+14.8% 🔺)2.392s (+15.3% 🔺)0.519s131.58x
Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)2.349s3.008s0.659s101.00x
🐘 PostgresExpress2.363s (~)3.009s (~)0.646s101.01x
🐘 PostgresNitro2.400s (+2.1%)3.011s (~)0.611s101.02x
💻 LocalExpress2.521s (-14.6% 🟢)3.007s (-12.9% 🟢)0.486s101.07x
💻 LocalNext.js (Turbopack)2.837s3.565s0.728s91.21x
💻 LocalNitro3.050s (-3.0%)3.760s (-3.2%)0.711s81.30x
Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express3.466s (-0.6%)4.010s (~)0.544s81.00x
🐘 PostgresNitro3.476s (~)4.011s (~)0.536s81.00x
🐘 PostgresNext.js (Turbopack)3.514s4.010s0.495s81.01x
💻 LocalExpress6.216s (-25.5% 🟢)6.814s (-24.5% 🟢)0.599s51.79x
💻 LocalNitro8.493s (+1.7%)9.025s (~)0.532s42.45x
💻 LocalNext.js (Turbopack)8.680s9.271s0.591s42.50x
Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.170s2.007s0.837s151.00x
🐘 PostgresExpress1.265s (+0.6%)2.008s (~)0.743s151.08x
🐘 PostgresNitro1.279s (+1.8%)2.009s (~)0.730s151.09x
💻 LocalNitro1.526s (-18.2% 🟢)2.005s (-14.3% 🟢)0.479s151.30x
💻 LocalNext.js (Turbopack)1.553s2.005s0.452s151.33x
💻 LocalExpress1.583s (-16.4% 🟢)2.109s (-10.8% 🟢)0.526s151.35x
Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.345s (~)3.009s (~)0.664s101.00x
🐘 PostgresNitro2.368s (+1.2%)3.011s (~)0.643s101.01x
🐘 PostgresNext.js (Turbopack)2.418s3.010s0.592s101.03x
💻 LocalExpress2.505s (-20.0% 🟢)3.007s (-20.1% 🟢)0.502s101.07x
💻 LocalNext.js (Turbopack)2.934s3.759s0.825s81.25x
💻 LocalNitro3.017s (-1.6%)3.759s (-3.3%)0.742s81.29x
Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express3.473s (-0.7%)4.011s (~)0.538s81.00x
🐘 PostgresNitro3.525s (+1.3%)4.010s (~)0.485s81.01x
🐘 PostgresNext.js (Turbopack)3.556s4.010s0.454s81.02x
💻 LocalExpress6.601s (-25.0% 🟢)7.222s (-22.1% 🟢)0.621s51.90x
💻 LocalNext.js (Turbopack)8.335s8.518s0.183s42.40x
💻 LocalNitro8.823s (-3.5%)9.273s (-7.5% 🟢)0.450s42.54x
workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.618s1.006s0.388s601.00x
🐘 PostgresExpress0.836s (~)1.041s (+1.7%)0.205s581.35x
💻 LocalNext.js (Turbopack)0.851s1.021s0.170s591.38x
🐘 PostgresNitro0.856s (+4.4%)1.023s (+1.7%)0.167s591.39x
💻 LocalExpress0.871s (-11.5% 🟢)1.095s (+1.7%)0.224s551.41x
💻 LocalNitro0.983s (~)1.076s (-1.6%)0.094s561.59x
workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.513s2.008s0.495s451.00x
🐘 PostgresExpress1.920s (-2.9%)2.053s (-9.1% 🟢)0.133s441.27x
🐘 PostgresNitro2.079s (+7.9% 🔺)2.945s (+40.2% 🔺)0.866s311.37x
💻 LocalExpress2.691s (-10.8% 🟢)3.110s (-13.3% 🟢)0.420s291.78x
💻 LocalNext.js (Turbopack)2.691s3.008s0.317s301.78x
💻 LocalNitro3.040s (~)3.842s (+2.2%)0.802s242.01x
workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)3.056s3.822s0.766s321.00x
🐘 PostgresExpress3.863s (-3.2%)4.077s (-6.7% 🟢)0.214s301.26x
🐘 PostgresNitro4.238s (+3.3%)5.013s (+8.9% 🔺)0.775s241.39x
💻 LocalExpress7.711s (-16.3% 🟢)8.214s (-18.0% 🟢)0.503s152.52x
💻 LocalNext.js (Turbopack)8.787s9.161s0.374s142.87x
💻 LocalNitro9.222s (-0.8%)9.787s (-2.3%)0.566s133.02x
workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.195s1.006s0.811s601.00x
🐘 PostgresExpress0.285s (+1.1%)1.007s (~)0.722s601.46x
🐘 PostgresNitro0.300s (+6.0% 🔺)1.008s (~)0.708s601.54x
💻 LocalExpress0.505s (-10.0% 🟢)1.004s (~)0.499s602.59x
💻 LocalNext.js (Turbopack)0.560s1.004s0.445s602.87x
💻 LocalNitro0.604s (~)1.022s (~)0.417s593.10x
workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.406s1.006s0.599s901.00x
🐘 PostgresExpress0.488s (-4.2%)1.006s (~)0.518s901.20x
🐘 PostgresNitro0.532s (+7.1% 🔺)1.007s (~)0.475s901.31x
💻 LocalExpress2.239s (-10.9% 🟢)3.013s (~)0.774s305.51x
💻 LocalNitro2.539s (~)3.009s (~)0.471s306.25x
💻 LocalNext.js (Turbopack)2.644s3.009s0.365s306.50x
workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.621s1.006s0.385s1201.00x
🐘 PostgresExpress0.800s (-2.3%)1.008s (-0.9%)0.208s1201.29x
🐘 PostgresNitro0.880s (+11.4% 🔺)1.021s (+1.3%)0.140s1181.42x
💻 LocalExpress8.989s (-19.7% 🟢)9.483s (-20.6% 🟢)0.494s1314.48x
💻 LocalNext.js (Turbopack)10.772s11.392s0.620s1117.36x
💻 LocalNitro11.168s (~)11.756s (+0.8%)0.588s1118.00x
Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.166s1.000s0.001s1.010s0.844s101.00x
💻 LocalNext.js (Turbopack)0.171s1.003s0.013s1.019s0.848s101.03x
🐘 PostgresExpress0.200s (-2.6%)0.998s (~)0.001s (-12.5% 🟢)1.010s (~)0.810s101.20x
💻 LocalNitro0.201s (-5.9% 🟢)1.004s (~)0.012s (-4.0%)1.018s (~)0.817s101.21x
💻 LocalExpress0.202s (+1.3%)1.003s (~)0.008s (-35.5% 🟢)1.013s (-0.5%)0.811s101.21x
🐘 PostgresNitro0.224s (+9.2% 🔺)0.997s (~)0.001s (-13.3% 🟢)1.011s (~)0.787s101.35x
stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.541s1.026s0.003s1.037s0.496s581.00x
🐘 PostgresExpress0.609s (-3.3%)1.005s (~)0.011s (+194.7% 🔺)1.031s (+0.8%)0.422s591.13x
💻 LocalExpress0.663s (-12.4% 🟢)1.028s (~)0.007s (-28.4% 🟢)1.036s (~)0.373s581.23x
🐘 PostgresNitro0.682s (+9.3% 🔺)1.022s (+1.6%)0.004s (+8.4% 🔺)1.041s (+1.8%)0.359s581.26x
💻 LocalNext.js (Turbopack)0.770s1.030s0.010s1.137s0.367s531.42x
💻 LocalNitro0.957s (+14.1% 🔺)1.012s (~)0.009s (-2.9%)1.212s (+8.6% 🔺)0.255s531.77x
10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.888s1.071s0.000s1.077s0.189s571.00x
🐘 PostgresExpress0.964s (~)1.239s (-3.0%)0.000s (-6.1% 🟢)1.253s (-4.1%)0.289s491.09x
🐘 PostgresNitro1.040s (+7.3% 🔺)1.604s (+28.6% 🔺)0.000s (-36.8% 🟢)1.616s (+28.5% 🔺)0.576s381.17x
💻 LocalExpress1.106s (-9.7% 🟢)1.951s (-3.4%)0.000s (+35.5% 🔺)1.953s (-3.4%)0.848s311.25x
💻 LocalNext.js (Turbopack)1.263s2.020s0.000s2.023s0.760s301.42x
💻 LocalNitro1.397s (+14.2% 🔺)2.020s (~)0.000s (+221.4% 🔺)2.200s (+8.8% 🔺)0.803s281.57x
fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.751s2.105s0.000s2.120s0.369s291.00x
🐘 PostgresExpress1.761s (-0.6%)2.102s (-3.5%)0.000s (NaN%)2.113s (-3.9%)0.352s291.01x
🐘 PostgresNitro1.904s (+6.3% 🔺)2.293s (+7.1% 🔺)0.000s (+3.7%)2.307s (+6.1% 🔺)0.403s271.09x
💻 LocalExpress3.308s (-4.6%)3.779s (-6.3% 🟢)0.001s (-21.9% 🟢)3.781s (-6.3% 🟢)0.474s161.89x
💻 LocalNitro3.557s (+5.0% 🔺)4.097s (+1.6%)0.001s (+12.5% 🔺)4.100s (+1.6%)0.543s152.03x
💻 LocalNext.js (Turbopack)3.594s4.233s0.001s4.236s0.643s152.05x

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress18/21
🐘 PostgresNext.js (Turbopack)18/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres18/21
Next.js (Turbopack)🐘 Postgres21/21
Nitro🐘 Postgres17/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run


Some benchmark jobs failed:

  • Local: success
  • Postgres: success
  • Vercel: failure

Check the workflow run for details.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support in @workflow/world-vercel for sending Vercel Deployment Protection bypass credentials via WORKFLOW_VERCEL_PROTECTION_BYPASS, ensuring outbound requests can access protected preview/production deployments.

Changes:

  • Introduces getProtectionBypassHeader() helper to conditionally produce the x-vercel-protection-bypass header.
  • Injects the bypass header into the shared getHeaders() path (covers makeRequest/streamer/refs).
  • Spreads the bypass header into direct fetch() calls in resolve-latest-deployment.ts and encryption.ts.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

FileDescription
packages/world-vercel/src/utils.tsAdds bypass-header helper and includes bypass header in shared header construction.
packages/world-vercel/src/resolve-latest-deployment.tsAdds bypass header to direct Vercel API request headers.
packages/world-vercel/src/encryption.tsAdds bypass header to direct Vercel API request headers.
.changeset/world-vercel-protection-bypass.mdDeclares a minor release for the new env var behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadpackages/world-vercel/src/resolve-latest-deployment.ts Outdated
Comment threadpackages/world-vercel/src/encryption.ts Outdated
Comment threadpackages/world-vercel/src/utils.ts Outdated
Comment threadpackages/world-vercel/src/utils.ts
Replace hard-coded WORKFLOW_SERVER_URL_OVERRIDE constant with a function
that reads from the VERCEL_WORKFLOW_SERVER_URL env var. Allows configuring
the workflow-server URL per-deployment (e.g. workbench Preview envs
pointing to a branch deployment) without editing source.
Set VERCEL_WORKFLOW_SERVER_URL and VERCEL_WORKFLOW_SERVER_PROTECTION_BYPASS
on PR runs so e2e tests hit the protected workflow-server preview; leave
unset on main so production runs use the public default URL.

@karthikscale3karthikscale3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good. the codex review comments are worth addressing

- Consolidate bypass header logic in getHeaders() to reuse
getProtectionBypassHeader() instead of duplicating env lookup.
- Use consistent 'Authorization' casing in direct fetch() calls.
- Add unit tests for getProtectionBypassHeader, getHttpUrl, and getHeaders
covering env var toggling and proxy/override combinations.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-stableCherry-pick this PR to the stable branch when merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@TooTallNate@karthikscale3
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(world-vercel): support new env vars for Vercel Deployment Protection - #1824

Merged
TooTallNate merged 6 commits into
mainfrom
world-vercel-protection-bypass
Apr 22, 2026
Merged

feat(world-vercel): support new env vars for Vercel Deployment Protection#1824
TooTallNate merged 6 commits into
mainfrom
world-vercel-protection-bypass

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Apr 21, 2026

Copy link
Copy Markdown
Member

Summary

Adds two new environment variables to @workflow/world-vercel for use with Vercel Deployment Protection.

VERCEL_WORKFLOW_SERVER_PROTECTION_BYPASS

When set, the value is sent as the x-vercel-protection-bypass header on every outbound HTTP request made by the Vercel world (via makeRequest, the streamer, refs, and direct api.vercel.com calls in resolve-latest-deployment.ts and encryption.ts).

Needed because workflow-server is getting Vercel Deployment Protection enabled, so external callers need a way to authenticate bypass.

VERCEL_WORKFLOW_SERVER_URL

Replaces the need to edit source to change the workflow-server URL. When set, requests bypass the default production host (https://vercel-workflow.com) and use the override instead. When going through the api.vercel.com/v1/workflow proxy, the value is forwarded via the x-vercel-workflow-api-url header so the proxy routes accordingly.

The existing inline WORKFLOW_SERVER_URL_OVERRIDE const is preserved as an empty-string literal so external CI rewrite tooling continues to work unmodified; the inline const wins over the env var when non-empty.

Implementation

  • New getProtectionBypassHeader() helper in utils.ts returns the bypass header when the env var is set.
  • getHeaders() applies the bypass header automatically (covers makeRequest, streamer, refs).
  • Direct api.vercel.com fetches in resolve-latest-deployment.ts and encryption.ts spread the helper into their headers.
  • New getWorkflowServerUrlOverride() function prefers the inline const, falls back to VERCEL_WORKFLOW_SERVER_URL.
  • The bypass header passes through the api.vercel.com/v1/workflow proxy transparently — http-proxy-middleware forwards all request headers by default, so no proxy-side changes needed.

Testing

  • pnpm --filter @workflow/world-vercel typecheck
  • pnpm --filter @workflow/world-vercel test — 79 tests pass ✅

Allows sending a Vercel Deployment Protection bypass secret via the
`x-vercel-protection-bypass` header on all outbound requests made by
the Vercel world, enabling use against protected deployments (e.g.
previews, or workflow-server once protection is enabled).
CopilotAI review requested due to automatic review settings April 21, 2026 21:49
@TooTallNate
TooTallNate requested a review from a team as a code ownerApril 21, 2026 21:49
@vercel

vercelBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

@changeset-bot

changeset-botBot commented Apr 21, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 515010b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 18 packages
NameType
@workflow/world-vercelMinor
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
workflowPatch
@workflow/world-testingPatch
@workflow/buildersPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/vitestPatch
@workflow/web-sharedPatch
@workflow/aiPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actionsBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ 💻 Local Development10540861140
✅ 📦 Local Production10540861140
❌ 🐘 Local Postgres10522861140
✅ 🪟 Windows950095
✅ 📋 Other267018285
Total352222763800

❌ Failed Tests

🐘 Local Postgres (2 failed)

nuxt-stable (2 failed):

  • fibonacciWorkflow - recursive workflow composition via start()
  • health check (queue-based) - workflow and step endpoints respond to health check messages

Details by Category

✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
❌ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
❌ nuxt-stable8726
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9500
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8906
✅ e2e-local-postgres-nest-stable8906
✅ e2e-local-prod-nest-stable8906

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: success
  • Local Prod: success
  • Local Postgres: failure
  • Windows: success

Check the workflow run for details.

@github-actions

github-actionsBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.033s (-25.1% 🟢)1.004s (~)0.971s101.00x
💻 LocalNitro0.043s (~)1.005s (~)0.962s101.30x
🐘 PostgresNext.js (Turbopack)0.046s1.009s0.963s101.39x
💻 LocalNext.js (Turbopack)0.048s1.006s0.957s101.45x
🐘 PostgresExpress0.059s (+2.4%)1.012s (~)0.953s101.79x
🐘 PostgresNitro0.064s (-33.1% 🟢)1.010s (-3.1%)0.947s101.92x
workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.105s (-1.8%)2.005s (~)0.900s101.00x
🐘 PostgresNext.js (Turbopack)1.116s2.009s0.893s101.01x
💻 LocalNext.js (Turbopack)1.123s2.007s0.884s101.02x
💻 LocalNitro1.125s (-0.5%)2.006s (~)0.881s101.02x
🐘 PostgresExpress1.144s (~)2.009s (~)0.865s101.03x
🐘 PostgresNitro1.152s (+1.0%)2.012s (~)0.860s101.04x
workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)10.694s11.020s0.326s31.00x
💻 LocalExpress10.758s (-1.5%)11.022s (~)0.264s31.01x
💻 LocalNext.js (Turbopack)10.827s11.025s0.198s31.01x
🐘 PostgresExpress10.847s (-1.1%)11.020s (~)0.173s31.01x
💻 LocalNitro10.934s (~)11.023s (~)0.089s31.02x
🐘 PostgresNitro10.955s (+0.8%)11.026s (~)0.070s31.02x
workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)14.091s15.020s0.929s41.00x
🐘 PostgresExpress14.532s (~)15.020s (~)0.488s41.03x
💻 LocalExpress14.548s (-2.8%)15.029s (~)0.481s41.03x
💻 LocalNext.js (Turbopack)14.628s15.029s0.401s41.04x
🐘 PostgresNitro14.704s (+0.7%)15.028s (~)0.324s41.04x
💻 LocalNitro14.960s (-0.7%)15.030s (-6.2% 🟢)0.070s41.06x
workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)13.144s13.881s0.737s71.00x
🐘 PostgresExpress13.862s (-1.0%)14.024s (-3.9%)0.162s71.05x
🐘 PostgresNitro14.311s (+2.5%)15.021s (+5.0%)0.710s61.09x
💻 LocalExpress15.112s (-9.0% 🟢)16.028s (-5.9% 🟢)0.916s61.15x
💻 LocalNext.js (Turbopack)16.172s17.031s0.859s61.23x
💻 LocalNitro16.642s (-0.8%)17.029s (~)0.387s61.27x
Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.185s2.008s0.823s151.00x
🐘 PostgresExpress1.263s (~)2.010s (~)0.747s151.07x
🐘 PostgresNitro1.282s (+0.6%)2.010s (~)0.728s151.08x
💻 LocalExpress1.436s (-3.6%)2.008s (~)0.573s151.21x
💻 LocalNext.js (Turbopack)1.525s2.005s0.481s151.29x
💻 LocalNitro1.873s (+14.8% 🔺)2.392s (+15.3% 🔺)0.519s131.58x
Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)2.349s3.008s0.659s101.00x
🐘 PostgresExpress2.363s (~)3.009s (~)0.646s101.01x
🐘 PostgresNitro2.400s (+2.1%)3.011s (~)0.611s101.02x
💻 LocalExpress2.521s (-14.6% 🟢)3.007s (-12.9% 🟢)0.486s101.07x
💻 LocalNext.js (Turbopack)2.837s3.565s0.728s91.21x
💻 LocalNitro3.050s (-3.0%)3.760s (-3.2%)0.711s81.30x
Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express3.466s (-0.6%)4.010s (~)0.544s81.00x
🐘 PostgresNitro3.476s (~)4.011s (~)0.536s81.00x
🐘 PostgresNext.js (Turbopack)3.514s4.010s0.495s81.01x
💻 LocalExpress6.216s (-25.5% 🟢)6.814s (-24.5% 🟢)0.599s51.79x
💻 LocalNitro8.493s (+1.7%)9.025s (~)0.532s42.45x
💻 LocalNext.js (Turbopack)8.680s9.271s0.591s42.50x
Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.170s2.007s0.837s151.00x
🐘 PostgresExpress1.265s (+0.6%)2.008s (~)0.743s151.08x
🐘 PostgresNitro1.279s (+1.8%)2.009s (~)0.730s151.09x
💻 LocalNitro1.526s (-18.2% 🟢)2.005s (-14.3% 🟢)0.479s151.30x
💻 LocalNext.js (Turbopack)1.553s2.005s0.452s151.33x
💻 LocalExpress1.583s (-16.4% 🟢)2.109s (-10.8% 🟢)0.526s151.35x
Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.345s (~)3.009s (~)0.664s101.00x
🐘 PostgresNitro2.368s (+1.2%)3.011s (~)0.643s101.01x
🐘 PostgresNext.js (Turbopack)2.418s3.010s0.592s101.03x
💻 LocalExpress2.505s (-20.0% 🟢)3.007s (-20.1% 🟢)0.502s101.07x
💻 LocalNext.js (Turbopack)2.934s3.759s0.825s81.25x
💻 LocalNitro3.017s (-1.6%)3.759s (-3.3%)0.742s81.29x
Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express3.473s (-0.7%)4.011s (~)0.538s81.00x
🐘 PostgresNitro3.525s (+1.3%)4.010s (~)0.485s81.01x
🐘 PostgresNext.js (Turbopack)3.556s4.010s0.454s81.02x
💻 LocalExpress6.601s (-25.0% 🟢)7.222s (-22.1% 🟢)0.621s51.90x
💻 LocalNext.js (Turbopack)8.335s8.518s0.183s42.40x
💻 LocalNitro8.823s (-3.5%)9.273s (-7.5% 🟢)0.450s42.54x
workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.618s1.006s0.388s601.00x
🐘 PostgresExpress0.836s (~)1.041s (+1.7%)0.205s581.35x
💻 LocalNext.js (Turbopack)0.851s1.021s0.170s591.38x
🐘 PostgresNitro0.856s (+4.4%)1.023s (+1.7%)0.167s591.39x
💻 LocalExpress0.871s (-11.5% 🟢)1.095s (+1.7%)0.224s551.41x
💻 LocalNitro0.983s (~)1.076s (-1.6%)0.094s561.59x
workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.513s2.008s0.495s451.00x
🐘 PostgresExpress1.920s (-2.9%)2.053s (-9.1% 🟢)0.133s441.27x
🐘 PostgresNitro2.079s (+7.9% 🔺)2.945s (+40.2% 🔺)0.866s311.37x
💻 LocalExpress2.691s (-10.8% 🟢)3.110s (-13.3% 🟢)0.420s291.78x
💻 LocalNext.js (Turbopack)2.691s3.008s0.317s301.78x
💻 LocalNitro3.040s (~)3.842s (+2.2%)0.802s242.01x
workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)3.056s3.822s0.766s321.00x
🐘 PostgresExpress3.863s (-3.2%)4.077s (-6.7% 🟢)0.214s301.26x
🐘 PostgresNitro4.238s (+3.3%)5.013s (+8.9% 🔺)0.775s241.39x
💻 LocalExpress7.711s (-16.3% 🟢)8.214s (-18.0% 🟢)0.503s152.52x
💻 LocalNext.js (Turbopack)8.787s9.161s0.374s142.87x
💻 LocalNitro9.222s (-0.8%)9.787s (-2.3%)0.566s133.02x
workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.195s1.006s0.811s601.00x
🐘 PostgresExpress0.285s (+1.1%)1.007s (~)0.722s601.46x
🐘 PostgresNitro0.300s (+6.0% 🔺)1.008s (~)0.708s601.54x
💻 LocalExpress0.505s (-10.0% 🟢)1.004s (~)0.499s602.59x
💻 LocalNext.js (Turbopack)0.560s1.004s0.445s602.87x
💻 LocalNitro0.604s (~)1.022s (~)0.417s593.10x
workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.406s1.006s0.599s901.00x
🐘 PostgresExpress0.488s (-4.2%)1.006s (~)0.518s901.20x
🐘 PostgresNitro0.532s (+7.1% 🔺)1.007s (~)0.475s901.31x
💻 LocalExpress2.239s (-10.9% 🟢)3.013s (~)0.774s305.51x
💻 LocalNitro2.539s (~)3.009s (~)0.471s306.25x
💻 LocalNext.js (Turbopack)2.644s3.009s0.365s306.50x
workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.621s1.006s0.385s1201.00x
🐘 PostgresExpress0.800s (-2.3%)1.008s (-0.9%)0.208s1201.29x
🐘 PostgresNitro0.880s (+11.4% 🔺)1.021s (+1.3%)0.140s1181.42x
💻 LocalExpress8.989s (-19.7% 🟢)9.483s (-20.6% 🟢)0.494s1314.48x
💻 LocalNext.js (Turbopack)10.772s11.392s0.620s1117.36x
💻 LocalNitro11.168s (~)11.756s (+0.8%)0.588s1118.00x
Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.166s1.000s0.001s1.010s0.844s101.00x
💻 LocalNext.js (Turbopack)0.171s1.003s0.013s1.019s0.848s101.03x
🐘 PostgresExpress0.200s (-2.6%)0.998s (~)0.001s (-12.5% 🟢)1.010s (~)0.810s101.20x
💻 LocalNitro0.201s (-5.9% 🟢)1.004s (~)0.012s (-4.0%)1.018s (~)0.817s101.21x
💻 LocalExpress0.202s (+1.3%)1.003s (~)0.008s (-35.5% 🟢)1.013s (-0.5%)0.811s101.21x
🐘 PostgresNitro0.224s (+9.2% 🔺)0.997s (~)0.001s (-13.3% 🟢)1.011s (~)0.787s101.35x
stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.541s1.026s0.003s1.037s0.496s581.00x
🐘 PostgresExpress0.609s (-3.3%)1.005s (~)0.011s (+194.7% 🔺)1.031s (+0.8%)0.422s591.13x
💻 LocalExpress0.663s (-12.4% 🟢)1.028s (~)0.007s (-28.4% 🟢)1.036s (~)0.373s581.23x
🐘 PostgresNitro0.682s (+9.3% 🔺)1.022s (+1.6%)0.004s (+8.4% 🔺)1.041s (+1.8%)0.359s581.26x
💻 LocalNext.js (Turbopack)0.770s1.030s0.010s1.137s0.367s531.42x
💻 LocalNitro0.957s (+14.1% 🔺)1.012s (~)0.009s (-2.9%)1.212s (+8.6% 🔺)0.255s531.77x
10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.888s1.071s0.000s1.077s0.189s571.00x
🐘 PostgresExpress0.964s (~)1.239s (-3.0%)0.000s (-6.1% 🟢)1.253s (-4.1%)0.289s491.09x
🐘 PostgresNitro1.040s (+7.3% 🔺)1.604s (+28.6% 🔺)0.000s (-36.8% 🟢)1.616s (+28.5% 🔺)0.576s381.17x
💻 LocalExpress1.106s (-9.7% 🟢)1.951s (-3.4%)0.000s (+35.5% 🔺)1.953s (-3.4%)0.848s311.25x
💻 LocalNext.js (Turbopack)1.263s2.020s0.000s2.023s0.760s301.42x
💻 LocalNitro1.397s (+14.2% 🔺)2.020s (~)0.000s (+221.4% 🔺)2.200s (+8.8% 🔺)0.803s281.57x
fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.751s2.105s0.000s2.120s0.369s291.00x
🐘 PostgresExpress1.761s (-0.6%)2.102s (-3.5%)0.000s (NaN%)2.113s (-3.9%)0.352s291.01x
🐘 PostgresNitro1.904s (+6.3% 🔺)2.293s (+7.1% 🔺)0.000s (+3.7%)2.307s (+6.1% 🔺)0.403s271.09x
💻 LocalExpress3.308s (-4.6%)3.779s (-6.3% 🟢)0.001s (-21.9% 🟢)3.781s (-6.3% 🟢)0.474s161.89x
💻 LocalNitro3.557s (+5.0% 🔺)4.097s (+1.6%)0.001s (+12.5% 🔺)4.100s (+1.6%)0.543s152.03x
💻 LocalNext.js (Turbopack)3.594s4.233s0.001s4.236s0.643s152.05x

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress18/21
🐘 PostgresNext.js (Turbopack)18/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres18/21
Next.js (Turbopack)🐘 Postgres21/21
Nitro🐘 Postgres17/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run


Some benchmark jobs failed:

  • Local: success
  • Postgres: success
  • Vercel: failure

Check the workflow run for details.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support in @workflow/world-vercel for sending Vercel Deployment Protection bypass credentials via WORKFLOW_VERCEL_PROTECTION_BYPASS, ensuring outbound requests can access protected preview/production deployments.

Changes:

  • Introduces getProtectionBypassHeader() helper to conditionally produce the x-vercel-protection-bypass header.
  • Injects the bypass header into the shared getHeaders() path (covers makeRequest/streamer/refs).
  • Spreads the bypass header into direct fetch() calls in resolve-latest-deployment.ts and encryption.ts.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

FileDescription
packages/world-vercel/src/utils.tsAdds bypass-header helper and includes bypass header in shared header construction.
packages/world-vercel/src/resolve-latest-deployment.tsAdds bypass header to direct Vercel API request headers.
packages/world-vercel/src/encryption.tsAdds bypass header to direct Vercel API request headers.
.changeset/world-vercel-protection-bypass.mdDeclares a minor release for the new env var behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadpackages/world-vercel/src/resolve-latest-deployment.ts Outdated
Comment threadpackages/world-vercel/src/encryption.ts Outdated
Comment threadpackages/world-vercel/src/utils.ts Outdated
Comment threadpackages/world-vercel/src/utils.ts
Replace hard-coded WORKFLOW_SERVER_URL_OVERRIDE constant with a function
that reads from the VERCEL_WORKFLOW_SERVER_URL env var. Allows configuring
the workflow-server URL per-deployment (e.g. workbench Preview envs
pointing to a branch deployment) without editing source.
Set VERCEL_WORKFLOW_SERVER_URL and VERCEL_WORKFLOW_SERVER_PROTECTION_BYPASS
on PR runs so e2e tests hit the protected workflow-server preview; leave
unset on main so production runs use the public default URL.

@karthikscale3karthikscale3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good. the codex review comments are worth addressing

- Consolidate bypass header logic in getHeaders() to reuse
getProtectionBypassHeader() instead of duplicating env lookup.
- Use consistent 'Authorization' casing in direct fetch() calls.
- Add unit tests for getProtectionBypassHeader, getHttpUrl, and getHeaders
covering env var toggling and proxy/override combinations.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-stableCherry-pick this PR to the stable branch when merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@TooTallNate@karthikscale3
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(world-vercel): support new env vars for Vercel Deployment Protection - #1824

Merged
TooTallNate merged 6 commits into
mainfrom
world-vercel-protection-bypass
Apr 22, 2026
Merged

feat(world-vercel): support new env vars for Vercel Deployment Protection#1824
TooTallNate merged 6 commits into
mainfrom
world-vercel-protection-bypass

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Apr 21, 2026

Copy link
Copy Markdown
Member

Summary

Adds two new environment variables to @workflow/world-vercel for use with Vercel Deployment Protection.

VERCEL_WORKFLOW_SERVER_PROTECTION_BYPASS

When set, the value is sent as the x-vercel-protection-bypass header on every outbound HTTP request made by the Vercel world (via makeRequest, the streamer, refs, and direct api.vercel.com calls in resolve-latest-deployment.ts and encryption.ts).

Needed because workflow-server is getting Vercel Deployment Protection enabled, so external callers need a way to authenticate bypass.

VERCEL_WORKFLOW_SERVER_URL

Replaces the need to edit source to change the workflow-server URL. When set, requests bypass the default production host (https://vercel-workflow.com) and use the override instead. When going through the api.vercel.com/v1/workflow proxy, the value is forwarded via the x-vercel-workflow-api-url header so the proxy routes accordingly.

The existing inline WORKFLOW_SERVER_URL_OVERRIDE const is preserved as an empty-string literal so external CI rewrite tooling continues to work unmodified; the inline const wins over the env var when non-empty.

Implementation

  • New getProtectionBypassHeader() helper in utils.ts returns the bypass header when the env var is set.
  • getHeaders() applies the bypass header automatically (covers makeRequest, streamer, refs).
  • Direct api.vercel.com fetches in resolve-latest-deployment.ts and encryption.ts spread the helper into their headers.
  • New getWorkflowServerUrlOverride() function prefers the inline const, falls back to VERCEL_WORKFLOW_SERVER_URL.
  • The bypass header passes through the api.vercel.com/v1/workflow proxy transparently — http-proxy-middleware forwards all request headers by default, so no proxy-side changes needed.

Testing

  • pnpm --filter @workflow/world-vercel typecheck
  • pnpm --filter @workflow/world-vercel test — 79 tests pass ✅

Allows sending a Vercel Deployment Protection bypass secret via the
`x-vercel-protection-bypass` header on all outbound requests made by
the Vercel world, enabling use against protected deployments (e.g.
previews, or workflow-server once protection is enabled).
CopilotAI review requested due to automatic review settings April 21, 2026 21:49
@TooTallNate
TooTallNate requested a review from a team as a code ownerApril 21, 2026 21:49
@vercel

vercelBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

@changeset-bot

changeset-botBot commented Apr 21, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 515010b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 18 packages
NameType
@workflow/world-vercelMinor
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
workflowPatch
@workflow/world-testingPatch
@workflow/buildersPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/vitestPatch
@workflow/web-sharedPatch
@workflow/aiPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actionsBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ 💻 Local Development10540861140
✅ 📦 Local Production10540861140
❌ 🐘 Local Postgres10522861140
✅ 🪟 Windows950095
✅ 📋 Other267018285
Total352222763800

❌ Failed Tests

🐘 Local Postgres (2 failed)

nuxt-stable (2 failed):

  • fibonacciWorkflow - recursive workflow composition via start()
  • health check (queue-based) - workflow and step endpoints respond to health check messages

Details by Category

✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
❌ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
❌ nuxt-stable8726
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9500
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8906
✅ e2e-local-postgres-nest-stable8906
✅ e2e-local-prod-nest-stable8906

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: success
  • Local Prod: success
  • Local Postgres: failure
  • Windows: success

Check the workflow run for details.

@github-actions

github-actionsBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.033s (-25.1% 🟢)1.004s (~)0.971s101.00x
💻 LocalNitro0.043s (~)1.005s (~)0.962s101.30x
🐘 PostgresNext.js (Turbopack)0.046s1.009s0.963s101.39x
💻 LocalNext.js (Turbopack)0.048s1.006s0.957s101.45x
🐘 PostgresExpress0.059s (+2.4%)1.012s (~)0.953s101.79x
🐘 PostgresNitro0.064s (-33.1% 🟢)1.010s (-3.1%)0.947s101.92x
workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.105s (-1.8%)2.005s (~)0.900s101.00x
🐘 PostgresNext.js (Turbopack)1.116s2.009s0.893s101.01x
💻 LocalNext.js (Turbopack)1.123s2.007s0.884s101.02x
💻 LocalNitro1.125s (-0.5%)2.006s (~)0.881s101.02x
🐘 PostgresExpress1.144s (~)2.009s (~)0.865s101.03x
🐘 PostgresNitro1.152s (+1.0%)2.012s (~)0.860s101.04x
workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)10.694s11.020s0.326s31.00x
💻 LocalExpress10.758s (-1.5%)11.022s (~)0.264s31.01x
💻 LocalNext.js (Turbopack)10.827s11.025s0.198s31.01x
🐘 PostgresExpress10.847s (-1.1%)11.020s (~)0.173s31.01x
💻 LocalNitro10.934s (~)11.023s (~)0.089s31.02x
🐘 PostgresNitro10.955s (+0.8%)11.026s (~)0.070s31.02x
workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)14.091s15.020s0.929s41.00x
🐘 PostgresExpress14.532s (~)15.020s (~)0.488s41.03x
💻 LocalExpress14.548s (-2.8%)15.029s (~)0.481s41.03x
💻 LocalNext.js (Turbopack)14.628s15.029s0.401s41.04x
🐘 PostgresNitro14.704s (+0.7%)15.028s (~)0.324s41.04x
💻 LocalNitro14.960s (-0.7%)15.030s (-6.2% 🟢)0.070s41.06x
workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)13.144s13.881s0.737s71.00x
🐘 PostgresExpress13.862s (-1.0%)14.024s (-3.9%)0.162s71.05x
🐘 PostgresNitro14.311s (+2.5%)15.021s (+5.0%)0.710s61.09x
💻 LocalExpress15.112s (-9.0% 🟢)16.028s (-5.9% 🟢)0.916s61.15x
💻 LocalNext.js (Turbopack)16.172s17.031s0.859s61.23x
💻 LocalNitro16.642s (-0.8%)17.029s (~)0.387s61.27x
Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.185s2.008s0.823s151.00x
🐘 PostgresExpress1.263s (~)2.010s (~)0.747s151.07x
🐘 PostgresNitro1.282s (+0.6%)2.010s (~)0.728s151.08x
💻 LocalExpress1.436s (-3.6%)2.008s (~)0.573s151.21x
💻 LocalNext.js (Turbopack)1.525s2.005s0.481s151.29x
💻 LocalNitro1.873s (+14.8% 🔺)2.392s (+15.3% 🔺)0.519s131.58x
Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)2.349s3.008s0.659s101.00x
🐘 PostgresExpress2.363s (~)3.009s (~)0.646s101.01x
🐘 PostgresNitro2.400s (+2.1%)3.011s (~)0.611s101.02x
💻 LocalExpress2.521s (-14.6% 🟢)3.007s (-12.9% 🟢)0.486s101.07x
💻 LocalNext.js (Turbopack)2.837s3.565s0.728s91.21x
💻 LocalNitro3.050s (-3.0%)3.760s (-3.2%)0.711s81.30x
Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express3.466s (-0.6%)4.010s (~)0.544s81.00x
🐘 PostgresNitro3.476s (~)4.011s (~)0.536s81.00x
🐘 PostgresNext.js (Turbopack)3.514s4.010s0.495s81.01x
💻 LocalExpress6.216s (-25.5% 🟢)6.814s (-24.5% 🟢)0.599s51.79x
💻 LocalNitro8.493s (+1.7%)9.025s (~)0.532s42.45x
💻 LocalNext.js (Turbopack)8.680s9.271s0.591s42.50x
Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.170s2.007s0.837s151.00x
🐘 PostgresExpress1.265s (+0.6%)2.008s (~)0.743s151.08x
🐘 PostgresNitro1.279s (+1.8%)2.009s (~)0.730s151.09x
💻 LocalNitro1.526s (-18.2% 🟢)2.005s (-14.3% 🟢)0.479s151.30x
💻 LocalNext.js (Turbopack)1.553s2.005s0.452s151.33x
💻 LocalExpress1.583s (-16.4% 🟢)2.109s (-10.8% 🟢)0.526s151.35x
Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.345s (~)3.009s (~)0.664s101.00x
🐘 PostgresNitro2.368s (+1.2%)3.011s (~)0.643s101.01x
🐘 PostgresNext.js (Turbopack)2.418s3.010s0.592s101.03x
💻 LocalExpress2.505s (-20.0% 🟢)3.007s (-20.1% 🟢)0.502s101.07x
💻 LocalNext.js (Turbopack)2.934s3.759s0.825s81.25x
💻 LocalNitro3.017s (-1.6%)3.759s (-3.3%)0.742s81.29x
Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express3.473s (-0.7%)4.011s (~)0.538s81.00x
🐘 PostgresNitro3.525s (+1.3%)4.010s (~)0.485s81.01x
🐘 PostgresNext.js (Turbopack)3.556s4.010s0.454s81.02x
💻 LocalExpress6.601s (-25.0% 🟢)7.222s (-22.1% 🟢)0.621s51.90x
💻 LocalNext.js (Turbopack)8.335s8.518s0.183s42.40x
💻 LocalNitro8.823s (-3.5%)9.273s (-7.5% 🟢)0.450s42.54x
workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.618s1.006s0.388s601.00x
🐘 PostgresExpress0.836s (~)1.041s (+1.7%)0.205s581.35x
💻 LocalNext.js (Turbopack)0.851s1.021s0.170s591.38x
🐘 PostgresNitro0.856s (+4.4%)1.023s (+1.7%)0.167s591.39x
💻 LocalExpress0.871s (-11.5% 🟢)1.095s (+1.7%)0.224s551.41x
💻 LocalNitro0.983s (~)1.076s (-1.6%)0.094s561.59x
workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.513s2.008s0.495s451.00x
🐘 PostgresExpress1.920s (-2.9%)2.053s (-9.1% 🟢)0.133s441.27x
🐘 PostgresNitro2.079s (+7.9% 🔺)2.945s (+40.2% 🔺)0.866s311.37x
💻 LocalExpress2.691s (-10.8% 🟢)3.110s (-13.3% 🟢)0.420s291.78x
💻 LocalNext.js (Turbopack)2.691s3.008s0.317s301.78x
💻 LocalNitro3.040s (~)3.842s (+2.2%)0.802s242.01x
workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)3.056s3.822s0.766s321.00x
🐘 PostgresExpress3.863s (-3.2%)4.077s (-6.7% 🟢)0.214s301.26x
🐘 PostgresNitro4.238s (+3.3%)5.013s (+8.9% 🔺)0.775s241.39x
💻 LocalExpress7.711s (-16.3% 🟢)8.214s (-18.0% 🟢)0.503s152.52x
💻 LocalNext.js (Turbopack)8.787s9.161s0.374s142.87x
💻 LocalNitro9.222s (-0.8%)9.787s (-2.3%)0.566s133.02x
workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.195s1.006s0.811s601.00x
🐘 PostgresExpress0.285s (+1.1%)1.007s (~)0.722s601.46x
🐘 PostgresNitro0.300s (+6.0% 🔺)1.008s (~)0.708s601.54x
💻 LocalExpress0.505s (-10.0% 🟢)1.004s (~)0.499s602.59x
💻 LocalNext.js (Turbopack)0.560s1.004s0.445s602.87x
💻 LocalNitro0.604s (~)1.022s (~)0.417s593.10x
workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.406s1.006s0.599s901.00x
🐘 PostgresExpress0.488s (-4.2%)1.006s (~)0.518s901.20x
🐘 PostgresNitro0.532s (+7.1% 🔺)1.007s (~)0.475s901.31x
💻 LocalExpress2.239s (-10.9% 🟢)3.013s (~)0.774s305.51x
💻 LocalNitro2.539s (~)3.009s (~)0.471s306.25x
💻 LocalNext.js (Turbopack)2.644s3.009s0.365s306.50x
workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.621s1.006s0.385s1201.00x
🐘 PostgresExpress0.800s (-2.3%)1.008s (-0.9%)0.208s1201.29x
🐘 PostgresNitro0.880s (+11.4% 🔺)1.021s (+1.3%)0.140s1181.42x
💻 LocalExpress8.989s (-19.7% 🟢)9.483s (-20.6% 🟢)0.494s1314.48x
💻 LocalNext.js (Turbopack)10.772s11.392s0.620s1117.36x
💻 LocalNitro11.168s (~)11.756s (+0.8%)0.588s1118.00x
Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.166s1.000s0.001s1.010s0.844s101.00x
💻 LocalNext.js (Turbopack)0.171s1.003s0.013s1.019s0.848s101.03x
🐘 PostgresExpress0.200s (-2.6%)0.998s (~)0.001s (-12.5% 🟢)1.010s (~)0.810s101.20x
💻 LocalNitro0.201s (-5.9% 🟢)1.004s (~)0.012s (-4.0%)1.018s (~)0.817s101.21x
💻 LocalExpress0.202s (+1.3%)1.003s (~)0.008s (-35.5% 🟢)1.013s (-0.5%)0.811s101.21x
🐘 PostgresNitro0.224s (+9.2% 🔺)0.997s (~)0.001s (-13.3% 🟢)1.011s (~)0.787s101.35x
stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.541s1.026s0.003s1.037s0.496s581.00x
🐘 PostgresExpress0.609s (-3.3%)1.005s (~)0.011s (+194.7% 🔺)1.031s (+0.8%)0.422s591.13x
💻 LocalExpress0.663s (-12.4% 🟢)1.028s (~)0.007s (-28.4% 🟢)1.036s (~)0.373s581.23x
🐘 PostgresNitro0.682s (+9.3% 🔺)1.022s (+1.6%)0.004s (+8.4% 🔺)1.041s (+1.8%)0.359s581.26x
💻 LocalNext.js (Turbopack)0.770s1.030s0.010s1.137s0.367s531.42x
💻 LocalNitro0.957s (+14.1% 🔺)1.012s (~)0.009s (-2.9%)1.212s (+8.6% 🔺)0.255s531.77x
10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.888s1.071s0.000s1.077s0.189s571.00x
🐘 PostgresExpress0.964s (~)1.239s (-3.0%)0.000s (-6.1% 🟢)1.253s (-4.1%)0.289s491.09x
🐘 PostgresNitro1.040s (+7.3% 🔺)1.604s (+28.6% 🔺)0.000s (-36.8% 🟢)1.616s (+28.5% 🔺)0.576s381.17x
💻 LocalExpress1.106s (-9.7% 🟢)1.951s (-3.4%)0.000s (+35.5% 🔺)1.953s (-3.4%)0.848s311.25x
💻 LocalNext.js (Turbopack)1.263s2.020s0.000s2.023s0.760s301.42x
💻 LocalNitro1.397s (+14.2% 🔺)2.020s (~)0.000s (+221.4% 🔺)2.200s (+8.8% 🔺)0.803s281.57x
fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.751s2.105s0.000s2.120s0.369s291.00x
🐘 PostgresExpress1.761s (-0.6%)2.102s (-3.5%)0.000s (NaN%)2.113s (-3.9%)0.352s291.01x
🐘 PostgresNitro1.904s (+6.3% 🔺)2.293s (+7.1% 🔺)0.000s (+3.7%)2.307s (+6.1% 🔺)0.403s271.09x
💻 LocalExpress3.308s (-4.6%)3.779s (-6.3% 🟢)0.001s (-21.9% 🟢)3.781s (-6.3% 🟢)0.474s161.89x
💻 LocalNitro3.557s (+5.0% 🔺)4.097s (+1.6%)0.001s (+12.5% 🔺)4.100s (+1.6%)0.543s152.03x
💻 LocalNext.js (Turbopack)3.594s4.233s0.001s4.236s0.643s152.05x

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress18/21
🐘 PostgresNext.js (Turbopack)18/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres18/21
Next.js (Turbopack)🐘 Postgres21/21
Nitro🐘 Postgres17/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run


Some benchmark jobs failed:

  • Local: success
  • Postgres: success
  • Vercel: failure

Check the workflow run for details.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support in @workflow/world-vercel for sending Vercel Deployment Protection bypass credentials via WORKFLOW_VERCEL_PROTECTION_BYPASS, ensuring outbound requests can access protected preview/production deployments.

Changes:

  • Introduces getProtectionBypassHeader() helper to conditionally produce the x-vercel-protection-bypass header.
  • Injects the bypass header into the shared getHeaders() path (covers makeRequest/streamer/refs).
  • Spreads the bypass header into direct fetch() calls in resolve-latest-deployment.ts and encryption.ts.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

FileDescription
packages/world-vercel/src/utils.tsAdds bypass-header helper and includes bypass header in shared header construction.
packages/world-vercel/src/resolve-latest-deployment.tsAdds bypass header to direct Vercel API request headers.
packages/world-vercel/src/encryption.tsAdds bypass header to direct Vercel API request headers.
.changeset/world-vercel-protection-bypass.mdDeclares a minor release for the new env var behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadpackages/world-vercel/src/resolve-latest-deployment.ts Outdated
Comment threadpackages/world-vercel/src/encryption.ts Outdated
Comment threadpackages/world-vercel/src/utils.ts Outdated
Comment threadpackages/world-vercel/src/utils.ts
Replace hard-coded WORKFLOW_SERVER_URL_OVERRIDE constant with a function
that reads from the VERCEL_WORKFLOW_SERVER_URL env var. Allows configuring
the workflow-server URL per-deployment (e.g. workbench Preview envs
pointing to a branch deployment) without editing source.
Set VERCEL_WORKFLOW_SERVER_URL and VERCEL_WORKFLOW_SERVER_PROTECTION_BYPASS
on PR runs so e2e tests hit the protected workflow-server preview; leave
unset on main so production runs use the public default URL.

@karthikscale3karthikscale3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good. the codex review comments are worth addressing

- Consolidate bypass header logic in getHeaders() to reuse
getProtectionBypassHeader() instead of duplicating env lookup.
- Use consistent 'Authorization' casing in direct fetch() calls.
- Add unit tests for getProtectionBypassHeader, getHttpUrl, and getHeaders
covering env var toggling and proxy/override combinations.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-stableCherry-pick this PR to the stable branch when merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@TooTallNate@karthikscale3
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(world-vercel): support new env vars for Vercel Deployment Protection - #1824

Merged
TooTallNate merged 6 commits into
mainfrom
world-vercel-protection-bypass
Apr 22, 2026
Merged

feat(world-vercel): support new env vars for Vercel Deployment Protection#1824
TooTallNate merged 6 commits into
mainfrom
world-vercel-protection-bypass

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Apr 21, 2026

Copy link
Copy Markdown
Member

Summary

Adds two new environment variables to @workflow/world-vercel for use with Vercel Deployment Protection.

VERCEL_WORKFLOW_SERVER_PROTECTION_BYPASS

When set, the value is sent as the x-vercel-protection-bypass header on every outbound HTTP request made by the Vercel world (via makeRequest, the streamer, refs, and direct api.vercel.com calls in resolve-latest-deployment.ts and encryption.ts).

Needed because workflow-server is getting Vercel Deployment Protection enabled, so external callers need a way to authenticate bypass.

VERCEL_WORKFLOW_SERVER_URL

Replaces the need to edit source to change the workflow-server URL. When set, requests bypass the default production host (https://vercel-workflow.com) and use the override instead. When going through the api.vercel.com/v1/workflow proxy, the value is forwarded via the x-vercel-workflow-api-url header so the proxy routes accordingly.

The existing inline WORKFLOW_SERVER_URL_OVERRIDE const is preserved as an empty-string literal so external CI rewrite tooling continues to work unmodified; the inline const wins over the env var when non-empty.

Implementation

  • New getProtectionBypassHeader() helper in utils.ts returns the bypass header when the env var is set.
  • getHeaders() applies the bypass header automatically (covers makeRequest, streamer, refs).
  • Direct api.vercel.com fetches in resolve-latest-deployment.ts and encryption.ts spread the helper into their headers.
  • New getWorkflowServerUrlOverride() function prefers the inline const, falls back to VERCEL_WORKFLOW_SERVER_URL.
  • The bypass header passes through the api.vercel.com/v1/workflow proxy transparently — http-proxy-middleware forwards all request headers by default, so no proxy-side changes needed.

Testing

  • pnpm --filter @workflow/world-vercel typecheck
  • pnpm --filter @workflow/world-vercel test — 79 tests pass ✅

Allows sending a Vercel Deployment Protection bypass secret via the
`x-vercel-protection-bypass` header on all outbound requests made by
the Vercel world, enabling use against protected deployments (e.g.
previews, or workflow-server once protection is enabled).
CopilotAI review requested due to automatic review settings April 21, 2026 21:49
@TooTallNate
TooTallNate requested a review from a team as a code ownerApril 21, 2026 21:49
@vercel

vercelBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

@changeset-bot

changeset-botBot commented Apr 21, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 515010b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 18 packages
NameType
@workflow/world-vercelMinor
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
workflowPatch
@workflow/world-testingPatch
@workflow/buildersPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/vitestPatch
@workflow/web-sharedPatch
@workflow/aiPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actionsBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ 💻 Local Development10540861140
✅ 📦 Local Production10540861140
❌ 🐘 Local Postgres10522861140
✅ 🪟 Windows950095
✅ 📋 Other267018285
Total352222763800

❌ Failed Tests

🐘 Local Postgres (2 failed)

nuxt-stable (2 failed):

  • fibonacciWorkflow - recursive workflow composition via start()
  • health check (queue-based) - workflow and step endpoints respond to health check messages

Details by Category

✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
❌ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
❌ nuxt-stable8726
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9500
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8906
✅ e2e-local-postgres-nest-stable8906
✅ e2e-local-prod-nest-stable8906

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: success
  • Local Prod: success
  • Local Postgres: failure
  • Windows: success

Check the workflow run for details.

@github-actions

github-actionsBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.033s (-25.1% 🟢)1.004s (~)0.971s101.00x
💻 LocalNitro0.043s (~)1.005s (~)0.962s101.30x
🐘 PostgresNext.js (Turbopack)0.046s1.009s0.963s101.39x
💻 LocalNext.js (Turbopack)0.048s1.006s0.957s101.45x
🐘 PostgresExpress0.059s (+2.4%)1.012s (~)0.953s101.79x
🐘 PostgresNitro0.064s (-33.1% 🟢)1.010s (-3.1%)0.947s101.92x
workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.105s (-1.8%)2.005s (~)0.900s101.00x
🐘 PostgresNext.js (Turbopack)1.116s2.009s0.893s101.01x
💻 LocalNext.js (Turbopack)1.123s2.007s0.884s101.02x
💻 LocalNitro1.125s (-0.5%)2.006s (~)0.881s101.02x
🐘 PostgresExpress1.144s (~)2.009s (~)0.865s101.03x
🐘 PostgresNitro1.152s (+1.0%)2.012s (~)0.860s101.04x
workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)10.694s11.020s0.326s31.00x
💻 LocalExpress10.758s (-1.5%)11.022s (~)0.264s31.01x
💻 LocalNext.js (Turbopack)10.827s11.025s0.198s31.01x
🐘 PostgresExpress10.847s (-1.1%)11.020s (~)0.173s31.01x
💻 LocalNitro10.934s (~)11.023s (~)0.089s31.02x
🐘 PostgresNitro10.955s (+0.8%)11.026s (~)0.070s31.02x
workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)14.091s15.020s0.929s41.00x
🐘 PostgresExpress14.532s (~)15.020s (~)0.488s41.03x
💻 LocalExpress14.548s (-2.8%)15.029s (~)0.481s41.03x
💻 LocalNext.js (Turbopack)14.628s15.029s0.401s41.04x
🐘 PostgresNitro14.704s (+0.7%)15.028s (~)0.324s41.04x
💻 LocalNitro14.960s (-0.7%)15.030s (-6.2% 🟢)0.070s41.06x
workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)13.144s13.881s0.737s71.00x
🐘 PostgresExpress13.862s (-1.0%)14.024s (-3.9%)0.162s71.05x
🐘 PostgresNitro14.311s (+2.5%)15.021s (+5.0%)0.710s61.09x
💻 LocalExpress15.112s (-9.0% 🟢)16.028s (-5.9% 🟢)0.916s61.15x
💻 LocalNext.js (Turbopack)16.172s17.031s0.859s61.23x
💻 LocalNitro16.642s (-0.8%)17.029s (~)0.387s61.27x
Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.185s2.008s0.823s151.00x
🐘 PostgresExpress1.263s (~)2.010s (~)0.747s151.07x
🐘 PostgresNitro1.282s (+0.6%)2.010s (~)0.728s151.08x
💻 LocalExpress1.436s (-3.6%)2.008s (~)0.573s151.21x
💻 LocalNext.js (Turbopack)1.525s2.005s0.481s151.29x
💻 LocalNitro1.873s (+14.8% 🔺)2.392s (+15.3% 🔺)0.519s131.58x
Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)2.349s3.008s0.659s101.00x
🐘 PostgresExpress2.363s (~)3.009s (~)0.646s101.01x
🐘 PostgresNitro2.400s (+2.1%)3.011s (~)0.611s101.02x
💻 LocalExpress2.521s (-14.6% 🟢)3.007s (-12.9% 🟢)0.486s101.07x
💻 LocalNext.js (Turbopack)2.837s3.565s0.728s91.21x
💻 LocalNitro3.050s (-3.0%)3.760s (-3.2%)0.711s81.30x
Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express3.466s (-0.6%)4.010s (~)0.544s81.00x
🐘 PostgresNitro3.476s (~)4.011s (~)0.536s81.00x
🐘 PostgresNext.js (Turbopack)3.514s4.010s0.495s81.01x
💻 LocalExpress6.216s (-25.5% 🟢)6.814s (-24.5% 🟢)0.599s51.79x
💻 LocalNitro8.493s (+1.7%)9.025s (~)0.532s42.45x
💻 LocalNext.js (Turbopack)8.680s9.271s0.591s42.50x
Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.170s2.007s0.837s151.00x
🐘 PostgresExpress1.265s (+0.6%)2.008s (~)0.743s151.08x
🐘 PostgresNitro1.279s (+1.8%)2.009s (~)0.730s151.09x
💻 LocalNitro1.526s (-18.2% 🟢)2.005s (-14.3% 🟢)0.479s151.30x
💻 LocalNext.js (Turbopack)1.553s2.005s0.452s151.33x
💻 LocalExpress1.583s (-16.4% 🟢)2.109s (-10.8% 🟢)0.526s151.35x
Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.345s (~)3.009s (~)0.664s101.00x
🐘 PostgresNitro2.368s (+1.2%)3.011s (~)0.643s101.01x
🐘 PostgresNext.js (Turbopack)2.418s3.010s0.592s101.03x
💻 LocalExpress2.505s (-20.0% 🟢)3.007s (-20.1% 🟢)0.502s101.07x
💻 LocalNext.js (Turbopack)2.934s3.759s0.825s81.25x
💻 LocalNitro3.017s (-1.6%)3.759s (-3.3%)0.742s81.29x
Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express3.473s (-0.7%)4.011s (~)0.538s81.00x
🐘 PostgresNitro3.525s (+1.3%)4.010s (~)0.485s81.01x
🐘 PostgresNext.js (Turbopack)3.556s4.010s0.454s81.02x
💻 LocalExpress6.601s (-25.0% 🟢)7.222s (-22.1% 🟢)0.621s51.90x
💻 LocalNext.js (Turbopack)8.335s8.518s0.183s42.40x
💻 LocalNitro8.823s (-3.5%)9.273s (-7.5% 🟢)0.450s42.54x
workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.618s1.006s0.388s601.00x
🐘 PostgresExpress0.836s (~)1.041s (+1.7%)0.205s581.35x
💻 LocalNext.js (Turbopack)0.851s1.021s0.170s591.38x
🐘 PostgresNitro0.856s (+4.4%)1.023s (+1.7%)0.167s591.39x
💻 LocalExpress0.871s (-11.5% 🟢)1.095s (+1.7%)0.224s551.41x
💻 LocalNitro0.983s (~)1.076s (-1.6%)0.094s561.59x
workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.513s2.008s0.495s451.00x
🐘 PostgresExpress1.920s (-2.9%)2.053s (-9.1% 🟢)0.133s441.27x
🐘 PostgresNitro2.079s (+7.9% 🔺)2.945s (+40.2% 🔺)0.866s311.37x
💻 LocalExpress2.691s (-10.8% 🟢)3.110s (-13.3% 🟢)0.420s291.78x
💻 LocalNext.js (Turbopack)2.691s3.008s0.317s301.78x
💻 LocalNitro3.040s (~)3.842s (+2.2%)0.802s242.01x
workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)3.056s3.822s0.766s321.00x
🐘 PostgresExpress3.863s (-3.2%)4.077s (-6.7% 🟢)0.214s301.26x
🐘 PostgresNitro4.238s (+3.3%)5.013s (+8.9% 🔺)0.775s241.39x
💻 LocalExpress7.711s (-16.3% 🟢)8.214s (-18.0% 🟢)0.503s152.52x
💻 LocalNext.js (Turbopack)8.787s9.161s0.374s142.87x
💻 LocalNitro9.222s (-0.8%)9.787s (-2.3%)0.566s133.02x
workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.195s1.006s0.811s601.00x
🐘 PostgresExpress0.285s (+1.1%)1.007s (~)0.722s601.46x
🐘 PostgresNitro0.300s (+6.0% 🔺)1.008s (~)0.708s601.54x
💻 LocalExpress0.505s (-10.0% 🟢)1.004s (~)0.499s602.59x
💻 LocalNext.js (Turbopack)0.560s1.004s0.445s602.87x
💻 LocalNitro0.604s (~)1.022s (~)0.417s593.10x
workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.406s1.006s0.599s901.00x
🐘 PostgresExpress0.488s (-4.2%)1.006s (~)0.518s901.20x
🐘 PostgresNitro0.532s (+7.1% 🔺)1.007s (~)0.475s901.31x
💻 LocalExpress2.239s (-10.9% 🟢)3.013s (~)0.774s305.51x
💻 LocalNitro2.539s (~)3.009s (~)0.471s306.25x
💻 LocalNext.js (Turbopack)2.644s3.009s0.365s306.50x
workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.621s1.006s0.385s1201.00x
🐘 PostgresExpress0.800s (-2.3%)1.008s (-0.9%)0.208s1201.29x
🐘 PostgresNitro0.880s (+11.4% 🔺)1.021s (+1.3%)0.140s1181.42x
💻 LocalExpress8.989s (-19.7% 🟢)9.483s (-20.6% 🟢)0.494s1314.48x
💻 LocalNext.js (Turbopack)10.772s11.392s0.620s1117.36x
💻 LocalNitro11.168s (~)11.756s (+0.8%)0.588s1118.00x
Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.166s1.000s0.001s1.010s0.844s101.00x
💻 LocalNext.js (Turbopack)0.171s1.003s0.013s1.019s0.848s101.03x
🐘 PostgresExpress0.200s (-2.6%)0.998s (~)0.001s (-12.5% 🟢)1.010s (~)0.810s101.20x
💻 LocalNitro0.201s (-5.9% 🟢)1.004s (~)0.012s (-4.0%)1.018s (~)0.817s101.21x
💻 LocalExpress0.202s (+1.3%)1.003s (~)0.008s (-35.5% 🟢)1.013s (-0.5%)0.811s101.21x
🐘 PostgresNitro0.224s (+9.2% 🔺)0.997s (~)0.001s (-13.3% 🟢)1.011s (~)0.787s101.35x
stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.541s1.026s0.003s1.037s0.496s581.00x
🐘 PostgresExpress0.609s (-3.3%)1.005s (~)0.011s (+194.7% 🔺)1.031s (+0.8%)0.422s591.13x
💻 LocalExpress0.663s (-12.4% 🟢)1.028s (~)0.007s (-28.4% 🟢)1.036s (~)0.373s581.23x
🐘 PostgresNitro0.682s (+9.3% 🔺)1.022s (+1.6%)0.004s (+8.4% 🔺)1.041s (+1.8%)0.359s581.26x
💻 LocalNext.js (Turbopack)0.770s1.030s0.010s1.137s0.367s531.42x
💻 LocalNitro0.957s (+14.1% 🔺)1.012s (~)0.009s (-2.9%)1.212s (+8.6% 🔺)0.255s531.77x
10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.888s1.071s0.000s1.077s0.189s571.00x
🐘 PostgresExpress0.964s (~)1.239s (-3.0%)0.000s (-6.1% 🟢)1.253s (-4.1%)0.289s491.09x
🐘 PostgresNitro1.040s (+7.3% 🔺)1.604s (+28.6% 🔺)0.000s (-36.8% 🟢)1.616s (+28.5% 🔺)0.576s381.17x
💻 LocalExpress1.106s (-9.7% 🟢)1.951s (-3.4%)0.000s (+35.5% 🔺)1.953s (-3.4%)0.848s311.25x
💻 LocalNext.js (Turbopack)1.263s2.020s0.000s2.023s0.760s301.42x
💻 LocalNitro1.397s (+14.2% 🔺)2.020s (~)0.000s (+221.4% 🔺)2.200s (+8.8% 🔺)0.803s281.57x
fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.751s2.105s0.000s2.120s0.369s291.00x
🐘 PostgresExpress1.761s (-0.6%)2.102s (-3.5%)0.000s (NaN%)2.113s (-3.9%)0.352s291.01x
🐘 PostgresNitro1.904s (+6.3% 🔺)2.293s (+7.1% 🔺)0.000s (+3.7%)2.307s (+6.1% 🔺)0.403s271.09x
💻 LocalExpress3.308s (-4.6%)3.779s (-6.3% 🟢)0.001s (-21.9% 🟢)3.781s (-6.3% 🟢)0.474s161.89x
💻 LocalNitro3.557s (+5.0% 🔺)4.097s (+1.6%)0.001s (+12.5% 🔺)4.100s (+1.6%)0.543s152.03x
💻 LocalNext.js (Turbopack)3.594s4.233s0.001s4.236s0.643s152.05x

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress18/21
🐘 PostgresNext.js (Turbopack)18/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres18/21
Next.js (Turbopack)🐘 Postgres21/21
Nitro🐘 Postgres17/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run


Some benchmark jobs failed:

  • Local: success
  • Postgres: success
  • Vercel: failure

Check the workflow run for details.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support in @workflow/world-vercel for sending Vercel Deployment Protection bypass credentials via WORKFLOW_VERCEL_PROTECTION_BYPASS, ensuring outbound requests can access protected preview/production deployments.

Changes:

  • Introduces getProtectionBypassHeader() helper to conditionally produce the x-vercel-protection-bypass header.
  • Injects the bypass header into the shared getHeaders() path (covers makeRequest/streamer/refs).
  • Spreads the bypass header into direct fetch() calls in resolve-latest-deployment.ts and encryption.ts.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

FileDescription
packages/world-vercel/src/utils.tsAdds bypass-header helper and includes bypass header in shared header construction.
packages/world-vercel/src/resolve-latest-deployment.tsAdds bypass header to direct Vercel API request headers.
packages/world-vercel/src/encryption.tsAdds bypass header to direct Vercel API request headers.
.changeset/world-vercel-protection-bypass.mdDeclares a minor release for the new env var behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadpackages/world-vercel/src/resolve-latest-deployment.ts Outdated
Comment threadpackages/world-vercel/src/encryption.ts Outdated
Comment threadpackages/world-vercel/src/utils.ts Outdated
Comment threadpackages/world-vercel/src/utils.ts
Replace hard-coded WORKFLOW_SERVER_URL_OVERRIDE constant with a function
that reads from the VERCEL_WORKFLOW_SERVER_URL env var. Allows configuring
the workflow-server URL per-deployment (e.g. workbench Preview envs
pointing to a branch deployment) without editing source.
Set VERCEL_WORKFLOW_SERVER_URL and VERCEL_WORKFLOW_SERVER_PROTECTION_BYPASS
on PR runs so e2e tests hit the protected workflow-server preview; leave
unset on main so production runs use the public default URL.

@karthikscale3karthikscale3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good. the codex review comments are worth addressing

- Consolidate bypass header logic in getHeaders() to reuse
getProtectionBypassHeader() instead of duplicating env lookup.
- Use consistent 'Authorization' casing in direct fetch() calls.
- Add unit tests for getProtectionBypassHeader, getHttpUrl, and getHeaders
covering env var toggling and proxy/override combinations.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-stableCherry-pick this PR to the stable branch when merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@TooTallNate@karthikscale3
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(world-vercel): support new env vars for Vercel Deployment Protection - #1824

Merged
TooTallNate merged 6 commits into
mainfrom
world-vercel-protection-bypass
Apr 22, 2026
Merged

feat(world-vercel): support new env vars for Vercel Deployment Protection#1824
TooTallNate merged 6 commits into
mainfrom
world-vercel-protection-bypass

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Apr 21, 2026

Copy link
Copy Markdown
Member

Summary

Adds two new environment variables to @workflow/world-vercel for use with Vercel Deployment Protection.

VERCEL_WORKFLOW_SERVER_PROTECTION_BYPASS

When set, the value is sent as the x-vercel-protection-bypass header on every outbound HTTP request made by the Vercel world (via makeRequest, the streamer, refs, and direct api.vercel.com calls in resolve-latest-deployment.ts and encryption.ts).

Needed because workflow-server is getting Vercel Deployment Protection enabled, so external callers need a way to authenticate bypass.

VERCEL_WORKFLOW_SERVER_URL

Replaces the need to edit source to change the workflow-server URL. When set, requests bypass the default production host (https://vercel-workflow.com) and use the override instead. When going through the api.vercel.com/v1/workflow proxy, the value is forwarded via the x-vercel-workflow-api-url header so the proxy routes accordingly.

The existing inline WORKFLOW_SERVER_URL_OVERRIDE const is preserved as an empty-string literal so external CI rewrite tooling continues to work unmodified; the inline const wins over the env var when non-empty.

Implementation

  • New getProtectionBypassHeader() helper in utils.ts returns the bypass header when the env var is set.
  • getHeaders() applies the bypass header automatically (covers makeRequest, streamer, refs).
  • Direct api.vercel.com fetches in resolve-latest-deployment.ts and encryption.ts spread the helper into their headers.
  • New getWorkflowServerUrlOverride() function prefers the inline const, falls back to VERCEL_WORKFLOW_SERVER_URL.
  • The bypass header passes through the api.vercel.com/v1/workflow proxy transparently — http-proxy-middleware forwards all request headers by default, so no proxy-side changes needed.

Testing

  • pnpm --filter @workflow/world-vercel typecheck
  • pnpm --filter @workflow/world-vercel test — 79 tests pass ✅

Allows sending a Vercel Deployment Protection bypass secret via the
`x-vercel-protection-bypass` header on all outbound requests made by
the Vercel world, enabling use against protected deployments (e.g.
previews, or workflow-server once protection is enabled).
CopilotAI review requested due to automatic review settings April 21, 2026 21:49
@TooTallNate
TooTallNate requested a review from a team as a code ownerApril 21, 2026 21:49
@vercel

vercelBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

@changeset-bot

changeset-botBot commented Apr 21, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 515010b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 18 packages
NameType
@workflow/world-vercelMinor
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
workflowPatch
@workflow/world-testingPatch
@workflow/buildersPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/vitestPatch
@workflow/web-sharedPatch
@workflow/aiPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actionsBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ 💻 Local Development10540861140
✅ 📦 Local Production10540861140
❌ 🐘 Local Postgres10522861140
✅ 🪟 Windows950095
✅ 📋 Other267018285
Total352222763800

❌ Failed Tests

🐘 Local Postgres (2 failed)

nuxt-stable (2 failed):

  • fibonacciWorkflow - recursive workflow composition via start()
  • health check (queue-based) - workflow and step endpoints respond to health check messages

Details by Category

✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
❌ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
❌ nuxt-stable8726
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9500
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8906
✅ e2e-local-postgres-nest-stable8906
✅ e2e-local-prod-nest-stable8906

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: success
  • Local Prod: success
  • Local Postgres: failure
  • Windows: success

Check the workflow run for details.

@github-actions

github-actionsBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.033s (-25.1% 🟢)1.004s (~)0.971s101.00x
💻 LocalNitro0.043s (~)1.005s (~)0.962s101.30x
🐘 PostgresNext.js (Turbopack)0.046s1.009s0.963s101.39x
💻 LocalNext.js (Turbopack)0.048s1.006s0.957s101.45x
🐘 PostgresExpress0.059s (+2.4%)1.012s (~)0.953s101.79x
🐘 PostgresNitro0.064s (-33.1% 🟢)1.010s (-3.1%)0.947s101.92x
workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.105s (-1.8%)2.005s (~)0.900s101.00x
🐘 PostgresNext.js (Turbopack)1.116s2.009s0.893s101.01x
💻 LocalNext.js (Turbopack)1.123s2.007s0.884s101.02x
💻 LocalNitro1.125s (-0.5%)2.006s (~)0.881s101.02x
🐘 PostgresExpress1.144s (~)2.009s (~)0.865s101.03x
🐘 PostgresNitro1.152s (+1.0%)2.012s (~)0.860s101.04x
workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)10.694s11.020s0.326s31.00x
💻 LocalExpress10.758s (-1.5%)11.022s (~)0.264s31.01x
💻 LocalNext.js (Turbopack)10.827s11.025s0.198s31.01x
🐘 PostgresExpress10.847s (-1.1%)11.020s (~)0.173s31.01x
💻 LocalNitro10.934s (~)11.023s (~)0.089s31.02x
🐘 PostgresNitro10.955s (+0.8%)11.026s (~)0.070s31.02x
workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)14.091s15.020s0.929s41.00x
🐘 PostgresExpress14.532s (~)15.020s (~)0.488s41.03x
💻 LocalExpress14.548s (-2.8%)15.029s (~)0.481s41.03x
💻 LocalNext.js (Turbopack)14.628s15.029s0.401s41.04x
🐘 PostgresNitro14.704s (+0.7%)15.028s (~)0.324s41.04x
💻 LocalNitro14.960s (-0.7%)15.030s (-6.2% 🟢)0.070s41.06x
workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)13.144s13.881s0.737s71.00x
🐘 PostgresExpress13.862s (-1.0%)14.024s (-3.9%)0.162s71.05x
🐘 PostgresNitro14.311s (+2.5%)15.021s (+5.0%)0.710s61.09x
💻 LocalExpress15.112s (-9.0% 🟢)16.028s (-5.9% 🟢)0.916s61.15x
💻 LocalNext.js (Turbopack)16.172s17.031s0.859s61.23x
💻 LocalNitro16.642s (-0.8%)17.029s (~)0.387s61.27x
Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.185s2.008s0.823s151.00x
🐘 PostgresExpress1.263s (~)2.010s (~)0.747s151.07x
🐘 PostgresNitro1.282s (+0.6%)2.010s (~)0.728s151.08x
💻 LocalExpress1.436s (-3.6%)2.008s (~)0.573s151.21x
💻 LocalNext.js (Turbopack)1.525s2.005s0.481s151.29x
💻 LocalNitro1.873s (+14.8% 🔺)2.392s (+15.3% 🔺)0.519s131.58x
Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)2.349s3.008s0.659s101.00x
🐘 PostgresExpress2.363s (~)3.009s (~)0.646s101.01x
🐘 PostgresNitro2.400s (+2.1%)3.011s (~)0.611s101.02x
💻 LocalExpress2.521s (-14.6% 🟢)3.007s (-12.9% 🟢)0.486s101.07x
💻 LocalNext.js (Turbopack)2.837s3.565s0.728s91.21x
💻 LocalNitro3.050s (-3.0%)3.760s (-3.2%)0.711s81.30x
Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express3.466s (-0.6%)4.010s (~)0.544s81.00x
🐘 PostgresNitro3.476s (~)4.011s (~)0.536s81.00x
🐘 PostgresNext.js (Turbopack)3.514s4.010s0.495s81.01x
💻 LocalExpress6.216s (-25.5% 🟢)6.814s (-24.5% 🟢)0.599s51.79x
💻 LocalNitro8.493s (+1.7%)9.025s (~)0.532s42.45x
💻 LocalNext.js (Turbopack)8.680s9.271s0.591s42.50x
Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.170s2.007s0.837s151.00x
🐘 PostgresExpress1.265s (+0.6%)2.008s (~)0.743s151.08x
🐘 PostgresNitro1.279s (+1.8%)2.009s (~)0.730s151.09x
💻 LocalNitro1.526s (-18.2% 🟢)2.005s (-14.3% 🟢)0.479s151.30x
💻 LocalNext.js (Turbopack)1.553s2.005s0.452s151.33x
💻 LocalExpress1.583s (-16.4% 🟢)2.109s (-10.8% 🟢)0.526s151.35x
Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.345s (~)3.009s (~)0.664s101.00x
🐘 PostgresNitro2.368s (+1.2%)3.011s (~)0.643s101.01x
🐘 PostgresNext.js (Turbopack)2.418s3.010s0.592s101.03x
💻 LocalExpress2.505s (-20.0% 🟢)3.007s (-20.1% 🟢)0.502s101.07x
💻 LocalNext.js (Turbopack)2.934s3.759s0.825s81.25x
💻 LocalNitro3.017s (-1.6%)3.759s (-3.3%)0.742s81.29x
Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express3.473s (-0.7%)4.011s (~)0.538s81.00x
🐘 PostgresNitro3.525s (+1.3%)4.010s (~)0.485s81.01x
🐘 PostgresNext.js (Turbopack)3.556s4.010s0.454s81.02x
💻 LocalExpress6.601s (-25.0% 🟢)7.222s (-22.1% 🟢)0.621s51.90x
💻 LocalNext.js (Turbopack)8.335s8.518s0.183s42.40x
💻 LocalNitro8.823s (-3.5%)9.273s (-7.5% 🟢)0.450s42.54x
workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.618s1.006s0.388s601.00x
🐘 PostgresExpress0.836s (~)1.041s (+1.7%)0.205s581.35x
💻 LocalNext.js (Turbopack)0.851s1.021s0.170s591.38x
🐘 PostgresNitro0.856s (+4.4%)1.023s (+1.7%)0.167s591.39x
💻 LocalExpress0.871s (-11.5% 🟢)1.095s (+1.7%)0.224s551.41x
💻 LocalNitro0.983s (~)1.076s (-1.6%)0.094s561.59x
workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.513s2.008s0.495s451.00x
🐘 PostgresExpress1.920s (-2.9%)2.053s (-9.1% 🟢)0.133s441.27x
🐘 PostgresNitro2.079s (+7.9% 🔺)2.945s (+40.2% 🔺)0.866s311.37x
💻 LocalExpress2.691s (-10.8% 🟢)3.110s (-13.3% 🟢)0.420s291.78x
💻 LocalNext.js (Turbopack)2.691s3.008s0.317s301.78x
💻 LocalNitro3.040s (~)3.842s (+2.2%)0.802s242.01x
workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)3.056s3.822s0.766s321.00x
🐘 PostgresExpress3.863s (-3.2%)4.077s (-6.7% 🟢)0.214s301.26x
🐘 PostgresNitro4.238s (+3.3%)5.013s (+8.9% 🔺)0.775s241.39x
💻 LocalExpress7.711s (-16.3% 🟢)8.214s (-18.0% 🟢)0.503s152.52x
💻 LocalNext.js (Turbopack)8.787s9.161s0.374s142.87x
💻 LocalNitro9.222s (-0.8%)9.787s (-2.3%)0.566s133.02x
workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.195s1.006s0.811s601.00x
🐘 PostgresExpress0.285s (+1.1%)1.007s (~)0.722s601.46x
🐘 PostgresNitro0.300s (+6.0% 🔺)1.008s (~)0.708s601.54x
💻 LocalExpress0.505s (-10.0% 🟢)1.004s (~)0.499s602.59x
💻 LocalNext.js (Turbopack)0.560s1.004s0.445s602.87x
💻 LocalNitro0.604s (~)1.022s (~)0.417s593.10x
workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.406s1.006s0.599s901.00x
🐘 PostgresExpress0.488s (-4.2%)1.006s (~)0.518s901.20x
🐘 PostgresNitro0.532s (+7.1% 🔺)1.007s (~)0.475s901.31x
💻 LocalExpress2.239s (-10.9% 🟢)3.013s (~)0.774s305.51x
💻 LocalNitro2.539s (~)3.009s (~)0.471s306.25x
💻 LocalNext.js (Turbopack)2.644s3.009s0.365s306.50x
workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.621s1.006s0.385s1201.00x
🐘 PostgresExpress0.800s (-2.3%)1.008s (-0.9%)0.208s1201.29x
🐘 PostgresNitro0.880s (+11.4% 🔺)1.021s (+1.3%)0.140s1181.42x
💻 LocalExpress8.989s (-19.7% 🟢)9.483s (-20.6% 🟢)0.494s1314.48x
💻 LocalNext.js (Turbopack)10.772s11.392s0.620s1117.36x
💻 LocalNitro11.168s (~)11.756s (+0.8%)0.588s1118.00x
Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.166s1.000s0.001s1.010s0.844s101.00x
💻 LocalNext.js (Turbopack)0.171s1.003s0.013s1.019s0.848s101.03x
🐘 PostgresExpress0.200s (-2.6%)0.998s (~)0.001s (-12.5% 🟢)1.010s (~)0.810s101.20x
💻 LocalNitro0.201s (-5.9% 🟢)1.004s (~)0.012s (-4.0%)1.018s (~)0.817s101.21x
💻 LocalExpress0.202s (+1.3%)1.003s (~)0.008s (-35.5% 🟢)1.013s (-0.5%)0.811s101.21x
🐘 PostgresNitro0.224s (+9.2% 🔺)0.997s (~)0.001s (-13.3% 🟢)1.011s (~)0.787s101.35x
stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.541s1.026s0.003s1.037s0.496s581.00x
🐘 PostgresExpress0.609s (-3.3%)1.005s (~)0.011s (+194.7% 🔺)1.031s (+0.8%)0.422s591.13x
💻 LocalExpress0.663s (-12.4% 🟢)1.028s (~)0.007s (-28.4% 🟢)1.036s (~)0.373s581.23x
🐘 PostgresNitro0.682s (+9.3% 🔺)1.022s (+1.6%)0.004s (+8.4% 🔺)1.041s (+1.8%)0.359s581.26x
💻 LocalNext.js (Turbopack)0.770s1.030s0.010s1.137s0.367s531.42x
💻 LocalNitro0.957s (+14.1% 🔺)1.012s (~)0.009s (-2.9%)1.212s (+8.6% 🔺)0.255s531.77x
10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.888s1.071s0.000s1.077s0.189s571.00x
🐘 PostgresExpress0.964s (~)1.239s (-3.0%)0.000s (-6.1% 🟢)1.253s (-4.1%)0.289s491.09x
🐘 PostgresNitro1.040s (+7.3% 🔺)1.604s (+28.6% 🔺)0.000s (-36.8% 🟢)1.616s (+28.5% 🔺)0.576s381.17x
💻 LocalExpress1.106s (-9.7% 🟢)1.951s (-3.4%)0.000s (+35.5% 🔺)1.953s (-3.4%)0.848s311.25x
💻 LocalNext.js (Turbopack)1.263s2.020s0.000s2.023s0.760s301.42x
💻 LocalNitro1.397s (+14.2% 🔺)2.020s (~)0.000s (+221.4% 🔺)2.200s (+8.8% 🔺)0.803s281.57x
fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.751s2.105s0.000s2.120s0.369s291.00x
🐘 PostgresExpress1.761s (-0.6%)2.102s (-3.5%)0.000s (NaN%)2.113s (-3.9%)0.352s291.01x
🐘 PostgresNitro1.904s (+6.3% 🔺)2.293s (+7.1% 🔺)0.000s (+3.7%)2.307s (+6.1% 🔺)0.403s271.09x
💻 LocalExpress3.308s (-4.6%)3.779s (-6.3% 🟢)0.001s (-21.9% 🟢)3.781s (-6.3% 🟢)0.474s161.89x
💻 LocalNitro3.557s (+5.0% 🔺)4.097s (+1.6%)0.001s (+12.5% 🔺)4.100s (+1.6%)0.543s152.03x
💻 LocalNext.js (Turbopack)3.594s4.233s0.001s4.236s0.643s152.05x

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress18/21
🐘 PostgresNext.js (Turbopack)18/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres18/21
Next.js (Turbopack)🐘 Postgres21/21
Nitro🐘 Postgres17/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run


Some benchmark jobs failed:

  • Local: success
  • Postgres: success
  • Vercel: failure

Check the workflow run for details.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support in @workflow/world-vercel for sending Vercel Deployment Protection bypass credentials via WORKFLOW_VERCEL_PROTECTION_BYPASS, ensuring outbound requests can access protected preview/production deployments.

Changes:

  • Introduces getProtectionBypassHeader() helper to conditionally produce the x-vercel-protection-bypass header.
  • Injects the bypass header into the shared getHeaders() path (covers makeRequest/streamer/refs).
  • Spreads the bypass header into direct fetch() calls in resolve-latest-deployment.ts and encryption.ts.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

FileDescription
packages/world-vercel/src/utils.tsAdds bypass-header helper and includes bypass header in shared header construction.
packages/world-vercel/src/resolve-latest-deployment.tsAdds bypass header to direct Vercel API request headers.
packages/world-vercel/src/encryption.tsAdds bypass header to direct Vercel API request headers.
.changeset/world-vercel-protection-bypass.mdDeclares a minor release for the new env var behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadpackages/world-vercel/src/resolve-latest-deployment.ts Outdated
Comment threadpackages/world-vercel/src/encryption.ts Outdated
Comment threadpackages/world-vercel/src/utils.ts Outdated
Comment threadpackages/world-vercel/src/utils.ts
Replace hard-coded WORKFLOW_SERVER_URL_OVERRIDE constant with a function
that reads from the VERCEL_WORKFLOW_SERVER_URL env var. Allows configuring
the workflow-server URL per-deployment (e.g. workbench Preview envs
pointing to a branch deployment) without editing source.
Set VERCEL_WORKFLOW_SERVER_URL and VERCEL_WORKFLOW_SERVER_PROTECTION_BYPASS
on PR runs so e2e tests hit the protected workflow-server preview; leave
unset on main so production runs use the public default URL.

@karthikscale3karthikscale3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good. the codex review comments are worth addressing

- Consolidate bypass header logic in getHeaders() to reuse
getProtectionBypassHeader() instead of duplicating env lookup.
- Use consistent 'Authorization' casing in direct fetch() calls.
- Add unit tests for getProtectionBypassHeader, getHttpUrl, and getHeaders
covering env var toggling and proxy/override combinations.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-stableCherry-pick this PR to the stable branch when merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@TooTallNate@karthikscale3
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(world-vercel): support new env vars for Vercel Deployment Protection - #1824

Merged
TooTallNate merged 6 commits into
mainfrom
world-vercel-protection-bypass
Apr 22, 2026
Merged

feat(world-vercel): support new env vars for Vercel Deployment Protection#1824
TooTallNate merged 6 commits into
mainfrom
world-vercel-protection-bypass

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Apr 21, 2026

Copy link
Copy Markdown
Member

Summary

Adds two new environment variables to @workflow/world-vercel for use with Vercel Deployment Protection.

VERCEL_WORKFLOW_SERVER_PROTECTION_BYPASS

When set, the value is sent as the x-vercel-protection-bypass header on every outbound HTTP request made by the Vercel world (via makeRequest, the streamer, refs, and direct api.vercel.com calls in resolve-latest-deployment.ts and encryption.ts).

Needed because workflow-server is getting Vercel Deployment Protection enabled, so external callers need a way to authenticate bypass.

VERCEL_WORKFLOW_SERVER_URL

Replaces the need to edit source to change the workflow-server URL. When set, requests bypass the default production host (https://vercel-workflow.com) and use the override instead. When going through the api.vercel.com/v1/workflow proxy, the value is forwarded via the x-vercel-workflow-api-url header so the proxy routes accordingly.

The existing inline WORKFLOW_SERVER_URL_OVERRIDE const is preserved as an empty-string literal so external CI rewrite tooling continues to work unmodified; the inline const wins over the env var when non-empty.

Implementation

  • New getProtectionBypassHeader() helper in utils.ts returns the bypass header when the env var is set.
  • getHeaders() applies the bypass header automatically (covers makeRequest, streamer, refs).
  • Direct api.vercel.com fetches in resolve-latest-deployment.ts and encryption.ts spread the helper into their headers.
  • New getWorkflowServerUrlOverride() function prefers the inline const, falls back to VERCEL_WORKFLOW_SERVER_URL.
  • The bypass header passes through the api.vercel.com/v1/workflow proxy transparently — http-proxy-middleware forwards all request headers by default, so no proxy-side changes needed.

Testing

  • pnpm --filter @workflow/world-vercel typecheck
  • pnpm --filter @workflow/world-vercel test — 79 tests pass ✅

Allows sending a Vercel Deployment Protection bypass secret via the
`x-vercel-protection-bypass` header on all outbound requests made by
the Vercel world, enabling use against protected deployments (e.g.
previews, or workflow-server once protection is enabled).
CopilotAI review requested due to automatic review settings April 21, 2026 21:49
@TooTallNate
TooTallNate requested a review from a team as a code ownerApril 21, 2026 21:49
@vercel

vercelBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

@changeset-bot

changeset-botBot commented Apr 21, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 515010b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 18 packages
NameType
@workflow/world-vercelMinor
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
workflowPatch
@workflow/world-testingPatch
@workflow/buildersPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/vitestPatch
@workflow/web-sharedPatch
@workflow/aiPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actionsBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ 💻 Local Development10540861140
✅ 📦 Local Production10540861140
❌ 🐘 Local Postgres10522861140
✅ 🪟 Windows950095
✅ 📋 Other267018285
Total352222763800

❌ Failed Tests

🐘 Local Postgres (2 failed)

nuxt-stable (2 failed):

  • fibonacciWorkflow - recursive workflow composition via start()
  • health check (queue-based) - workflow and step endpoints respond to health check messages

Details by Category

✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
❌ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
❌ nuxt-stable8726
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9500
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8906
✅ e2e-local-postgres-nest-stable8906
✅ e2e-local-prod-nest-stable8906

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: success
  • Local Prod: success
  • Local Postgres: failure
  • Windows: success

Check the workflow run for details.

@github-actions

github-actionsBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.033s (-25.1% 🟢)1.004s (~)0.971s101.00x
💻 LocalNitro0.043s (~)1.005s (~)0.962s101.30x
🐘 PostgresNext.js (Turbopack)0.046s1.009s0.963s101.39x
💻 LocalNext.js (Turbopack)0.048s1.006s0.957s101.45x
🐘 PostgresExpress0.059s (+2.4%)1.012s (~)0.953s101.79x
🐘 PostgresNitro0.064s (-33.1% 🟢)1.010s (-3.1%)0.947s101.92x
workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.105s (-1.8%)2.005s (~)0.900s101.00x
🐘 PostgresNext.js (Turbopack)1.116s2.009s0.893s101.01x
💻 LocalNext.js (Turbopack)1.123s2.007s0.884s101.02x
💻 LocalNitro1.125s (-0.5%)2.006s (~)0.881s101.02x
🐘 PostgresExpress1.144s (~)2.009s (~)0.865s101.03x
🐘 PostgresNitro1.152s (+1.0%)2.012s (~)0.860s101.04x
workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)10.694s11.020s0.326s31.00x
💻 LocalExpress10.758s (-1.5%)11.022s (~)0.264s31.01x
💻 LocalNext.js (Turbopack)10.827s11.025s0.198s31.01x
🐘 PostgresExpress10.847s (-1.1%)11.020s (~)0.173s31.01x
💻 LocalNitro10.934s (~)11.023s (~)0.089s31.02x
🐘 PostgresNitro10.955s (+0.8%)11.026s (~)0.070s31.02x
workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)14.091s15.020s0.929s41.00x
🐘 PostgresExpress14.532s (~)15.020s (~)0.488s41.03x
💻 LocalExpress14.548s (-2.8%)15.029s (~)0.481s41.03x
💻 LocalNext.js (Turbopack)14.628s15.029s0.401s41.04x
🐘 PostgresNitro14.704s (+0.7%)15.028s (~)0.324s41.04x
💻 LocalNitro14.960s (-0.7%)15.030s (-6.2% 🟢)0.070s41.06x
workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)13.144s13.881s0.737s71.00x
🐘 PostgresExpress13.862s (-1.0%)14.024s (-3.9%)0.162s71.05x
🐘 PostgresNitro14.311s (+2.5%)15.021s (+5.0%)0.710s61.09x
💻 LocalExpress15.112s (-9.0% 🟢)16.028s (-5.9% 🟢)0.916s61.15x
💻 LocalNext.js (Turbopack)16.172s17.031s0.859s61.23x
💻 LocalNitro16.642s (-0.8%)17.029s (~)0.387s61.27x
Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.185s2.008s0.823s151.00x
🐘 PostgresExpress1.263s (~)2.010s (~)0.747s151.07x
🐘 PostgresNitro1.282s (+0.6%)2.010s (~)0.728s151.08x
💻 LocalExpress1.436s (-3.6%)2.008s (~)0.573s151.21x
💻 LocalNext.js (Turbopack)1.525s2.005s0.481s151.29x
💻 LocalNitro1.873s (+14.8% 🔺)2.392s (+15.3% 🔺)0.519s131.58x
Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)2.349s3.008s0.659s101.00x
🐘 PostgresExpress2.363s (~)3.009s (~)0.646s101.01x
🐘 PostgresNitro2.400s (+2.1%)3.011s (~)0.611s101.02x
💻 LocalExpress2.521s (-14.6% 🟢)3.007s (-12.9% 🟢)0.486s101.07x
💻 LocalNext.js (Turbopack)2.837s3.565s0.728s91.21x
💻 LocalNitro3.050s (-3.0%)3.760s (-3.2%)0.711s81.30x
Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express3.466s (-0.6%)4.010s (~)0.544s81.00x
🐘 PostgresNitro3.476s (~)4.011s (~)0.536s81.00x
🐘 PostgresNext.js (Turbopack)3.514s4.010s0.495s81.01x
💻 LocalExpress6.216s (-25.5% 🟢)6.814s (-24.5% 🟢)0.599s51.79x
💻 LocalNitro8.493s (+1.7%)9.025s (~)0.532s42.45x
💻 LocalNext.js (Turbopack)8.680s9.271s0.591s42.50x
Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.170s2.007s0.837s151.00x
🐘 PostgresExpress1.265s (+0.6%)2.008s (~)0.743s151.08x
🐘 PostgresNitro1.279s (+1.8%)2.009s (~)0.730s151.09x
💻 LocalNitro1.526s (-18.2% 🟢)2.005s (-14.3% 🟢)0.479s151.30x
💻 LocalNext.js (Turbopack)1.553s2.005s0.452s151.33x
💻 LocalExpress1.583s (-16.4% 🟢)2.109s (-10.8% 🟢)0.526s151.35x
Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.345s (~)3.009s (~)0.664s101.00x
🐘 PostgresNitro2.368s (+1.2%)3.011s (~)0.643s101.01x
🐘 PostgresNext.js (Turbopack)2.418s3.010s0.592s101.03x
💻 LocalExpress2.505s (-20.0% 🟢)3.007s (-20.1% 🟢)0.502s101.07x
💻 LocalNext.js (Turbopack)2.934s3.759s0.825s81.25x
💻 LocalNitro3.017s (-1.6%)3.759s (-3.3%)0.742s81.29x
Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express3.473s (-0.7%)4.011s (~)0.538s81.00x
🐘 PostgresNitro3.525s (+1.3%)4.010s (~)0.485s81.01x
🐘 PostgresNext.js (Turbopack)3.556s4.010s0.454s81.02x
💻 LocalExpress6.601s (-25.0% 🟢)7.222s (-22.1% 🟢)0.621s51.90x
💻 LocalNext.js (Turbopack)8.335s8.518s0.183s42.40x
💻 LocalNitro8.823s (-3.5%)9.273s (-7.5% 🟢)0.450s42.54x
workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.618s1.006s0.388s601.00x
🐘 PostgresExpress0.836s (~)1.041s (+1.7%)0.205s581.35x
💻 LocalNext.js (Turbopack)0.851s1.021s0.170s591.38x
🐘 PostgresNitro0.856s (+4.4%)1.023s (+1.7%)0.167s591.39x
💻 LocalExpress0.871s (-11.5% 🟢)1.095s (+1.7%)0.224s551.41x
💻 LocalNitro0.983s (~)1.076s (-1.6%)0.094s561.59x
workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.513s2.008s0.495s451.00x
🐘 PostgresExpress1.920s (-2.9%)2.053s (-9.1% 🟢)0.133s441.27x
🐘 PostgresNitro2.079s (+7.9% 🔺)2.945s (+40.2% 🔺)0.866s311.37x
💻 LocalExpress2.691s (-10.8% 🟢)3.110s (-13.3% 🟢)0.420s291.78x
💻 LocalNext.js (Turbopack)2.691s3.008s0.317s301.78x
💻 LocalNitro3.040s (~)3.842s (+2.2%)0.802s242.01x
workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)3.056s3.822s0.766s321.00x
🐘 PostgresExpress3.863s (-3.2%)4.077s (-6.7% 🟢)0.214s301.26x
🐘 PostgresNitro4.238s (+3.3%)5.013s (+8.9% 🔺)0.775s241.39x
💻 LocalExpress7.711s (-16.3% 🟢)8.214s (-18.0% 🟢)0.503s152.52x
💻 LocalNext.js (Turbopack)8.787s9.161s0.374s142.87x
💻 LocalNitro9.222s (-0.8%)9.787s (-2.3%)0.566s133.02x
workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.195s1.006s0.811s601.00x
🐘 PostgresExpress0.285s (+1.1%)1.007s (~)0.722s601.46x
🐘 PostgresNitro0.300s (+6.0% 🔺)1.008s (~)0.708s601.54x
💻 LocalExpress0.505s (-10.0% 🟢)1.004s (~)0.499s602.59x
💻 LocalNext.js (Turbopack)0.560s1.004s0.445s602.87x
💻 LocalNitro0.604s (~)1.022s (~)0.417s593.10x
workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.406s1.006s0.599s901.00x
🐘 PostgresExpress0.488s (-4.2%)1.006s (~)0.518s901.20x
🐘 PostgresNitro0.532s (+7.1% 🔺)1.007s (~)0.475s901.31x
💻 LocalExpress2.239s (-10.9% 🟢)3.013s (~)0.774s305.51x
💻 LocalNitro2.539s (~)3.009s (~)0.471s306.25x
💻 LocalNext.js (Turbopack)2.644s3.009s0.365s306.50x
workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.621s1.006s0.385s1201.00x
🐘 PostgresExpress0.800s (-2.3%)1.008s (-0.9%)0.208s1201.29x
🐘 PostgresNitro0.880s (+11.4% 🔺)1.021s (+1.3%)0.140s1181.42x
💻 LocalExpress8.989s (-19.7% 🟢)9.483s (-20.6% 🟢)0.494s1314.48x
💻 LocalNext.js (Turbopack)10.772s11.392s0.620s1117.36x
💻 LocalNitro11.168s (~)11.756s (+0.8%)0.588s1118.00x
Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.166s1.000s0.001s1.010s0.844s101.00x
💻 LocalNext.js (Turbopack)0.171s1.003s0.013s1.019s0.848s101.03x
🐘 PostgresExpress0.200s (-2.6%)0.998s (~)0.001s (-12.5% 🟢)1.010s (~)0.810s101.20x
💻 LocalNitro0.201s (-5.9% 🟢)1.004s (~)0.012s (-4.0%)1.018s (~)0.817s101.21x
💻 LocalExpress0.202s (+1.3%)1.003s (~)0.008s (-35.5% 🟢)1.013s (-0.5%)0.811s101.21x
🐘 PostgresNitro0.224s (+9.2% 🔺)0.997s (~)0.001s (-13.3% 🟢)1.011s (~)0.787s101.35x
stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.541s1.026s0.003s1.037s0.496s581.00x
🐘 PostgresExpress0.609s (-3.3%)1.005s (~)0.011s (+194.7% 🔺)1.031s (+0.8%)0.422s591.13x
💻 LocalExpress0.663s (-12.4% 🟢)1.028s (~)0.007s (-28.4% 🟢)1.036s (~)0.373s581.23x
🐘 PostgresNitro0.682s (+9.3% 🔺)1.022s (+1.6%)0.004s (+8.4% 🔺)1.041s (+1.8%)0.359s581.26x
💻 LocalNext.js (Turbopack)0.770s1.030s0.010s1.137s0.367s531.42x
💻 LocalNitro0.957s (+14.1% 🔺)1.012s (~)0.009s (-2.9%)1.212s (+8.6% 🔺)0.255s531.77x
10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.888s1.071s0.000s1.077s0.189s571.00x
🐘 PostgresExpress0.964s (~)1.239s (-3.0%)0.000s (-6.1% 🟢)1.253s (-4.1%)0.289s491.09x
🐘 PostgresNitro1.040s (+7.3% 🔺)1.604s (+28.6% 🔺)0.000s (-36.8% 🟢)1.616s (+28.5% 🔺)0.576s381.17x
💻 LocalExpress1.106s (-9.7% 🟢)1.951s (-3.4%)0.000s (+35.5% 🔺)1.953s (-3.4%)0.848s311.25x
💻 LocalNext.js (Turbopack)1.263s2.020s0.000s2.023s0.760s301.42x
💻 LocalNitro1.397s (+14.2% 🔺)2.020s (~)0.000s (+221.4% 🔺)2.200s (+8.8% 🔺)0.803s281.57x
fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.751s2.105s0.000s2.120s0.369s291.00x
🐘 PostgresExpress1.761s (-0.6%)2.102s (-3.5%)0.000s (NaN%)2.113s (-3.9%)0.352s291.01x
🐘 PostgresNitro1.904s (+6.3% 🔺)2.293s (+7.1% 🔺)0.000s (+3.7%)2.307s (+6.1% 🔺)0.403s271.09x
💻 LocalExpress3.308s (-4.6%)3.779s (-6.3% 🟢)0.001s (-21.9% 🟢)3.781s (-6.3% 🟢)0.474s161.89x
💻 LocalNitro3.557s (+5.0% 🔺)4.097s (+1.6%)0.001s (+12.5% 🔺)4.100s (+1.6%)0.543s152.03x
💻 LocalNext.js (Turbopack)3.594s4.233s0.001s4.236s0.643s152.05x

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress18/21
🐘 PostgresNext.js (Turbopack)18/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres18/21
Next.js (Turbopack)🐘 Postgres21/21
Nitro🐘 Postgres17/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run


Some benchmark jobs failed:

  • Local: success
  • Postgres: success
  • Vercel: failure

Check the workflow run for details.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support in @workflow/world-vercel for sending Vercel Deployment Protection bypass credentials via WORKFLOW_VERCEL_PROTECTION_BYPASS, ensuring outbound requests can access protected preview/production deployments.

Changes:

  • Introduces getProtectionBypassHeader() helper to conditionally produce the x-vercel-protection-bypass header.
  • Injects the bypass header into the shared getHeaders() path (covers makeRequest/streamer/refs).
  • Spreads the bypass header into direct fetch() calls in resolve-latest-deployment.ts and encryption.ts.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

FileDescription
packages/world-vercel/src/utils.tsAdds bypass-header helper and includes bypass header in shared header construction.
packages/world-vercel/src/resolve-latest-deployment.tsAdds bypass header to direct Vercel API request headers.
packages/world-vercel/src/encryption.tsAdds bypass header to direct Vercel API request headers.
.changeset/world-vercel-protection-bypass.mdDeclares a minor release for the new env var behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadpackages/world-vercel/src/resolve-latest-deployment.ts Outdated
Comment threadpackages/world-vercel/src/encryption.ts Outdated
Comment threadpackages/world-vercel/src/utils.ts Outdated
Comment threadpackages/world-vercel/src/utils.ts
Replace hard-coded WORKFLOW_SERVER_URL_OVERRIDE constant with a function
that reads from the VERCEL_WORKFLOW_SERVER_URL env var. Allows configuring
the workflow-server URL per-deployment (e.g. workbench Preview envs
pointing to a branch deployment) without editing source.
Set VERCEL_WORKFLOW_SERVER_URL and VERCEL_WORKFLOW_SERVER_PROTECTION_BYPASS
on PR runs so e2e tests hit the protected workflow-server preview; leave
unset on main so production runs use the public default URL.

@karthikscale3karthikscale3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good. the codex review comments are worth addressing

- Consolidate bypass header logic in getHeaders() to reuse
getProtectionBypassHeader() instead of duplicating env lookup.
- Use consistent 'Authorization' casing in direct fetch() calls.
- Add unit tests for getProtectionBypassHeader, getHttpUrl, and getHeaders
covering env var toggling and proxy/override combinations.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-stableCherry-pick this PR to the stable branch when merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@TooTallNate@karthikscale3
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(world-vercel): support new env vars for Vercel Deployment Protection - #1824

Merged
TooTallNate merged 6 commits into
mainfrom
world-vercel-protection-bypass
Apr 22, 2026
Merged

feat(world-vercel): support new env vars for Vercel Deployment Protection#1824
TooTallNate merged 6 commits into
mainfrom
world-vercel-protection-bypass

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Apr 21, 2026

Copy link
Copy Markdown
Member

Summary

Adds two new environment variables to @workflow/world-vercel for use with Vercel Deployment Protection.

VERCEL_WORKFLOW_SERVER_PROTECTION_BYPASS

When set, the value is sent as the x-vercel-protection-bypass header on every outbound HTTP request made by the Vercel world (via makeRequest, the streamer, refs, and direct api.vercel.com calls in resolve-latest-deployment.ts and encryption.ts).

Needed because workflow-server is getting Vercel Deployment Protection enabled, so external callers need a way to authenticate bypass.

VERCEL_WORKFLOW_SERVER_URL

Replaces the need to edit source to change the workflow-server URL. When set, requests bypass the default production host (https://vercel-workflow.com) and use the override instead. When going through the api.vercel.com/v1/workflow proxy, the value is forwarded via the x-vercel-workflow-api-url header so the proxy routes accordingly.

The existing inline WORKFLOW_SERVER_URL_OVERRIDE const is preserved as an empty-string literal so external CI rewrite tooling continues to work unmodified; the inline const wins over the env var when non-empty.

Implementation

  • New getProtectionBypassHeader() helper in utils.ts returns the bypass header when the env var is set.
  • getHeaders() applies the bypass header automatically (covers makeRequest, streamer, refs).
  • Direct api.vercel.com fetches in resolve-latest-deployment.ts and encryption.ts spread the helper into their headers.
  • New getWorkflowServerUrlOverride() function prefers the inline const, falls back to VERCEL_WORKFLOW_SERVER_URL.
  • The bypass header passes through the api.vercel.com/v1/workflow proxy transparently — http-proxy-middleware forwards all request headers by default, so no proxy-side changes needed.

Testing

  • pnpm --filter @workflow/world-vercel typecheck
  • pnpm --filter @workflow/world-vercel test — 79 tests pass ✅

Allows sending a Vercel Deployment Protection bypass secret via the
`x-vercel-protection-bypass` header on all outbound requests made by
the Vercel world, enabling use against protected deployments (e.g.
previews, or workflow-server once protection is enabled).
CopilotAI review requested due to automatic review settings April 21, 2026 21:49
@TooTallNate
TooTallNate requested a review from a team as a code ownerApril 21, 2026 21:49
@vercel

vercelBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

@changeset-bot

changeset-botBot commented Apr 21, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 515010b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 18 packages
NameType
@workflow/world-vercelMinor
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
workflowPatch
@workflow/world-testingPatch
@workflow/buildersPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/vitestPatch
@workflow/web-sharedPatch
@workflow/aiPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actionsBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ 💻 Local Development10540861140
✅ 📦 Local Production10540861140
❌ 🐘 Local Postgres10522861140
✅ 🪟 Windows950095
✅ 📋 Other267018285
Total352222763800

❌ Failed Tests

🐘 Local Postgres (2 failed)

nuxt-stable (2 failed):

  • fibonacciWorkflow - recursive workflow composition via start()
  • health check (queue-based) - workflow and step endpoints respond to health check messages

Details by Category

✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
✅ nuxt-stable8906
✅ sveltekit-stable8906
✅ vite-stable8906
❌ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8906
✅ express-stable8906
✅ fastify-stable8906
✅ hono-stable8906
✅ nextjs-turbopack-canary76019
✅ nextjs-turbopack-stable9500
✅ nextjs-webpack-canary76019
✅ nextjs-webpack-stable9500
✅ nitro-stable8906
❌ nuxt-stable8726
✅ sveltekit-stable8906
✅ vite-stable8906
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9500
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8906
✅ e2e-local-postgres-nest-stable8906
✅ e2e-local-prod-nest-stable8906

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: success
  • Local Prod: success
  • Local Postgres: failure
  • Windows: success

Check the workflow run for details.

@github-actions

github-actionsBot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.033s (-25.1% 🟢)1.004s (~)0.971s101.00x
💻 LocalNitro0.043s (~)1.005s (~)0.962s101.30x
🐘 PostgresNext.js (Turbopack)0.046s1.009s0.963s101.39x
💻 LocalNext.js (Turbopack)0.048s1.006s0.957s101.45x
🐘 PostgresExpress0.059s (+2.4%)1.012s (~)0.953s101.79x
🐘 PostgresNitro0.064s (-33.1% 🟢)1.010s (-3.1%)0.947s101.92x
workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.105s (-1.8%)2.005s (~)0.900s101.00x
🐘 PostgresNext.js (Turbopack)1.116s2.009s0.893s101.01x
💻 LocalNext.js (Turbopack)1.123s2.007s0.884s101.02x
💻 LocalNitro1.125s (-0.5%)2.006s (~)0.881s101.02x
🐘 PostgresExpress1.144s (~)2.009s (~)0.865s101.03x
🐘 PostgresNitro1.152s (+1.0%)2.012s (~)0.860s101.04x
workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)10.694s11.020s0.326s31.00x
💻 LocalExpress10.758s (-1.5%)11.022s (~)0.264s31.01x
💻 LocalNext.js (Turbopack)10.827s11.025s0.198s31.01x
🐘 PostgresExpress10.847s (-1.1%)11.020s (~)0.173s31.01x
💻 LocalNitro10.934s (~)11.023s (~)0.089s31.02x
🐘 PostgresNitro10.955s (+0.8%)11.026s (~)0.070s31.02x
workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)14.091s15.020s0.929s41.00x
🐘 PostgresExpress14.532s (~)15.020s (~)0.488s41.03x
💻 LocalExpress14.548s (-2.8%)15.029s (~)0.481s41.03x
💻 LocalNext.js (Turbopack)14.628s15.029s0.401s41.04x
🐘 PostgresNitro14.704s (+0.7%)15.028s (~)0.324s41.04x
💻 LocalNitro14.960s (-0.7%)15.030s (-6.2% 🟢)0.070s41.06x
workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)13.144s13.881s0.737s71.00x
🐘 PostgresExpress13.862s (-1.0%)14.024s (-3.9%)0.162s71.05x
🐘 PostgresNitro14.311s (+2.5%)15.021s (+5.0%)0.710s61.09x
💻 LocalExpress15.112s (-9.0% 🟢)16.028s (-5.9% 🟢)0.916s61.15x
💻 LocalNext.js (Turbopack)16.172s17.031s0.859s61.23x
💻 LocalNitro16.642s (-0.8%)17.029s (~)0.387s61.27x
Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.185s2.008s0.823s151.00x
🐘 PostgresExpress1.263s (~)2.010s (~)0.747s151.07x
🐘 PostgresNitro1.282s (+0.6%)2.010s (~)0.728s151.08x
💻 LocalExpress1.436s (-3.6%)2.008s (~)0.573s151.21x
💻 LocalNext.js (Turbopack)1.525s2.005s0.481s151.29x
💻 LocalNitro1.873s (+14.8% 🔺)2.392s (+15.3% 🔺)0.519s131.58x
Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)2.349s3.008s0.659s101.00x
🐘 PostgresExpress2.363s (~)3.009s (~)0.646s101.01x
🐘 PostgresNitro2.400s (+2.1%)3.011s (~)0.611s101.02x
💻 LocalExpress2.521s (-14.6% 🟢)3.007s (-12.9% 🟢)0.486s101.07x
💻 LocalNext.js (Turbopack)2.837s3.565s0.728s91.21x
💻 LocalNitro3.050s (-3.0%)3.760s (-3.2%)0.711s81.30x
Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express3.466s (-0.6%)4.010s (~)0.544s81.00x
🐘 PostgresNitro3.476s (~)4.011s (~)0.536s81.00x
🐘 PostgresNext.js (Turbopack)3.514s4.010s0.495s81.01x
💻 LocalExpress6.216s (-25.5% 🟢)6.814s (-24.5% 🟢)0.599s51.79x
💻 LocalNitro8.493s (+1.7%)9.025s (~)0.532s42.45x
💻 LocalNext.js (Turbopack)8.680s9.271s0.591s42.50x
Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.170s2.007s0.837s151.00x
🐘 PostgresExpress1.265s (+0.6%)2.008s (~)0.743s151.08x
🐘 PostgresNitro1.279s (+1.8%)2.009s (~)0.730s151.09x
💻 LocalNitro1.526s (-18.2% 🟢)2.005s (-14.3% 🟢)0.479s151.30x
💻 LocalNext.js (Turbopack)1.553s2.005s0.452s151.33x
💻 LocalExpress1.583s (-16.4% 🟢)2.109s (-10.8% 🟢)0.526s151.35x
Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.345s (~)3.009s (~)0.664s101.00x
🐘 PostgresNitro2.368s (+1.2%)3.011s (~)0.643s101.01x
🐘 PostgresNext.js (Turbopack)2.418s3.010s0.592s101.03x
💻 LocalExpress2.505s (-20.0% 🟢)3.007s (-20.1% 🟢)0.502s101.07x
💻 LocalNext.js (Turbopack)2.934s3.759s0.825s81.25x
💻 LocalNitro3.017s (-1.6%)3.759s (-3.3%)0.742s81.29x
Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express3.473s (-0.7%)4.011s (~)0.538s81.00x
🐘 PostgresNitro3.525s (+1.3%)4.010s (~)0.485s81.01x
🐘 PostgresNext.js (Turbopack)3.556s4.010s0.454s81.02x
💻 LocalExpress6.601s (-25.0% 🟢)7.222s (-22.1% 🟢)0.621s51.90x
💻 LocalNext.js (Turbopack)8.335s8.518s0.183s42.40x
💻 LocalNitro8.823s (-3.5%)9.273s (-7.5% 🟢)0.450s42.54x
workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.618s1.006s0.388s601.00x
🐘 PostgresExpress0.836s (~)1.041s (+1.7%)0.205s581.35x
💻 LocalNext.js (Turbopack)0.851s1.021s0.170s591.38x
🐘 PostgresNitro0.856s (+4.4%)1.023s (+1.7%)0.167s591.39x
💻 LocalExpress0.871s (-11.5% 🟢)1.095s (+1.7%)0.224s551.41x
💻 LocalNitro0.983s (~)1.076s (-1.6%)0.094s561.59x
workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.513s2.008s0.495s451.00x
🐘 PostgresExpress1.920s (-2.9%)2.053s (-9.1% 🟢)0.133s441.27x
🐘 PostgresNitro2.079s (+7.9% 🔺)2.945s (+40.2% 🔺)0.866s311.37x
💻 LocalExpress2.691s (-10.8% 🟢)3.110s (-13.3% 🟢)0.420s291.78x
💻 LocalNext.js (Turbopack)2.691s3.008s0.317s301.78x
💻 LocalNitro3.040s (~)3.842s (+2.2%)0.802s242.01x
workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)3.056s3.822s0.766s321.00x
🐘 PostgresExpress3.863s (-3.2%)4.077s (-6.7% 🟢)0.214s301.26x
🐘 PostgresNitro4.238s (+3.3%)5.013s (+8.9% 🔺)0.775s241.39x
💻 LocalExpress7.711s (-16.3% 🟢)8.214s (-18.0% 🟢)0.503s152.52x
💻 LocalNext.js (Turbopack)8.787s9.161s0.374s142.87x
💻 LocalNitro9.222s (-0.8%)9.787s (-2.3%)0.566s133.02x
workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.195s1.006s0.811s601.00x
🐘 PostgresExpress0.285s (+1.1%)1.007s (~)0.722s601.46x
🐘 PostgresNitro0.300s (+6.0% 🔺)1.008s (~)0.708s601.54x
💻 LocalExpress0.505s (-10.0% 🟢)1.004s (~)0.499s602.59x
💻 LocalNext.js (Turbopack)0.560s1.004s0.445s602.87x
💻 LocalNitro0.604s (~)1.022s (~)0.417s593.10x
workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.406s1.006s0.599s901.00x
🐘 PostgresExpress0.488s (-4.2%)1.006s (~)0.518s901.20x
🐘 PostgresNitro0.532s (+7.1% 🔺)1.007s (~)0.475s901.31x
💻 LocalExpress2.239s (-10.9% 🟢)3.013s (~)0.774s305.51x
💻 LocalNitro2.539s (~)3.009s (~)0.471s306.25x
💻 LocalNext.js (Turbopack)2.644s3.009s0.365s306.50x
workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.621s1.006s0.385s1201.00x
🐘 PostgresExpress0.800s (-2.3%)1.008s (-0.9%)0.208s1201.29x
🐘 PostgresNitro0.880s (+11.4% 🔺)1.021s (+1.3%)0.140s1181.42x
💻 LocalExpress8.989s (-19.7% 🟢)9.483s (-20.6% 🟢)0.494s1314.48x
💻 LocalNext.js (Turbopack)10.772s11.392s0.620s1117.36x
💻 LocalNitro11.168s (~)11.756s (+0.8%)0.588s1118.00x
Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.166s1.000s0.001s1.010s0.844s101.00x
💻 LocalNext.js (Turbopack)0.171s1.003s0.013s1.019s0.848s101.03x
🐘 PostgresExpress0.200s (-2.6%)0.998s (~)0.001s (-12.5% 🟢)1.010s (~)0.810s101.20x
💻 LocalNitro0.201s (-5.9% 🟢)1.004s (~)0.012s (-4.0%)1.018s (~)0.817s101.21x
💻 LocalExpress0.202s (+1.3%)1.003s (~)0.008s (-35.5% 🟢)1.013s (-0.5%)0.811s101.21x
🐘 PostgresNitro0.224s (+9.2% 🔺)0.997s (~)0.001s (-13.3% 🟢)1.011s (~)0.787s101.35x
stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.541s1.026s0.003s1.037s0.496s581.00x
🐘 PostgresExpress0.609s (-3.3%)1.005s (~)0.011s (+194.7% 🔺)1.031s (+0.8%)0.422s591.13x
💻 LocalExpress0.663s (-12.4% 🟢)1.028s (~)0.007s (-28.4% 🟢)1.036s (~)0.373s581.23x
🐘 PostgresNitro0.682s (+9.3% 🔺)1.022s (+1.6%)0.004s (+8.4% 🔺)1.041s (+1.8%)0.359s581.26x
💻 LocalNext.js (Turbopack)0.770s1.030s0.010s1.137s0.367s531.42x
💻 LocalNitro0.957s (+14.1% 🔺)1.012s (~)0.009s (-2.9%)1.212s (+8.6% 🔺)0.255s531.77x
10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.888s1.071s0.000s1.077s0.189s571.00x
🐘 PostgresExpress0.964s (~)1.239s (-3.0%)0.000s (-6.1% 🟢)1.253s (-4.1%)0.289s491.09x
🐘 PostgresNitro1.040s (+7.3% 🔺)1.604s (+28.6% 🔺)0.000s (-36.8% 🟢)1.616s (+28.5% 🔺)0.576s381.17x
💻 LocalExpress1.106s (-9.7% 🟢)1.951s (-3.4%)0.000s (+35.5% 🔺)1.953s (-3.4%)0.848s311.25x
💻 LocalNext.js (Turbopack)1.263s2.020s0.000s2.023s0.760s301.42x
💻 LocalNitro1.397s (+14.2% 🔺)2.020s (~)0.000s (+221.4% 🔺)2.200s (+8.8% 🔺)0.803s281.57x
fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)1.751s2.105s0.000s2.120s0.369s291.00x
🐘 PostgresExpress1.761s (-0.6%)2.102s (-3.5%)0.000s (NaN%)2.113s (-3.9%)0.352s291.01x
🐘 PostgresNitro1.904s (+6.3% 🔺)2.293s (+7.1% 🔺)0.000s (+3.7%)2.307s (+6.1% 🔺)0.403s271.09x
💻 LocalExpress3.308s (-4.6%)3.779s (-6.3% 🟢)0.001s (-21.9% 🟢)3.781s (-6.3% 🟢)0.474s161.89x
💻 LocalNitro3.557s (+5.0% 🔺)4.097s (+1.6%)0.001s (+12.5% 🔺)4.100s (+1.6%)0.543s152.03x
💻 LocalNext.js (Turbopack)3.594s4.233s0.001s4.236s0.643s152.05x

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress18/21
🐘 PostgresNext.js (Turbopack)18/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres18/21
Next.js (Turbopack)🐘 Postgres21/21
Nitro🐘 Postgres17/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run


Some benchmark jobs failed:

  • Local: success
  • Postgres: success
  • Vercel: failure

Check the workflow run for details.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support in @workflow/world-vercel for sending Vercel Deployment Protection bypass credentials via WORKFLOW_VERCEL_PROTECTION_BYPASS, ensuring outbound requests can access protected preview/production deployments.

Changes:

  • Introduces getProtectionBypassHeader() helper to conditionally produce the x-vercel-protection-bypass header.
  • Injects the bypass header into the shared getHeaders() path (covers makeRequest/streamer/refs).
  • Spreads the bypass header into direct fetch() calls in resolve-latest-deployment.ts and encryption.ts.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

FileDescription
packages/world-vercel/src/utils.tsAdds bypass-header helper and includes bypass header in shared header construction.
packages/world-vercel/src/resolve-latest-deployment.tsAdds bypass header to direct Vercel API request headers.
packages/world-vercel/src/encryption.tsAdds bypass header to direct Vercel API request headers.
.changeset/world-vercel-protection-bypass.mdDeclares a minor release for the new env var behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadpackages/world-vercel/src/resolve-latest-deployment.ts Outdated
Comment threadpackages/world-vercel/src/encryption.ts Outdated
Comment threadpackages/world-vercel/src/utils.ts Outdated
Comment threadpackages/world-vercel/src/utils.ts
Replace hard-coded WORKFLOW_SERVER_URL_OVERRIDE constant with a function
that reads from the VERCEL_WORKFLOW_SERVER_URL env var. Allows configuring
the workflow-server URL per-deployment (e.g. workbench Preview envs
pointing to a branch deployment) without editing source.
Set VERCEL_WORKFLOW_SERVER_URL and VERCEL_WORKFLOW_SERVER_PROTECTION_BYPASS
on PR runs so e2e tests hit the protected workflow-server preview; leave
unset on main so production runs use the public default URL.

@karthikscale3karthikscale3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good. the codex review comments are worth addressing

- Consolidate bypass header logic in getHeaders() to reuse
getProtectionBypassHeader() instead of duplicating env lookup.
- Use consistent 'Authorization' casing in direct fetch() calls.
- Add unit tests for getProtectionBypassHeader, getHttpUrl, and getHeaders
covering env var toggling and proxy/override combinations.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-stableCherry-pick this PR to the stable branch when merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@TooTallNate@karthikscale3