Dashboard › cli › Session 1QSumG3ibJRO
1QSumG3ibJROI40b7Perform an independent read-only correctness review of the current worktree patch for issue #1568 in getsentry/cli. Do not edit files. Focus on packages/cli/src/lib/constants.ts, src/lib/sentry-client.ts, auth/token-host precedence, request routing, explicit SENTRY_HOST/SENTRY_URL behavior including whitespace, storage OAuth vs env tokens, SENTRY_FORCE_ENV_TOKEN, malformed claims, and test adequacy. Inspect source and relevant tests. Return findings first, ordered by severity with file:line references, then residual gaps. End with exactly PASS if no merge-blocking correctness defect, otherwise MUST-FIX. Do not report generic style suggestions.
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus</path> <type>directory</type> <entries> .craft.yml .git .github/ .gitignore .lore.md .nojekyll .npmrc .opencode/ .plans/ .ruff_cache/ AGENTS.md apps/ CHANGELOG.md codemods/ coverage/ dist-bin/ dist/ docs/ LICENSE.md node_modules/ package.json packages/ pnpm-lock.yaml pnpm-workspace.yaml README.md test-results.junit.xml (26 entries) </entries>
M .lore.md M packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dashboard.md M packages/cli/plugins/sentry-cli/skills/sentry-cli/references/event.md M packages/cli/plugins/sentry-cli/skills/sentry-cli/references/explore.md M packages/cli/plugins/sentry-cli/skills/sentry-cli/references/feedback.md M packages/cli/plugins/sentry-cli/skills/sentry-cli/references/issue.md M packages/cli/plugins/sentry-cli/skills/sentry-cli/references/log.md M packages/cli/plugins/sentry-cli/skills/sentry-cli/references/replay.md M packages/cli/plugins/sentry-cli/skills/sentry-cli/references/span.md M packages/cli/plugins/sentry-cli/skills/sentry-cli/references/trace.md M packages/cli/src/lib/constants.ts M packages/cli/src/lib/sentry-client.ts M packages/cli/test/lib/constants.test.ts M packages/cli/test/lib/security/sntrys-claim-mismatch.test.ts .lore.md | 700 ++++++++++++--------- .../skills/sentry-cli/references/dashboard.md | 2 ...
Found 100 matches (more matches available)
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/token-host.ts:
Line 55: * token unless `SENTRY_FORCE_ENV_TOKEN` is set.
Line 57: export function getActiveTokenHost(): string | undefined {
Line 59: const forceEnv = hasEnvToken && !!getEnv().SENTRY_FORCE_ENV_TOKEN?.trim();
Line 129: const tokenHost = getActiveTokenHost();
Line 138: * url instead of `getActiveTokenHost()`.
Line 158: if (getActiveTokenHost()) {
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/token-claims.ts:
Line 10: * (the attacker who can poison `SENTRY_HOST` via `$GITHUB_ENV` can't read or
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/constants.ts:
Line 22: export const DEFAULT_SENTRY_HOST = "sentry.io";
Line 25: export const ...
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/test/lib/token-host.test.ts /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/test/lib/token-host.property.test.ts /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/test/lib/token-claims.test.ts /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/test/lib/token-claims.property.test.ts /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/test/lib/sentry-client.test.ts /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/test/lib/sentry-client.invalidation.test.ts /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/test/lib/scan/constan...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/token-host.ts</path> <type>file</type> <content> 1: /** 2: * Host-Scoped Token Trust Model 3: * 4: * Tokens (env or stored OAuth) are bound to a specific Sentry host. The fetch 5: * layer (and the `.sentryclirc` / URL-arg entry points) check each request's 6: * destination against the token's recorded host and refuse to attach 7: * credentials when they don't match — so untrusted routing inputs can't leak 8: * credentials to an attacker's host. 9: * 10: * Host equivalence: 11: * - Exact origin match (scheme + host + explicit port). 12: * - SaaS equivalence class: a token scoped to `https://sentry.io` is valid for 13: * any `*.sentry.io` subdomain. Non-SaaS hosts match exactly — no subdomain 14: * suffix matching (a `sentry.acme.com` token does NOT match 15: * `sentry.acme.evil.com`). ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/token-claims.ts</path>
<type>file</type>
<content>
1: /**
2: * Sentry Org-Auth-Token (`sntrys_`) Claim Extraction
3: *
4: * Format: `sntrys_<base64(JSON{iat, url, region_url, org})>_<random-secret>`
5: * (server-side: getsentry/sentry `orgauthtoken_token.py`).
6: *
7: * The claim is **NOT signed** — anyone can forge a `sntrys_` string with any
8: * `url`. However, for legitimate tokens the claim IS authoritative: the real
9: * server wrote it at issuance time, and it's immune to env-injection attacks
10: * (the attacker who can poison `SENTRY_HOST` via `$GITHUB_ENV` can't read or
11: * modify the token bytes). `captureEnvTokenHost` uses the claim as the
12: * primary trust source for `sntrys_` tokens, ahead of env vars. ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/db/auth.ts</path>
<type>file</type>
<content>
1: /**
2: * Authentication credential storage (single-row table pattern).
3: */
4:
5: import { createHash } from "node:crypto";
6: import { DEFAULT_SENTRY_URL, getConfiguredSentryUrl } from "../constants.js";
7: import { getEnv } from "../env.js";
8: import { getEnvTokenHost } from "../env-token-host.js";
9: import { logger } from "../logger.js";
10: import { normalizeOrigin } from "../sentry-urls.js";
11: import { withDbSpan } from "../telemetry.js";
12: import { getDatabase } from "./index.js";
13: import { clearAllIssueOrgCache } from "./issue-org-cache.js";
14: import { clearTrustedHostState } from "./regions.js";
15: import { runUpsert } from "./utils.js";
16:
17: /** Refresh when less than 10% of token lifetime remains */
18: export const REFRESH_THRESHOLD = 0.1;
19:
20: /** Default token lifetime (1 hour) ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/sentry-client.ts</path>
<type>file</type>
<content>
1: /**
2: * Sentry API Client Configuration
3: *
4: * Provides request configuration for @sentry/api SDK functions,
5: * including authentication, retry logic, timeout, and multi-region support.
6: *
7: * Instead of managing client instances, we pass configuration per-request
8: * through the SDK function options (baseUrl, fetch, headers).
9: */
10:
11: import { setTimeout as sleepMs } from "node:timers/promises";
12: import { getTraceData } from "@sentry/node-core/light";
13: import { maybeWarnEnvTokenIgnored } from "./auth-hint.js";
14: import { computeInvalidationPrefixes } from "./cache-keys.js";
15: import {
16: DEFAULT_SENTRY_URL,
17: getConfiguredSentryUrl,
18: getUserAgent,
19: } from "./constants.js";
20: import {
21: buildTlsErrorDetail,
22: getCustomTlsOptions,
23: ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/sentry-client.ts</path>
<type>file</type>
<content>
430: * made stale. Awaited so a subsequent read in the same command sees
431: * fresh data. Prefix computation: {@link computeInvalidationPrefixes}.
432: *
433: * Never throws: a post-mutation housekeeping failure must not convert
434: * a successful mutation into a caller-visible error. Defense-in-depth
435: * for future regressions — the helpers we call are already no-throw
436: * today.
437: */
438: async function invalidateAfterMutation(
439: method: string,
440: fullUrl: string,
441: response: Response
442: ): Promise<void> {
443: if (method === "GET" || !response.ok) {
444: return;
445: }
446: try {
447: const prefixes = computeInvalidationPrefixes(fullUrl, getApiBaseUrl());
448: await Promise.all(
449: prefixes.map((prefix) => ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/env-token-host.ts</path> <type>file</type> <content> 1: /** 2: * Env-Token Host Snapshot 3: * 4: * Captures the host an env-var auth token (`SENTRY_AUTH_TOKEN` / 5: * `SENTRY_TOKEN`) is scoped to, BEFORE any post-boot code path can mutate 6: * `env.SENTRY_HOST`/`env.SENTRY_URL` (specifically before 7: * `applySentryCliRcEnvShim` writes from a `.sentryclirc` file). 8: * 9: * Trust model for the snapshot source: 10: * 11: * - `SENTRY_HOST`/`SENTRY_URL` from env are NOT unconditionally trusted. 12: * In layered CI environments (e.g. GitHub Actions `$GITHUB_ENV`), a 13: * low-privilege step can write env vars that a later high-privilege step 14: * inherits — without having read access to `SENTRY_AUTH_TOKEN`. So 15: * env-host and env-token may have different integrity levels. ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/sentry-urls.ts</path>
<type>file</type>
<content>
1: /**
2: * Sentry URL Utilities
3: *
4: * Utilities for constructing Sentry web URLs.
5: * Supports self-hosted instances via SENTRY_URL environment variable.
6: */
7:
8: import {
9: DEFAULT_SENTRY_HOST,
10: DEFAULT_SENTRY_URL,
11: getConfiguredSentryUrl,
12: normalizeUrl,
13: } from "./constants.js";
14:
15: /**
16: * Get the Sentry web base URL.
17: * Supports self-hosted instances via SENTRY_URL env var.
18: */
19: export function getSentryBaseUrl(): string {
20: return getConfiguredSentryUrl() ?? DEFAULT_SENTRY_URL;
21: }
22:
23: /**
24: * Build the org-scoped base URL using the subdomain pattern.
25: * E.g. "https://sentry.io" + "my-org" → "https://my-org.sentry.io"
26: *
27: * @param orgSlug - Organization slug
28: * @returns Origin URL with org as subdomain
29: */
30: export ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/test/lib/constants.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Tests for normalizeUrl and getConfiguredSentryUrl.
3: *
4: * The primary invariant — bare hostnames get `https://` prepended so that
5: * downstream URL construction produces valid URLs — is tested via property-based
6: * tests in constants.property.test.ts. These unit tests cover specific edge
7: * cases and the env-var integration path.
8: */
9:
10: import { afterEach, beforeEach, describe, expect, test } from "vitest";
11: import {
12: getCliEnvironment,
13: getConfiguredSentryUrl,
14: normalizeUrl,
15: } from "../../src/lib/constants.js";
16:
17: describe("normalizeUrl", () => {
18: test("returns undefined for undefined", () => {
19: expect(normalizeUrl(undefined)).toBeUndefined();
20: });
21:
22: test("returns undefined for empty string", () => {
23: ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/test/lib/security/sntrys-claim-mismatch.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Defense-in-depth: `sntrys_` token claim vs request-origin mismatch.
3: *
4: * The fetch-layer guard refuses to attach a `sntrys_` token when its
5: * embedded `url` claim disagrees with the request origin. Defends users
6: * with access to multiple Sentry instances against routing one
7: * instance's token to another. Claim is unsigned (see token-claims.ts),
8: * so this catches honest misconfigurations more than malicious attacks.
9: */
10:
11: import { afterEach, beforeEach, describe, expect, test } from "vitest";
12: import {
13: extractFetchUrl,
14: mintSntrysToken,
15: resetHostScopingState,
16: useEnvSandbox,
17: useTestConfigDir,
18: } from "../../helpers.js";
19:
20: const ENV_KEYS = [
21: "SENTRY_AUTH_TOKEN",
22: "SENTRY_TOKEN",
23: ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/test/lib/token-host.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Unit tests for token-host: normalizeOrigin + isHostTrusted.
3: *
4: * Core invariants (SaaS equivalence, subdomain-attack resistance, port
5: * sensitivity) are also covered by test/lib/token-host.property.test.ts.
6: * This file focuses on the specific cases that property generators don't
7: * cover well (exact edge strings, malformed inputs).
8: */
9:
10: import { describe, expect, test } from "vitest";
11: import { normalizeOrigin } from "../../src/lib/sentry-urls.js";
12: import { isHostTrusted } from "../../src/lib/token-host.js";
13:
14: describe("normalizeOrigin", () => {
15: test("returns origin for a valid https URL", () => {
16: expect(normalizeOrigin("https://sentry.io/api/0/")).toBe(
17: "https://sentry.io"
18: );
19: });
20:
21: test("lowercases the ...
Found 100 matches (more matches available)
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/test/lib/token-claims.test.ts:
Line 2: * Unit tests for `sntrys_` org-auth-token claim parsing.
Line 16: import { parseSntrysClaim } from "../../src/lib/token-claims.js";
Line 186: // claim object — never throw.
Line 201: test("treats forged claim same as legitimate (we don't verify signatures)", () => {
Line 203: // validate the claim's authenticity. An attacker can mint a token
Line 205: // must NEVER use the claim as a primary security signal — see
Line 206: // `src/lib/token-claims.ts` JSDoc.
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/test/lib/token-claims.property.test.ts:
Line 9: * 3. Forged claims parse identically to legitimate ones (this is by
Line 10: * design — see `token-claims.ts` JSDoc — and the property ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/test/lib/sentry-client.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Tests for the authenticated fetch retry + timeout behavior — CLI-1D6
3: * regression coverage.
4: */
5:
6: import { afterEach, beforeEach, describe, expect, test } from "vitest";
7: import { setAuthToken } from "../../src/lib/db/auth.js";
8: import { TimeoutError } from "../../src/lib/errors.js";
9: import {
10: __injectTimeoutOverrideForTests,
11: __resolveRequestTimeoutMsForTests,
12: getSdkConfig,
13: resetAuthenticatedFetch,
14: } from "../../src/lib/sentry-client.js";
15: import { mockFetch, useTestConfigDir } from "../helpers.js";
16:
17: useTestConfigDir("sentry-client-");
18:
19: let originalFetch: typeof globalThis.fetch;
20: const REGION_URL = "https://us.sentry.io";
21:
22: beforeEach(async () => {
23: originalFetch = globalThis.fetch;
24: // Non-expiring token — ...
(no output)
{"body":"When only `SENTRY_AUTH_TOKEN` is set (an `sntrys_` org-auth token embedding a custom instance URL, e.g. `http://localhost:8000`) and no `SENTRY_URL`/`SENTRY_HOST`/`--url` is provided, commands such as `sentry debug-files upload` fail with:\n\n```\nError: Credentials: https://sentry.io\nRefusing to route requests here because it doesn't match the host your Sentry credentials are for (http://localhost:8000).\nTo use this host, run: sentry auth login --url https://sentry.io\nTo keep using your current credentials, remove this URL override.\n```\n\nRunning `sentry auth logout` first does not help; the same error persists.\n\nRoot cause (source-verified):\n- `getConfiguredSentryUrl()` in `packages/cli/src/lib/constants.ts` (used by `getApiBaseUrl()`/`getControlSiloUrl()` in `lib/sentry-client.ts`) only reads `SENTRY_HOST`/`SENTRY_URL` and otherwise falls back to `DEFAULT_SENTRY_URL` (`https://sentry.io`). It never consults the `sntrys_` token's embedded `url` claim.\n- Separately, ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/db/auth.ts</path>
<type>file</type>
<content>
460: const { clearResponseCache } = await import("../response-cache.js");
461: await clearResponseCache();
462: } catch {
463: // Non-fatal: cache directory may not exist yet
464: }
465: }
466:
467: export function isAuthenticated(): boolean {
468: const token = getAuthToken();
469: return !!token;
470: }
471:
472: /** Fingerprint returned when no token is present (logged out, no env var). */
473: export const ANON_IDENTITY = "<anon>";
474:
475: /** Memoized fingerprint. Identity doesn't change within a single CLI run. */
476: let cachedFingerprint: string | undefined;
477:
478: /**
479: * Opaque fingerprint of the active bearer identity, used to namespace
480: * response-cache keys so entries never leak across accounts. ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/api/infrastructure.ts</path>
<type>file</type>
<content>
1: /**
2: * API Client Infrastructure
3: *
4: * Shared helpers, types, constants, and raw request functions used by
5: * all domain-specific API modules. This is the foundation layer that
6: * other modules in `src/lib/api/` import from.
7: */
8:
9: import { promisify } from "node:util";
10: import { zstdCompress as zstdCompressCb } from "node:zlib";
11: import { parseSentryLinkHeader } from "@sentry/api";
12: // biome-ignore lint/performance/noNamespaceImport: Sentry SDK recommends namespace import
13: import * as Sentry from "@sentry/node-core/light";
14: import type { z } from "zod";
15:
16: import { extractRequiredScopes } from "../api-scope.js";
17: import { getActiveEnvVarName, isEnvTokenActive } from "../db/auth.js";
18: import { getEnv } from "../env.js";
19: import { ApiError, AuthError, ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/api/infrastructure.ts</path>
<type>file</type>
<content>
340: }
341: }
342:
343: return searchParams.toString() ? searchParams : undefined;
344: }
345:
346: /**
347: * Get SDK config for an organization's region.
348: * Resolves the org's region URL and returns the config.
349: */
350: export async function getOrgSdkConfig(orgSlug: string) {
351: const regionUrl = await resolveOrgRegion(orgSlug);
352: return getSdkConfig(regionUrl);
353: }
354:
355: /**
356: * Maximum number of pages to follow when auto-paginating.
357: *
358: * Safety limit to prevent runaway pagination when the API returns an unexpectedly
359: * large number of pages. At API_MAX_PER_PAGE items/page this allows up to 5,000 items, which
360: * covers even the largest organizations. Override with SENTRY_MAX_PAGINATION_PAGES
361: * env var for edge cases. ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/region.ts</path>
<type>file</type>
<content>
1: /**
2: * Region resolution for multi-region Sentry support.
3: *
4: * Provides utilities to resolve the correct region URL for an organization,
5: * using cached data when available or fetching from the API when needed.
6: */
7:
8: import { getOrganization } from "@sentry/api";
9: import { getConfiguredSentryUrl } from "./constants.js";
10: import { getOrgByNumericId, getOrgRegion, setOrgRegion } from "./db/regions.js";
11: import { stripDsnOrgPrefix } from "./dsn/index.js";
12: import { withAuthGuard } from "./errors.js";
13: import { getSdkConfig } from "./sentry-client.js";
14: import { getSentryBaseUrl, isSentrySaasUrl } from "./sentry-urls.js";
15:
16: /**
17: * Promise cache for org region resolution, keyed by orgSlug. ...
Found 40 matches /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/api/teams.ts: Line 32: const config = await getOrgSdkConfig(orgSlug); Line 54: const config = await getOrgSdkConfig(orgSlug); Line 82: const config = await getOrgSdkConfig(orgSlug); Line 109: const config = await getOrgSdkConfig(orgSlug); Line 144: const config = await getOrgSdkConfig(orgSlug); /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/api/repositories.ts: Line 35: const config = await getOrgSdkConfig(orgSlug); Line 60: const config = await getOrgSdkConfig(orgSlug); /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/api/replays.ts: Line 306: const config = await ...
Found 22 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/telemetry.ts:
Line 709: Sentry.setTag("is_self_hosted", !isSentrySaasUrl(getSentryBaseUrl()));
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/sentry-urls.ts:
Line 19: export function getSentryBaseUrl(): string {
Line 31: const base = getSentryBaseUrl();
Line 51: return isSentrySaasUrl(getSentryBaseUrl());
Line 164: return `${getSentryBaseUrl()}/organizations/${orgSlug}/`;
Line 178: return `${getSentryBaseUrl()}/settings/${orgSlug}/projects/${projectSlug}/`;
Line 192: return `${getSentryBaseUrl()}/organizations/${orgSlug}/issues/${issueId}/`;
Line 207: return `${getSentryBaseUrl()}/organizations/${orgSlug}/issues/?query=event.id:${eventId}`;
Line 222: : `${getSentryBaseUrl()}/settings/${orgSlug}/`;
Line 236: return ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/package.json</path>
<type>file</type>
<content>
1: {
2: "name": "sentry",
3: "version": "0.40.0-dev.0",
4: "description": "Sentry CLI - A command-line interface for using Sentry built by robots and humans for robots and humans",
5: "repository": {
6: "type": "git",
7: "url": "git+https://github.com/getsentry/cli.git"
8: },
9: "main": "./dist/index.cjs",
10: "type": "module",
11: "types": "./dist/index.d.cts",
12: "exports": {
13: ".": {
14: "import": {
15: "types": "./dist/index.d.mts",
16: "default": "./dist/index.mjs"
17: },
18: "require": {
19: "types": "./dist/index.d.cts",
20: "default": "./dist/index.cjs"
21: }
22: }
23: },
24: "bin": {
25: "sentry": "./dist/bin.cjs"
26: },
27: "files": [
28: "dist/bin.cjs",
29: "dist/index.cjs",
30: ...
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/test/lib/region.test.ts /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/test/lib/api-client.multiregion.test.ts /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/test/e2e/multiregion.test.ts
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/test/lib/region.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Region Resolution Tests
3: *
4: * Tests for resolving organization regions in multi-region Sentry support.
5: */
6:
7: import { setTimeout as sleep } from "node:timers/promises";
8: import { afterEach, beforeEach, describe, expect, test } from "vitest";
9: import { setAuthToken } from "../../src/lib/db/auth.js";
10: import { setOrgRegion } from "../../src/lib/db/regions.js";
11: import {
12: isMultiRegionEnabled,
13: resolveOrgRegion,
14: } from "../../src/lib/region.js";
15: import { getSentryBaseUrl } from "../../src/lib/sentry-urls.js";
16: import { useTestConfigDir } from "../helpers.js";
17:
18: useTestConfigDir("region-resolve-");
19:
20: beforeEach(async () => {
21: // Clear any SENTRY_HOST/SENTRY_URL override for most tests
22: delete process.env.SENTRY_HOST;
23: delete ...
Found 58 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/app.ts:
Line 19: import { debugFilesRoute } from "./commands/debug-files/index.js";
Line 109: "debug-files": debugFilesRoute,
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/sdk.generated.ts:
Line 1842: "debug-files": {
Line 1845: invoke<unknown>(["debug-files","check"], {}, params?.path ? [params.path] : []) as Promise<unknown>,
Line 1848: invoke<unknown>(["debug-files","find"], { type: params?.type, "no-well-known": params?.noWellKnown, "no-cwd": params?.noCwd, path: params?.path }, positional) as Promise<unknown>,
Line 1851: invoke<unknown>(["debug-files","upload"], { type: params?.type, id: params?.id, "require-all": params?.requireAll, "no-debug": params?.noDebug, "no-unwind": params?.noUnwind, "no-sources": params?.noSources, ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/api/debug-files.ts</path>
<type>file</type>
<content>
1: /**
2: * Debug Information File (DIF) Upload API
3: *
4: * Uploads native debug information files (Mach-O/dSYM, ELF, PE/PDB, Portable
5: * PDB, WASM, Breakpad, source bundles) via the DIF chunk-upload + assemble
6: * protocol shared with ProGuard and Dart symbol-map uploads.
7: *
8: * Protocol: each file's raw bytes are chunked directly (no ZIP wrapping) and
9: * assembled through `projects/{org}/{project}/files/difs/assemble/`. The body
10: * keys each file by its overall SHA-1 checksum, with `name`, optional
11: * `debug_id`, and the per-chunk checksum list. Multiple files are batched into
12: * a single assemble request, like ProGuard. ...
Found 66 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/api/traces.ts:
Line 27: import { resolveOrgRegion } from "../region.js";
Line 117: const regionUrl = await resolveOrgRegion(orgSlug);
Line 157: const regionUrl = await resolveOrgRegion(orgSlug);
Line 201: const regionUrl = await resolveOrgRegion(orgSlug);
Line 425: const regionUrl = await resolveOrgRegion(orgSlug);
Line 562: const regionUrl = await resolveOrgRegion(orgSlug);
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/api/sourcemaps.ts:
Line 23: import { resolveOrgRegion } from "../region.js";
Line 323: const regionUrl = await resolveOrgRegion(org);
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/api/seer.ts:
Line 11: import { resolveOrgRegion } from "../region.js";
...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/api/debug-files.ts</path>
<type>file</type>
<content>
410: const encoding = pickUploadEncoding(serverOptions.compression);
411:
412: // Honor the per-file cap. Use the server-advertised `maxFileSize`, falling
413: // back to `DEFAULT_MAX_DIF_SIZE` when the server omits it (`0`) — the same
414: // fallback the scan gate uses, so in-memory `--include-sources` bundles
415: // (which bypass the scan gate) are still capped here.
416: const effectiveMaxFileSize =
417: serverOptions.maxFileSize && serverOptions.maxFileSize > 0
418: ? serverOptions.maxFileSize
419: : DEFAULT_MAX_DIF_SIZE;
420: const { accepted, dropped } = filterBySize(difs, effectiveMaxFileSize);
421:
422: // `difs` is non-empty (checked above), so an empty `accepted` means every
423: // file was dropped by the size gate. ...
DEPRECATED `test.poolOptions` was removed in Vitest 4. All previous `poolOptions` are now top-level options. Please, refer to the migration guide: https://vitest.dev/guide/migration#pool-rework
RUN v4.1.10 /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli
[info] [auth] Detected SENTRY_AUTH_TOKEN env var but using stored login for stored OAuth user.
Set SENTRY_FORCE_ENV_TOKEN=1 to prefer the env var.
[info] [auth] Detected SENTRY_AUTH_TOKEN env var but using stored login for stored OAuth user.
Set SENTRY_FORCE_ENV_TOKEN=1 to prefer the env var.
Test Files 3 passed (3)
Tests 56 passed (56)
Start at 09:39:03
Duration 20.31s (transform 16.57s, setup 680ms, import 20.31s, tests 11.92s, environment 0ms)
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/test/lib/token-claims.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Unit tests for `sntrys_` org-auth-token claim parsing.
3: *
4: * Mirrors the server's token format from
5: * `getsentry/sentry/src/sentry/utils/security/orgauthtoken_token.py`:
6: *
7: * sntrys_<base64(JSON{iat, url, region_url, org})>_<random-secret>
8: *
9: * The middle chunk is plaintext base64 (NOT base64url), and the trailing
10: * chunk is opaque entropy. The CLI's parser must match the server's
11: * `parse_token` semantics (strict prefix, exactly 2 underscores, valid
12: * base64 → valid UTF-8 → valid JSON object → truthy `iat`).
13: */
14:
15: import { describe, expect, test } from "vitest";
16: import { parseSntrysClaim } from "../../src/lib/token-claims.js";
17: import { mintSntrysToken } from "../helpers.js";
18:
19: describe("parseSntrysClaim", () => {
20: ...
Found 10 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/constants.ts:
Line 73: export function getConfiguredSentryUrl(): string | undefined {
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/telemetry.ts:
Line 472: const customUrl = getConfiguredSentryUrl();
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/sentry-urls.ts:
Line 20: return getConfiguredSentryUrl() ?? DEFAULT_SENTRY_URL;
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/sentry-client.ts:
Line 686: return getConfiguredSentryUrl() ?? getActiveTokenHost() ?? DEFAULT_SENTRY_URL;
Line 697: return getConfiguredSentryUrl() ?? getActiveTokenHost() ?? ...
Found 1 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-cactus/packages/cli/src/lib/region.ts:
Line 107: export function isMultiRegionEnabled(): boolean {
P1 — issue #1568 remains broken for org-scoped requests.
packages/cli/src/lib/region.ts:73 still uses getSentryBaseUrl(), which resolves only configured env URLs and otherwise returns https://sentry.io (src/lib/sentry-urls.ts:20). debug-files upload then calls resolveOrgRegion() at src/lib/api/debug-files.ts:441.
With only a self-hosted sntrys_ env token, the first region lookup still targets SaaS. The fetch host guard rejects it against the claim host at src/lib/sentry-client.ts:121-126, so the reported command continues to fail. The new fallback in getApiBaseUrl() does not reach this route.
test/lib/security/sntrys-claim-mismatch.test.ts:130-151 tests a direct apiRequestToRegion() call, bypassing resolveOrgRegion() and the failing debug-files upload path.SENTRY_FORCE_ENV_TOKEN enabled; it should prove the env token’s claim selects both the route and bearer.sntrys-claim-mismatch.test.ts:181-191 checks only base-URL selection, not authenticated request behavior or token non-disclosure.Focused tests passed: 56/56 across constants, region, and claim-mismatch suites.
MUST-FIX
Date: Sep 10, 2026 * 🔴 (09:33) User directed to always check `package.json` for the latest scripts; commands run from `packages/cli` or from repo root via `pnpm --filter sentry run <script>`. * 🔴 (09:33) User specified all packages must be placed in `devDependencies`, never `dependencies`, because everything is bundled at build time via esbuild; CI enforces this through `pnpm run check:deps`. *…
Date: Sep 10, 2026 * 🔴 (09:33) User specified that `throwOnError` is always `false` because errors are handled by the CLI itself. * 🔴 (09:33) User specified that control-silo endpoints are always on the control silo, including OAuth, user accounts, and regions. * 🟡 (09:33) Review evidence: worktree is `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/glowing-ca…
Date: Sep 10, 2026 * 🔴 [requested-review] (09:32) User requested an independent read-only correctness review of the current worktree patch for issue #1568 in getsentry/cli; explicitly instructed not to edit files. * 🔴 (09:32) User specified review focus: `packages/cli/src/lib/constants.ts`, `src/lib/sentry-client.ts`, auth/token-host precedence, request routing, explicit `SENTRY_HOST`/`SENTRY_U…