Skip to content

[wrangler] Extract remote bindings into @cloudflare/remote-bindings#14443

Draft
penalosa wants to merge 2 commits into
penalosa/remote-bindings-auth-foundationfrom
penalosa/remote-bindings-v2
Draft

[wrangler] Extract remote bindings into @cloudflare/remote-bindings#14443
penalosa wants to merge 2 commits into
penalosa/remote-bindings-auth-foundationfrom
penalosa/remote-bindings-v2

Conversation

@penalosa

@penalosa penalosa commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Extracts a standalone @cloudflare/remote-bindings package so remote bindings can be established without depending on wrangler (notably from @cloudflare/vite-plugin), and switches both wrangler and the Vite plugin onto it.

PR 2 of a 2-PR stack — builds on the auth/storage foundation in #14444 (this PR is based on that branch; review/merge #14444 first).

This unblocks decoupling the Vite plugin from wrangler — remote bindings were the main blocker — and enables a cf dev → vite dev → @cloudflare/remote-bindings delegation chain.

What changed

  • @cloudflare/remote-bindings (new): lightweight, wrangler-free remote binding proxy sessions — direct edge-preview API calls + a minimal Node HTTP/WS proxy + a pre-bundled ProxyServerWorker — replacing the previous startWorker()/DevEnv approach. Exposes startRemoteProxySession, maybeStartOrUpdateRemoteProxySession, pickRemoteBindings, and createEnvAuthResolver. Reuses createWorkerUploadForm from @cloudflare/deploy-helpers.
  • wrangler: start-remote-proxy-session now delegates to the package, preserving wrangler's own auth resolution (interactive requireAuth login + account selection) and error reporting. auth-config-file / auth-variables re-export the shared helpers from the foundation PR (no behaviour change).
  • @cloudflare/vite-plugin: establishes remote binding sessions via @cloudflare/remote-bindings directly instead of through wrangler.

Auth model

The package's default resolver is fully environment-driven (using the foundation PR's storage + env vars), so a top-level CLI can delegate remote bindings and have the OAuth token discovered and refreshed mid-run:

Variable Role
CLOUDFLARE_CONFIG_DIR Pin the global config dir for the whole process tree
CLOUDFLARE_AUTH_CONFIG_FILE Explicit auth file (format inferred: TOML / JSON / JSONC)
CLOUDFLARE_OAUTH_CLIENT_ID OAuth app used to refresh the token (falls back to WRANGLER_CLIENT_ID)
CLOUDFLARE_ACCOUNT_ID Target account
CLOUDFLARE_ALLOW_GLOBAL_API_KEY Honour the global API key + email pair (default true)
CLOUDFLARE_LOGIN_COMMAND Hint shown in the "not authenticated" error

Behaviour notes:

  • wrangler dev is unchanged: it injects a requireAuth-backed auth hook, so requesting remote bindings while unauthorised starts wrangler's interactive login (and account selection) as before — or fails with a clear error in CI.
  • The package itself is refresh-only and never starts an interactive login (it's a delegated child that doesn't own the terminal); when no credentials are available it fails fast with the CLOUDFLARE_LOGIN_COMMAND hint.

  • Tests
    • Tests included/updated
    • Automated tests not possible - manual testing has been completed as follows:
    • Additional testing not necessary because:
  • Public documentation
    • Cloudflare docs PR(s):
    • Documentation not necessary because: internal architectural extraction. The new package is internal/prerelease (not a user-facing API), and wrangler dev's remote-bindings behaviour and configuration are unchanged.

@changeset-bot

changeset-bot Bot commented Jun 26, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2e5ac72

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

This PR includes changesets to release 4 packages
Name Type
@cloudflare/remote-bindings Minor
@cloudflare/vite-plugin Patch
wrangler Patch
@cloudflare/vitest-pool-workers Patch

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

Copy link
Copy Markdown
Contributor

✅ All changesets look good

@ask-bonk ask-bonk Bot 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.

I'm Bonk, and I've done a quick review of your PR.

Extracts remote bindings into a standalone @cloudflare/remote-bindings package (wrangler-free, env-driven auth) and rewires wrangler + the Vite plugin to use it.

One correctness issue worth fixing before merge, plus a couple of smaller robustness notes:

  1. (high) Compliance-region API base URL is wrong. getApiBaseUrl in packages/remote-bindings/src/api/fetch.ts special-cases "eu" (which compliance_region never is — its type is "public" | "fedramp_high" | undefined) with a eu-client URL that exists nowhere else in the repo, and it does not handle "fedramp_high". So a worker in the FedRAMP compliance region would have its remote-binding edge-preview calls routed to the public api.cloudflare.com endpoint instead of api.fed.cloudflare.com. wrangler's canonical getCloudflareApiBaseUrl maps fedramp_high.fed subdomain.

  2. (low) fetchResult assumes json.errors is always an array. If the API returns success: false without an errors array, json.errors.map(...) throws a TypeError, masking the real status. Guard with (json.errors ?? []).

  3. (low) getApiBaseUrl ignores CLOUDFLARE_API_BASE_URL for non-public regions. Once the region branch is taken, the env override is skipped. wrangler's resolver checks the env override first regardless of region. Worth preserving that precedence.

