Skip to content

[docs] Document authenticating from outside a Vercel deployment - #3989

Merged
TooTallNate merged 6 commits into
mainfrom
workflow-auth-docs
Oct 16, 2026
Merged

TooTallNate merged 6 commits into
mainfrom
workflow-auth-docs

Conversation

@TooTallNate

@TooTallNate TooTallNate commented Sep 4, 2026 •

Copy link
Copy Markdown
Member

Description

Inside a Vercel deployment the Vercel World authenticates itself with the per-request OIDC token the platform injects, so the docs only really described the zero-configuration case. A process that is not a deployment — a script on your laptop, a CI job driving e2e tests against a preview — has no such token, and the reference pages listed the WORKFLOW_VERCEL_* variables one at a time without saying which ones have to be set together, or why.

Adds a Connecting from outside a deployment section to the Vercel World page (both v4 and v5) covering:

  • The four values an external client needs: auth token, project ID, team ID, environment.
  • That the auth token, projectId, and teamId are a set — supply all three or none. Supplying both IDs with no token throws up front instead of surfacing as an opaque 401.
  • That the VERCEL_OIDC_TOKEN written by vercel env pull is not a substitute: requests made with it are attributed to the environment carried in the token itself, not to the production or preview data the script means to reach. Called out separately from the same token's legitimate use as a Trusted Sources deployment-protection bypass, since those are two different credentials and conflating them is the easy mistake.
  • That start() additionally needs VERCEL_DEPLOYMENT_ID (reads don't), plus deploymentId: "latest" resolving from it.
  • A worked script using createWorld() / createVercelWorld() + setWorld(), and a GitHub Actions snippet shaped like this repo's own e2e lanes (wait for the deployment, hand its ID to the test step alongside the auth vars). Notes that this is what the workflow CLI does under the hood, and that the SDK does not read WORKFLOW_VERCEL_* implicitly.
  • On v5 only: the cross-environment guard, i.e. what happens when the environment you authenticate as disagrees with the deployment you pin. Left out of v4, which has no getEnvironment and no such guard.

Cross-links added from configuration/worlds and configuration/cli-and-web-ui so the reference entries point at the walkthrough.

The section deliberately stops at the contract the reader can act on. An earlier revision also described how the request is carried — the api-workflow proxy on api.vercel.com, the x-vercel-* headers derived from the config, the direct workflow-server path taken when the two IDs are absent — and 45ab74b takes all of that back out, along with the Why both IDs are required subsection that existed only to explain it. None of it is actionable, and all of it is free to change without notice. The guidance is unchanged: same four values, same script, same CI snippet, same warnings.

One small drive-by fix in the v4 page's existing programmatic-configuration sample, since it sits right next to the new section and contradicted it: it passed a baseUrl option that isn't in APIConfig, and used slug-shaped placeholders for projectId/teamId, which are IDs.

How did you test your changes?

Docs-only, no code changes. Every claim was checked against the source rather than carried over from the existing prose:

  • getHttpConfig / getHttpUrl / getHeaders in packages/world-vercel/src/utils.ts for the token + projectId + teamId coupling and the missing-token throw.
  • resolveVercelApiToken in http-core.ts and fetchRunKey in encryption.ts for VERCEL_TOKEN's actual (narrow) role and for the run-key fetch the same token authorizes.
  • resolveClientEnvironment for the two environment sources and the custom-environment slug-vs-ID note, and refuseCrossEnvironmentDelivery in packages/core/src/runtime.ts for the v5 guard callout.
  • queue.ts's getDeploymentId and resolve-latest-deployment.ts for the VERCEL_DEPLOYMENT_ID requirement.
  • packages/cli/src/lib/inspect/env.ts + auth.ts for the CLI's resolution order, and .github/workflows/tests.yml / benchmarks.yml for the CI shape the example is modelled on.
  • The v4 statements were verified separately against origin/stable (createVercelWorld, no baseUrl in APIConfig, same header behaviour, no environment guard) so the two versions don't claim each other's behaviour.

docs/scripts/lint.ts needs bun and an installed workspace, which I didn't have here, so I re-implemented its URL/anchor resolution (version spaces, github-slugger heading slugs, GitHub-style dedup) and ran it over the content tree — including after removing the Why both IDs are required heading, to confirm nothing still points at that anchor and that no other heading's dedup suffix shifted. No pnpm test:docs impact: that suite globs docs/content/docs/**/*.mdx, and the new code samples live under docs/content/worlds/.

The YAML snippet deliberately has no [!code highlight] annotations — there's no precedent for that notation in a non-TS block in this repo and I couldn't render the site here to confirm the transformer handles # comments, so rather than risk the marker showing up as literal text it's left plain.

Docs Preview

Base: https://workflow-docs-git-workflow-auth-docs.vercel.sh (from the vercel[bot] comment — behind deployment protection, so the links need Vercel team access).

Page v4 v5
Vercel World — new section /worlds/vercel#connecting-from-outside-a-deployment /v5/worlds/vercel#connecting-from-outside-a-deployment
Vercel World — programmatic config /worlds/vercel#programmatic-configuration /v5/worlds/vercel#programmatic-configuration
Configuration → Worlds — /v5/docs/configuration/worlds#vercel-world
Configuration → CLI and Web UI — /v5/docs/configuration/cli-and-web-ui

PR Checklist - Required to merge

  • 📦 pnpm changeset was run to create a changelog for this PR
    • Empty changeset, per the template's guidance for documentation-only changes.
  • 🔒 DCO sign-off passes (run git commit --signoff on your commits)
  • 📝 Ping @vercel/workflow in a comment once the PR is ready, and the above checklist is complete

🤖 Generated with Claude Code

@TooTallNate
TooTallNate requested a review from a team as a code owner September 4, 2026 20:38
Copilot AI lite review requested due to automatic review settings September 4, 2026 20:38
@vercel

vercel Bot commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
example-nextjs-workflow-turbopack Ready Ready Preview, v0 Oct 16, 2026 7:55pm UTC
example-nextjs-workflow-webpack Ready Ready Preview, v0 Oct 16, 2026 7:55pm UTC
example-workflow Ready Ready Preview, v0 Oct 16, 2026 7:55pm UTC
workbench-astro-workflow Ready Ready Preview, v0 Oct 16, 2026 7:55pm UTC
workbench-express-workflow Ready Ready Preview, v0 Oct 16, 2026 7:55pm UTC
workbench-fastify-workflow Ready Ready Preview, v0 Oct 16, 2026 7:55pm UTC
workbench-hono-workflow Ready Ready Preview, v0 Oct 16, 2026 7:55pm UTC
workbench-nestjs-workflow Ready Ready Preview, v0 Oct 16, 2026 7:55pm UTC
workbench-nitro-workflow Ready Ready Preview, v0 Oct 16, 2026 7:55pm UTC
workbench-nuxt-workflow Ready Ready Preview, v0 Oct 16, 2026 7:55pm UTC
workbench-python-workflow Ready Ready Preview, v0 Oct 16, 2026 7:55pm UTC
workbench-sveltekit-workflow Ready Ready Preview, v0 Oct 16, 2026 7:55pm UTC
workbench-tanstack-start-workflow Ready Ready Preview, v0 Oct 16, 2026 7:55pm UTC
workbench-vite-workflow Ready Ready Preview, v0 Oct 16, 2026 7:55pm UTC
workflow-docs Ready Ready Preview, v0 Oct 16, 2026 7:55pm UTC
workflow-swc-playground Ready Ready Preview, v0 Oct 16, 2026 7:55pm UTC
workflow-tarballs Ready Ready Preview, v0 Oct 16, 2026 7:55pm UTC
workflow-web Ready Ready Preview, v0 Oct 16, 2026 7:55pm UTC

Copilot AI 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.

🟡 Changes recommended

A few newly-introduced docs statements are inconsistent with existing reference text (v4 development env) and with custom-environment support (v5), which could mislead users configuring WORKFLOW_VERCEL_ENV.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds documentation that explains how to authenticate and configure the Vercel World from outside a Vercel deployment (local scripts / CI), including required variables, proxy vs direct backend behavior, and CI examples, with supporting cross-links from configuration reference pages.

Changes:

  • Add “Connecting from outside a deployment” guidance to both v4 and v5 Vercel World pages, including worked script + CI snippets.
  • Cross-link the new walkthrough from the v5 “Worlds” and “CLI and Web UI” configuration reference pages.
  • Fix a couple of inaccuracies in the existing v4 programmatic configuration sample (remove unsupported baseUrl, use ID-shaped placeholders).
File summaries
File Description
docs/content/worlds/v5/vercel.mdx Adds the external-auth walkthrough + references it from the env-var section.
docs/content/worlds/v4/vercel.mdx Adds the external-auth walkthrough + aligns nearby programmatic config sample.
docs/content/docs/v5/configuration/worlds.mdx Links the reference knobs to the new external-auth walkthrough and clarifies token/ID coupling.
docs/content/docs/v5/configuration/cli-and-web-ui.mdx Notes the 4 required values and links to the walkthrough.
.changeset/docs-external-vercel-auth.md Adds a docs-only (empty-frontmatter) changeset entry for the documentation update.
Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread docs/content/worlds/v4/vercel.mdx Resolved
Comment thread docs/content/worlds/v5/vercel.mdx Resolved
@changeset-bot

changeset-bot Bot commented Sep 4, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 922ff92

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

This PR includes changesets to release 0 packages

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

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

Copy link
Copy Markdown
Member Author

Pushed 82abefb (on top of 081e7ed): development is no longer presented as a supported environment anywhere in the docs, and every mention of WORKFLOW_VERCEL_ENV now names its accepted values in place.

That reverses the compromise in my earlier reply on the v4 thread. Copilot asked for development to be added to the env-var table for consistency; I had instead made the table defer to the reference entry, since I couldn't verify development as a target for an external client. Deferring left development sitting in the v4 reference entry, so it is gone, and both pages list the values inline: production, preview, or a custom environment's slug.

Also in this commit:

  • --env in configuration/cli-and-web-ui accepted production or preview only, which contradicted projectConfig.environment in configuration/worlds after 081e7ed. Same three values now.
  • The "isolates data per environment" bullet at the top of both Vercel World pages listed development; it now reads production, preview, and any custom environments.
  • The vercel env pull warning no longer says the pulled VERCEL_OIDC_TOKEN "addresses development data". It states the consequence instead — requests made with that token are attributed to the environment carried in the token itself, not to the production or preview data you mean to reach — which also clears the last of the proxy/direct-path mechanics out of that callout, matching what 081e7ed did to the rest of the section.
  • getHookByToken's "Checking Hook Environment" sample compared hook.environment against process.env.VERCEL_ENV || "development". That fallback could never match: packages/world-local/src/storage/hooks-storage.ts records hooks as local. It now prefers VERCEL_TARGET_ENV — which carries a custom environment's slug, where VERCEL_ENV reports preview — and falls back to local. This is the one change outside the pages the PR already touched; both v4 and v5 copies were the same.

The description's OIDC-token bullet was reworded to match the callout.

How I verified

The workspace installed on this box, so unlike the earlier commits this one got a real run of the repo's own docs typecheck. DOCS_FILE="get-hook-by-token,configuration/cli-and-web-ui,configuration/worlds" pnpm test:docs: 13 passed, 1 skipped — the edited sample type-checks in both getHookByToken pages. (It needs packages/workflow/dist, so I built the TS packages first; @workflow/swc-plugin cannot build here — no Rust toolchain — which is why the full suite and docs lint:links (bun-only) are still out of reach.)

Anchors were re-checked after the rebase with the same version-space/github-slugger/GitHub-dedup rules as docs/scripts/lint.ts: 14 in-page refs across the five touched pages, 0 failures. No section headings were added or removed, so no existing anchor's dedup suffix shifted.

@github-actions

github-actions Bot commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Sim World

Simulated world deterministic testing for races. Traces

🟢 world-sim scenario book — 0 fail of 42 total

fence=per-spec

scenario outcome events virt replay violations
✅ smoke-no-steps completed 3 0ms ok 0
✅ smoke-one-step completed 6 0ms ok 0
✅ hook-at-step-started completed 12 0ms ok 0
✅ hook-at-step-completed completed 12 0ms ok 0
✅ hook-at-hook-created completed 12 0ms ok 0
✅ deadline-hook-wins completed 7 1.0h ok 0
✅ deadline-expires completed 7 1.0h ok 0
✅ step-vs-timer-early-settlement completed 8 1.0h ok 0
✅ long-sleep completed 11 30.0d ok 0
✅ hook-never-arrives stalled 3 0ms skipped 0
✅ step-retries-twice completed 10 2.0s ok 0
✅ parallel-steps completed 9 0ms ok 0
✅ hook-on-execution-state completed 12 0ms ok 0
✅ peek-hook-before-branch completed 12 0ms ok 0
✅ peek-hook-after-branch completed 12 0ms ok 0
✅ peek-hook-at-registration completed 12 0ms ok 0
✅ race-hook-before-probe completed 12 0ms ok 0
✅ race-hook-after-probe completed 12 0ms ok 0
✅ race-duplicate-delivery completed 13 0ms ok 0
✅ attr-hook-before-step completed 11 0ms ok 0
✅ attr-hook-after-step completed 11 0ms ok 0
✅ attr-from-step-body completed 13 0ms ok 0
✅ fork-hook-after-timeout completed 14 1.0m ok 0
✅ fork-hook-before-timeout completed 14 1.0m ok 0
✅ count-hook-after-timeout completed 17 1.0m ok 0
✅ count-hook-before-timeout completed 20 1.0m ok 0
✅ stale-read-step-count-fork completed 20 1.0m ok 0
✅ stale-read-equal-step-counts completed 14 1.0m ok 0
✅ step-vs-step-fork completed 12 0ms ok 0
✅ step-vs-step-fork-fenced completed 12 0ms ok 0
✅ fence-catches-benign-direction completed 12 5ms ok 0
✅ in-flight-before-decision completed 17 1.0m ok 0
✅ in-flight-before-decision-counted completed 17 1.0m ok 0
✅ in-flight-after-decision completed 19 2.0m ok 0
✅ stale-read-step-count-fork-fenced completed 20 1.0m ok 0
✅ fork-hook-wins completed 13 1.0m ok 0
✅ fork-timeout-wins completed 13 1.0m ok 0
✅ unclaimed-payload-under-fork completed 17 1.0m ok 0
✅ claimed-payload-under-fork completed 17 1.0m ok 0
✅ writers-independent-step-bodies completed 12 0ms ok 0
✅ writers-scripted-tempo completed 12 0ms ok 0
✅ cancel-mid-step cancelled 7 0ms skipped 0

Full trace: world-sim.txt

Comment thread docs/content/worlds/v5/vercel.mdx Resolved
vercel Bot and others added 6 commits October 16, 2026 19:32
Inside a deployment the Vercel World authenticates itself with the
per-request OIDC token the platform injects, so the docs only described
the zero-configuration case. A local script or a CI job has no such
token, and the reference pages listed the WORKFLOW_VERCEL_* variables
one by one without saying which ones go together or why.

Adds a "Connecting from outside a deployment" section to the Vercel
World page (v4 and v5) covering the token plus project ID, team ID, and
environment; that projectId+teamId is what routes the client through the
api-workflow proxy, which is the only path that accepts a Vercel auth
token; that starting runs additionally needs VERCEL_DEPLOYMENT_ID; and a
worked script and GitHub Actions example. Notes that a development-scoped
VERCEL_OIDC_TOKEN from `vercel env pull` is not a substitute — the
backend attributes requests to the environment in the token's claim, so
it must not be used to reach production or preview data.

Also drops a non-existent `baseUrl` option from the v4 programmatic
configuration sample and uses ID-shaped placeholders there, since
projectId/teamId are IDs rather than slugs.

Signed-off-by: Nathan Rajlich <71256+TooTallNate@users.noreply.github.com>

Co-Authored-By: Nathan Rajlich <71256+TooTallNate@users.noreply.github.com>
The new section documented custom environment slugs while the reference
entries on the same pages still listed only production/preview (v5) or
production/preview/development (v4), so the two disagreed.

The env-var table now names the variable and defers to the reference
entry for the accepted values, keeping one canonical list per page. The
v5 reference entry gains custom environment slugs, matching what the
proxy accepts on the projectConfig path, and the v5 configuration
reference records that the proxy takes a custom environment's slug or ID
but attributes the write to the slug.

Signed-off-by: Nathan Rajlich <71256+TooTallNate@users.noreply.github.com>

Co-Authored-By: Nathan Rajlich <71256+TooTallNate@users.noreply.github.com>
The external-auth section explained how the request is carried as well as
what the caller has to set: the api-workflow proxy on api.vercel.com, the
x-vercel-* headers derived from the config, and the direct workflow-server
path taken when the two IDs are absent. None of that is something a reader
can act on, and all of it is free to change without notice.

The guidance itself is unchanged — same four values, same script, same CI
snippet, same warnings about the pulled OIDC token and about environment
alignment. What the reader now gets is the contract: authenticate with a
Vercel auth token, set the token and both IDs together, name the
environment you mean.

"Why both IDs are required" was that reasoning in section form, so it is
gone; the one actionable sentence it carried — set all three or none, and
setting the IDs alone fails up front rather than as a 401 — moves inline
under the sample, and the env-var tables say "Required" without pointing
at a section that explains the backend's routing.

Also finishes Copilot's remaining review thread on the v5 configuration
reference: projectConfig.environment now lists custom environment slugs
alongside production and preview, with the slug-not-ID caveat stated as a
rule for the reader rather than as a description of what the proxy accepts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Nathan Rajlich <71256+TooTallNate@users.noreply.github.com>

Co-Authored-By: Nathan Rajlich <71256+TooTallNate@users.noreply.github.com>
WORKFLOW_VERCEL_ENV was documented three ways: the external-client
tables deferred to the reference entry, the v5 reference entry listed
production/preview plus custom environment slugs, and the v4 entry
listed production/preview/development. Copilot flagged the mismatch on
all three pages, suggesting `development` be added to the tables for
consistency.

`development` is not an environment an external client should target, so
the inconsistency is resolved by dropping it rather than by spreading it
to the pages that never mentioned it:

- The env-var tables on both Vercel World pages name the accepted values
  inline (production, preview, or a custom environment's slug) and still
  link to the reference entry, so a reader does not have to follow a
  link to learn what is allowed.
- The v4 reference entry drops `development` and gains custom
  environment slugs, matching v5. The v4 page also gains the
  slug-not-ID rule the v5 page already carried.
- `--env` in the CLI and web UI reference accepts the same values, so it
  no longer says production/preview while the world reference and
  projectConfig.environment say otherwise.
- The "isolates data per environment" bullet on both pages now reads
  production, preview, and any custom environments.
- The `vercel env pull` warning no longer frames the pulled
  VERCEL_OIDC_TOKEN as addressing "development data". It states the
  consequence for the reader instead: requests made with that token are
  attributed to the environment carried in the token itself, so
  authenticate with a Vercel auth token.
- The getHookByToken environment sample compared hook.environment
  against `VERCEL_ENV || "development"`, which could never match — the
  local world records hooks as `local`. It now prefers
  VERCEL_TARGET_ENV, which carries a custom environment's slug where
  VERCEL_ENV reports preview, and falls back to `local`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Nathan Rajlich <71256+TooTallNate@users.noreply.github.com>

Co-Authored-By: Nathan Rajlich <71256+TooTallNate@users.noreply.github.com>
…e CI example its permissions

Co-Authored-By: Nathan Rajlich <71256+TooTallNate@users.noreply.github.com>
Co-Authored-By: Nathan Rajlich <71256+TooTallNate@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

No backport to stable for eb9acbc (AI decision).

This is overwhelmingly net-new documentation — a multi-page "Connecting from outside a deployment" walkthrough plus cross-links — rather than a correction of something wrong on stable, and the files it edits (docs/content/worlds/v4|v5/vercel.mdx, docs/content/docs/v5/configuration/*, the versioned get-hook-by-token.mdx paths) do not exist on stable, whose docs tree is unversioned (docs/content/docs/deploying/world/vercel-world.mdx, docs/content/docs/api-reference/workflow-api/get-hook-by-token.mdx). It does carry two genuine corrections that also apply to stable's Vercel World page — the programmatic-configuration sample passes a baseUrl option that is not in APIConfig, and WORKFLOW_VERCEL_ENV is documented as accepting development — so a human may want to split those out and force them through via workflow_dispatch.

To override, re-run the Backport to stable workflow manually via workflow_dispatch and paste this commit SHA into the ref input:

eb9acbc8ba0041e2cbcd06049c29e56568b7ece3

@Sum1cares Sum1cares left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Awesome

This branch was successfully deployed

18 active (17 outdated) deployments
Preview – workflow-docs — 922ff927 Deployed Oct 16, 2026 by vercel[bot]
Preview – workflow-swc-playground — d95e1600 Deployed Sep 11, 2026 by vercel[bot]
Preview – example-nextjs-workflow-webpack — d95e1600 Deployed Sep 11, 2026 by vercel[bot]
Preview – example-nextjs-workflow-turbopack — d95e1600 Deployed Sep 11, 2026 by vercel[bot]
Preview – workbench-express-workflow — d95e1600 Deployed Sep 11, 2026 by vercel[bot]
Preview – workbench-nuxt-workflow — d95e1600 Deployed Sep 11, 2026 by vercel[bot]
Preview – workbench-tanstack-start-workflow — d95e1600 Deployed Sep 11, 2026 by vercel[bot]
Preview – workbench-sveltekit-workflow — d95e1600 Deployed Sep 11, 2026 by vercel[bot]
Preview – example-workflow — d95e1600 Deployed Sep 11, 2026 by vercel[bot]
Preview – workbench-astro-workflow — d95e1600 Deployed Sep 11, 2026 by vercel[bot]
Preview – workbench-nestjs-workflow — d95e1600 Deployed Sep 11, 2026 by vercel[bot]
Preview – workbench-nitro-workflow — d95e1600 Deployed Sep 11, 2026 by vercel[bot]
Preview – workbench-fastify-workflow — d95e1600 Deployed Sep 11, 2026 by vercel[bot]
Preview – workbench-vite-workflow — d95e1600 Deployed Sep 11, 2026 by vercel[bot]
Preview – workbench-hono-workflow — d95e1600 Deployed Sep 11, 2026 by vercel[bot]
Preview – workflow-tarballs — d95e1600 Deployed Sep 11, 2026 by vercel[bot]
Preview – workflow-web — d95e1600 Deployed Sep 11, 2026 by vercel[bot]
Preview – workbench-python-workflow — d95e1600 Deployed Sep 11, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants