Skip to content

[wrangler] Only show accounts available for the current login auth#13770

Merged
petebacondarwin merged 12 commits intomainfrom
pbd/wrangler/auth-scoped-account-list
May 6, 2026
Merged

[wrangler] Only show accounts available for the current login auth#13770
petebacondarwin merged 12 commits intomainfrom
pbd/wrangler/auth-scoped-account-list

Conversation

@petebacondarwin
Copy link
Copy Markdown
Contributor

@petebacondarwin petebacondarwin commented May 1, 2026

Wrangler's account listings now respect the active login auth: wrangler whoami and the interactive 'Select an account' prompt show the intersection of /accounts and /memberships, dropping any accounts the current OAuth token or API token has no membership in.

Previously these two code paths used different sources:

  • wrangler whoami listed every account from GET /accounts — including ones the active token couldn't actually use.
  • The interactive Select an account prompt (and the non-interactive 'no account ID' error message) listed accounts from GET /memberships.

That could produce a whoami table where an account showed up but couldn't be picked from the prompt or used by other commands. After this change both flows share fetchAllAccounts, which:

  1. Calls /accounts and /memberships in parallel.
  2. Returns the intersection by ID, taking metadata (e.g. account name) from /accounts.
  3. Falls back to /accounts when /memberships returns 9109 (Insufficient permissions) or 10000 (Authentication error). 9109 is the structural Account API Token case; 10000 covers tokens that work against /accounts but are not accepted by /memberships. Any other failure on either endpoint is surfaced to the user.
  4. Exposes a throwOnEmpty flag so whoami shows an empty list rather than throwing when the intersection is empty, while account selection still throws (as before) so the error guides the user to set account_id.

The accounts field of wrangler whoami --json is more restrictive in the same way.


  • 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: this is a behavior fix; the wrangler whoami and account-selection UX are unchanged on the surface aside from the filtered list.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 1, 2026

🦋 Changeset detected

Latest commit: 89b895e

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

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

@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk Bot commented May 1, 2026

Good. When success: false, throwFetchError is called, which rejects the promise. So mockGetMembershipsFail correctly causes both endpoints to reject. The /accounts handler returns createFetchResult([], false), which means it also throws. Both endpoints will be rejected in Promise.allSettled. The memberships error won't be 9109 (no error code in the response), so it falls to line 86 where membershipsRes.status === "rejected" is true, permissive is false (default), so it throws membershipsRes.reason. That's the expected behavior for the test.

After thoroughly reviewing the PR, I'm satisfied that the logic is correct and well-tested. The implementation handles all edge cases properly:

  • Happy path (both succeed): intersection computed correctly
  • 9109 fallback (Account API Tokens): preserved correctly
  • Permissive mode (whoami): graceful fallback to /accounts
  • /accounts failure with /memberships success: fallback to memberships
  • Both failures: errors propagated correctly
  • throwOnEmpty flag: works correctly for both whoami and account selection

The test coverage is comprehensive, covering intersection, filtering in both directions, 9109 fallback, permissive mode, and the throwOnEmpty flag. The only minor gap is no test for the /accounts fails + /memberships succeeds path, but that's not a blocking concern.

The changeset is properly formatted and classified as a patch.

LGTM

github run

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 1, 2026

create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@13770

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@13770

miniflare

npm i https://pkg.pr.new/miniflare@13770

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@13770

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@13770

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@13770

@cloudflare/vitest-pool-workers

npm i https://pkg.pr.new/@cloudflare/vitest-pool-workers@13770

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@13770

@cloudflare/workers-utils

npm i https://pkg.pr.new/@cloudflare/workers-utils@13770

wrangler

npm i https://pkg.pr.new/wrangler@13770

commit: 89b895e

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 1, 2026

✅ All changesets look good

@petebacondarwin petebacondarwin marked this pull request as ready for review May 1, 2026 20:32
@workers-devprod workers-devprod requested review from a team and penalosa and removed request for a team May 1, 2026 20:33
@workers-devprod
Copy link
Copy Markdown
Contributor

workers-devprod commented May 1, 2026

Codeowners approval required for this PR:

  • @cloudflare/d1
  • @cloudflare/workers-kv
  • ✅ @cloudflare/wrangler
Show detailed file reviewers
  • packages/wrangler/src/tests/d1/create.test.ts: [@cloudflare/d1]
  • packages/wrangler/src/tests/d1/delete.test.ts: [@cloudflare/d1]
  • packages/wrangler/src/tests/d1/execute.test.ts: [@cloudflare/d1]
  • packages/wrangler/src/tests/d1/export.test.ts: [@cloudflare/d1]
  • packages/wrangler/src/tests/d1/info.test.ts: [@cloudflare/d1]
  • packages/wrangler/src/tests/d1/insights.test.ts: [@cloudflare/d1]
  • packages/wrangler/src/tests/d1/list.test.ts: [@cloudflare/d1]
  • packages/wrangler/src/tests/d1/migrate.test.ts: [@cloudflare/d1]
  • packages/wrangler/src/tests/d1/timeTravel.test.ts: [@cloudflare/d1]
  • packages/wrangler/src/tests/d1/utils.test.ts: [@cloudflare/d1]
  • packages/wrangler/src/tests/kv/key.test.ts: [@cloudflare/workers-kv]