/**
* Get the Cloudflare API base URL, respecting compliance region settings.
*/
function getApiBaseUrl(complianceRegion?: string): string {

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.

compliance_region is typed "public" | "fedramp_high" | undefined (see packages/workers-utils/src/config/environment.ts:680), so the "eu" branch is dead code and the eu-client host appears nowhere else in the repo. More importantly, "fedramp_high" is unhandled, so FedRAMP-region remote bindings hit the public API. Mirror wrangler's getCloudflareApiBaseUrl (fedramp_high.fed subdomain) and keep the env override first:

Suggested change
function getApiBaseUrl(complianceRegion?: string): string {
function getApiBaseUrl(complianceRegion?: string): string {
// eslint-disable-next-line turbo/no-undeclared-env-vars -- Matches wrangler's API base URL override
const override = process.env.CLOUDFLARE_API_BASE_URL;
if (override) {
return override;
}
const sub = complianceRegion === "fedramp_high" ? ".fed" : "";
return `https://api${sub}.cloudflare.com/client/v4`;
}

}

if (!json.success) {
const errors = json.errors.map((e) => `${e.code}: ${e.message}`).join("\n");

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.

If the API returns success: false without an errors array, this throws a TypeError and hides the real status. Guard against a missing array:

Suggested change
const errors = json.errors.map((e) => `${e.code}: ${e.message}`).join("\n");
const errors = (json.errors ?? [])
.map((e) => `${e.code}: ${e.message}`)
.join("\n");

@ask-bonk

ask-bonk Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Review submitted successfully to PR #14443.

Summary of findings posted:

  1. (high) Compliance-region API base URL buggetApiBaseUrl in packages/remote-bindings/src/api/fetch.ts handles a non-existent "eu" region (with a fabricated eu-client URL found nowhere else in the repo) and fails to handle "fedramp_high", the only non-public value compliance_region can actually take. FedRAMP-region remote bindings would be routed to the public api.cloudflare.com endpoint. Posted a suggestion mirroring wrangler's canonical getCloudflareApiBaseUrl.

  2. (low) fetchResult assumes json.errors is an array — would throw a TypeError and mask the real status if the API returns success: false without errors. Posted a guard suggestion.

  3. (low) CLOUDFLARE_API_BASE_URL override skipped for non-public regions — folded into the suggestion in wrangler dev #1 so the env override is checked first.

github run

@penalosa penalosa changed the base branch from main to penalosa/remote-bindings-auth-foundation June 26, 2026 15:48
@penalosa penalosa force-pushed the penalosa/remote-bindings-v2 branch from e6dd08b to 83ceccf Compare June 26, 2026 16:45
@penalosa penalosa force-pushed the penalosa/remote-bindings-auth-foundation branch from 0540500 to c8616c1 Compare June 26, 2026 17:39
penalosa added 2 commits June 26, 2026 18:42
Add the standalone @cloudflare/remote-bindings package: a lightweight,
wrangler-free implementation of remote binding proxy sessions (direct
edge-preview API calls + a minimal Node HTTP/WS proxy and a pre-bundled
ProxyServerWorker), replacing the previous DevEnv-based approach.

Auth is customisable and environment-driven: createEnvAuthResolver reads
CLOUDFLARE_* credentials or refreshes the stored OAuth token discovered via
CLOUDFLARE_CONFIG_DIR / CLOUDFLARE_AUTH_CONFIG_FILE (TOML/JSON/JSONC), using
CLOUDFLARE_OAUTH_CLIENT_ID and honouring CLOUDFLARE_ALLOW_GLOBAL_API_KEY. It is
refresh-only and never starts an interactive login, failing with an actionable
CLOUDFLARE_LOGIN_COMMAND hint instead.

wrangler now delegates startRemoteProxySession to the package while preserving
its own auth resolution (interactive requireAuth login + account selection) and
error reporting.
Establish remote binding proxy sessions via @cloudflare/remote-bindings
directly instead of through wrangler, removing that coupling and enabling
environment-variable-driven auth discovery and mid-run OAuth token refresh.
@penalosa penalosa force-pushed the penalosa/remote-bindings-v2 branch from 83ceccf to 2e5ac72 Compare June 26, 2026 17:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Untriaged

Development

Successfully merging this pull request may close these issues.

2 participants