Skip to content

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

Open
TooTallNate wants to merge 4 commits into
mainfrom
workflow-auth-docs
Open

[docs] Document authenticating from outside a Vercel deployment#3989
TooTallNate wants to merge 4 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 081e7ed 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

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>
@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 Sep 4, 2026 9:24pm UTC
example-nextjs-workflow-webpack Ready Ready Preview, v0 Sep 4, 2026 9:24pm UTC
example-workflow Ready Ready Preview, v0 Sep 4, 2026 9:24pm UTC
workbench-astro-workflow Ready Ready Preview, v0 Sep 4, 2026 9:24pm UTC
workbench-express-workflow Ready Ready Preview, v0 Sep 4, 2026 9:24pm UTC
workbench-fastify-workflow Ready Ready Preview, v0 Sep 4, 2026 9:24pm UTC
workbench-hono-workflow Ready Ready Preview, v0 Sep 4, 2026 9:24pm UTC
workbench-nestjs-workflow Ready Ready Preview, v0 Sep 4, 2026 9:24pm UTC
workbench-nitro-workflow Ready Ready Preview, v0 Sep 4, 2026 9:24pm UTC
workbench-nuxt-workflow Ready Ready Preview, v0 Sep 4, 2026 9:24pm UTC
workbench-python-workflow Ready Ready Preview, v0 Sep 4, 2026 9:24pm UTC
workbench-sveltekit-workflow Ready Ready Preview, v0 Sep 4, 2026 9:24pm UTC
workbench-tanstack-start-workflow Ready Ready Preview, v0 Sep 4, 2026 9:24pm UTC
workbench-vite-workflow Ready Ready Preview, v0 Sep 4, 2026 9:24pm UTC
workflow-docs Ready Ready Preview, v0 Sep 4, 2026 9:24pm UTC
workflow-swc-playground Ready Ready Preview, v0 Sep 4, 2026 9:24pm UTC
workflow-tarballs Ready Ready Preview, v0 Sep 4, 2026 9:24pm UTC
workflow-web Ready Ready Preview, v0 Sep 4, 2026 9:24pm 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/docs/v5/configuration/worlds.mdx Outdated
Comment thread docs/content/worlds/v4/vercel.mdx Outdated
Comment thread docs/content/worlds/v5/vercel.mdx Outdated
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>
@changeset-bot

changeset-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 82abefb

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 081e7ed, which does two things.

Copilot's threads are all replied to and resolved. Two of the three were the WORKFLOW_VERCEL_ENV inconsistencies fixed back in 3e5e546 (custom environment slugs on v5; the v4 table contradicting its own reference entry, which I resolved by having the table defer to that entry rather than asserting development is a valid external target). The third, on projectConfig.environment in configuration/worlds, is now stated as a rule for the reader — configure the slug, not the environment's ID — instead of as a description of what the backend accepts.

Dropped the implementation detail. The section was explaining 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, the direct workflow-server path taken when the two IDs are absent, and WORKFLOW_VERCEL_BACKEND_URL as the way to repoint the proxy. That is all gone. It isn't something a reader can act on, and it's free to change without notice — which would leave these pages wrong.

Why both IDs are required went with it, since the whole subsection existed to explain that routing. Its one actionable sentence — set the token and both IDs together, and setting the IDs alone fails up front rather than as a 401 — now sits inline under the script sample, and the env-var tables just say Required instead of linking to a section about backend routing.

The guidance itself is untouched: same four values, same setWorld() sample, same CI snippet, same warnings about the pulled VERCEL_OIDC_TOKEN and about keeping WORKFLOW_VERCEL_ENV aligned with the deployment you pin. Net −9 lines across the three files.

Two things I did not touch, deliberately: the pre-existing WORKFLOW_VERCEL_BACKEND_URL, VERCEL_WORKFLOW_SERVER_URL, and WORKFLOW_EVENTS_TRANSPORT reference entries on main also name the proxy and workflow-server. They're documenting variables a user can actually set, and rewriting them is a separate change from this PR — happy to do it here if you'd rather it land together.

Re-ran the anchor resolution across the content tree after removing that heading: 22 anchor links in the four touched files resolve, nothing references #why-both-ids-are-required, and no other heading's dedup suffix moved. As before, Lint / Docs Checks don't fire on this branch (app-token pushes don't trigger on: pull_request), but Vercel – workflow-docs builds it.

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>

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.

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.

2 participants