Comment thread .changeset/wrangler-auth-scoped-account-list.md Outdated
Comment thread packages/wrangler/src/user/whoami.ts Outdated
Comment thread packages/wrangler/src/user/fetch-accounts.ts Outdated
Comment thread packages/wrangler/src/user/fetch-accounts.ts Outdated
Comment thread packages/wrangler/src/user/fetch-accounts.ts Outdated
@petebacondarwin petebacondarwin force-pushed the pbd/wrangler/auth-scoped-account-list branch from abfc494 to f28d9a9 Compare May 5, 2026 15:53
@petebacondarwin petebacondarwin requested a review from penalosa May 5, 2026 15:54
@workers-devprod workers-devprod requested a review from a team May 5, 2026 15:54
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@petebacondarwin petebacondarwin force-pushed the pbd/wrangler/auth-scoped-account-list branch from 60cfedc to 06d382c Compare May 5, 2026 20:43
devin-ai-integration[bot]

This comment was marked as resolved.

@petebacondarwin
Copy link
Copy Markdown
Contributor Author

@penalosa - this will probably need a "Codeowners Bypass" review since it touches D1 and KV tests.

@petebacondarwin petebacondarwin force-pushed the pbd/wrangler/auth-scoped-account-list branch from c3a97ae to 29e9093 Compare May 6, 2026 09:48
Copy link
Copy Markdown
Contributor

@penalosa penalosa left a comment

Choose a reason for hiding this comment

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

Some nits, but otherwise lgtm

Comment thread packages/wrangler/src/user/fetch-accounts.ts Outdated
Comment thread packages/wrangler/src/user/fetch-accounts.ts
Comment thread packages/wrangler/src/user/fetch-accounts.ts Outdated
Comment thread packages/wrangler/src/user/fetch-accounts.ts Outdated
Wrangler now intersects `/accounts` and `/memberships` when listing
accounts in `wrangler whoami` and the interactive 'Select an account'
prompt. Previously `whoami` rendered every account the underlying user
belonged to, including accounts the active OAuth token or API token had
no membership in, and it could disagree with the account picker (which
only consulted `/memberships`).

For Account API Tokens (where `/memberships` returns 9109) the
behavior is unchanged: the single account associated with the token is
shown via the existing `/accounts` fallback.
Per review feedback, drop the broad permissive escape hatch in
fetchAllAccounts and only fall back to /accounts when /memberships
fails with 9109 (Insufficient permissions) — the structural Account
API Token case. Any other failure on either endpoint is now surfaced
to the user instead of silently degrading.

This also removes the /accounts-failure fallback to /memberships:
if /accounts is unavailable we cannot compute the intersection
correctly, so we propagate the error.

whoami no longer requests permissive mode and will now fail when
/memberships is broken, matching the rest of the CLI.
Per follow-up review, broaden the /memberships fallback so that both
9109 (Insufficient permissions) and 10000 (Authentication error)
trigger the fall back to /accounts. 10000 covers tokens that work
against /accounts but not /memberships (e.g. missing the membership
read scope), so callers shouldn't be blocked by it.

The fallback is now the default for all callers — whoami, account
selection, and any other code path through fetchAllAccounts —
removing the previous integration-test-only special case.

Restore the unit test that asserts the 10000 fallback works, and
add a matching 'helpful error when /accounts is also unusable'
test for parity with the 9109 case. Update the propagate test to
use a code outside the tolerated set (1003), and restore the
whoami snapshot test for 10000 alongside a new whoami test that
asserts non-tolerated /memberships errors still fail the command.
@petebacondarwin petebacondarwin force-pushed the pbd/wrangler/auth-scoped-account-list branch from 29e9093 to be0c4ec Compare May 6, 2026 13:05
Copy link
Copy Markdown
Contributor

@penalosa penalosa left a comment

Choose a reason for hiding this comment

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

Codeowners bypass

Copy link
Copy Markdown
Contributor

@workers-devprod workers-devprod left a comment

Choose a reason for hiding this comment

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

Codeowners reviews satisfied

@github-project-automation github-project-automation Bot moved this from Untriaged to Approved in workers-sdk May 6, 2026
@petebacondarwin petebacondarwin merged commit beff19c into main May 6, 2026
63 of 64 checks passed
@petebacondarwin petebacondarwin deleted the pbd/wrangler/auth-scoped-account-list branch May 6, 2026 14:08
@github-project-automation github-project-automation Bot moved this from Approved to Done in workers-sdk May 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants