Skip to content

fix(cli): Route org-scoped API requests to the account that knows the org - #1976

Merged
BYK merged 2 commits into
mainfrom
fix/cli-api-org-account-routing
Nov 5, 2026
Merged

BYK merged 2 commits into
mainfrom
fix/cli-api-org-account-routing

Conversation

@sentry-junior

@sentry-junior sentry-junior Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

Fixes #1803.

sentry api organizations/<org>/... used the invocation's current account even when another stored login could reach <org>. Typed commands avoid this only because resolveOrgRegion calls selectAccountForOrg before building the request.

This moves the routing into the shared request layer. getsentry/sentry-api-schema#129 makes createApiTransport pass CredentialProvider.current({ url, scope }), where scope is the org (and project) the URL path targets. The CLI changes:

  • sentry-client.ts: for unpinned transports, current now runs selectAccountForOrg(scope.organization) before reading the credential. It is limited to accounts on the request's server, because the URL is already built. A numeric org id is matched as an id, as in region.ts.
  • getDefaultSdkConfig no longer pins the credential. Its only caller is sentry api's prepareRawApiRequest, so without this the transport could not route that request. The base URL still comes from the current credential, routing stays on that server, and assertCredentialScope still guards every send.
  • selectAccountForOrg gets an optional server that limits candidates, the env token included, to that server.
  • parseOrgProjectFromApiPath delegates to parseApiPathScope from @sentry/api/client, so the CLI and the transport read org scope the same way.
  • The auth docs fragment mentions sentry api paths under organization-based selection.

Existing rules still hold. One invocation never mixes accounts: once an org has picked an account, later requests are no-ops. Pinned credentials, such as region discovery and withStoredAccount, are not re-routed. Forced env tokens are never overridden.

Draft because: the CLI needs a published @sentry/api release that includes getsentry/sentry-api-schema#129. This PR still needs the catalog bump in pnpm-workspace.yaml, currently 1.20.0. Against 1.20.0, current: async (request) => … and the CredentialRequest import do not type-check.

Not covered: sentry api to an org that only an account on a different server can reach. The URL's host is fixed before the transport runs, so routing there would need the command to pick the account before building the URL. That's a CLI-layer change; I left it out to keep the fix in @sentry/api.

Verification, run with a local build of the sentry-api-schema branch installed in place of @sentry/api@1.20.0:

  • pnpm run typecheck and pnpm run lint in packages/cli pass.
  • New tests in test/lib/db/account-routing.test.ts cover routing by path org, unscoped requests staying on the active account, and the same-server limit. The first fails without the transport change.
  • pnpm run test:unit passes, except for 6 permission-based tests (completions, upgrade lock, resilient DB, code scanner, file-changes) that also fail on clean main in my sandbox.

via @BYK.

--

View Session in Sentry

… org

The shared transport now hands the credential provider the organization a
request's path targets (getsentry/sentry-api-schema#129). The CLI uses it to
run selectAccountForOrg for every request, limited to accounts on the
request's server since its URL is already built. getDefaultSdkConfig no
longer pins the credential, so `sentry api organizations/<org>/...` reaches
another stored login's org without `sentry auth switch`.

parseOrgProjectFromApiPath delegates to parseApiPathScope from
@sentry/api/client.

Fixes #1803

Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
@vercel

vercel Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
sentry-local Ready Ready Preview Nov 5, 2026 10:25am UTC

Request Review

@BYK
BYK marked this pull request as ready for review November 5, 2026 10:06
@BYK
BYK enabled auto-merge (squash) November 5, 2026 10:06
@github-actions github-actions Bot added the risk: medium PR risk score: medium label Nov 5, 2026
1.26.0 adds parseApiPathScope and passes the request's org scope to
CredentialProvider.current (getsentry/sentry-api-schema#129), which
the account routing in this branch depends on.

Co-Authored-By: BYK <burak.kaya@sentry.io>
@BYK
BYK merged commit 29fac5d into main Nov 5, 2026
43 checks passed
@BYK
BYK deleted the fix/cli-api-org-account-routing branch November 5, 2026 10:37
BYK added a commit that referenced this pull request Nov 5, 2026
#1978)

Follow-up to #1976 (#1803).

#1976 routes `sentry api organizations/<org>/...` to the stored account
that knows `<org>`, but the transport picks the account only after the
request URL is built. So it could only choose among accounts on that
URL's server. For example, with a SaaS login active, a self-hosted org's
account was never used.

This picks the account before the URL is built:

- **`getDefaultSdkConfig`** takes an optional `path`. When the path
names an org, it runs `selectAccountForOrg` with no server limit before
reading `getApiBaseUrl()`. An account on another server brings its
server along (`followDefaultAccountHost`), so the base URL follows it.
- **`prepareRawApiRequest`** passes the endpoint as `path` when no
`baseUrl` is given.
- **What stays on one server:** a full URL passed to `sentry api`
(`baseUrl`), and an explicit server (`SENTRY_URL`/`SENTRY_HOST`,
`.sentryclirc`). For these, the transport's existing same-server routing
still applies.

This stays in the CLI rather than `@sentry/api`. Switching servers
changes which origin receives the credential, and the transport
intentionally doesn't rewrite a URL it has already built. Picking the
server is the CLI's job, the same way `resolveOrgRegion` already does it
for typed commands.

## Tests

In `account-routing.test.ts`, the old "only consider accounts on the
request's server" test becomes three:

- **Another server:** an org whose account is on another server gets
that account's token and URL. This test fails without the fix.
- **Explicit server:** an explicit `SENTRY_URL` keeps the request on
that server.
- **Full URL:** a full URL (`baseUrl`) only considers accounts on its
server.

`pnpm run tsc` and `pnpm run lint` pass. The CLI suite passes except for
6 permission-based tests that also fail on `main` in my sandbox
(completions, upgrade, resilient DB, code-scanner, file-changes).

The docs fragment `apps/cli-docs/src/fragments/commands/auth.md` is
updated to match.

<!-- junior-request-attribution:start -->
via @BYK.
<!-- junior-request-attribution:end -->

<!-- junior-session-footer:start -->
<!-- junior-conversation-id:local%3Aweb%3Aad43917b182be622bccdd8f7 -->

--

[View Session in
Sentry](https://sentry.sentry.io/explore/conversations/local%3Aweb%3Aad43917b182be622bccdd8f7/?project=4510944073809921)

<!-- junior-session-footer:end -->

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: BYK <126780+BYK@users.noreply.github.com>

This branch was successfully deployed

1 active deployment
Preview — 85db2d12 Deployed Nov 5, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: medium PR risk score: medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Route sentry api requests by organization

1 participant