Dashboard › cli › Distillation
8b13240c-a906-4e0e-bd05-1f095357edfb["lore_tm_v1_BeTSNZnYj6W3vTlpf0SgHUgJ6LcsLi6WfjD3-2tlF5k","lore_tm_v1_XVBcpenPQVaRFMxP2Gne4a4AK0YXOtgDSlP9j7zYPDs","lore_tm_v1_56bnZ_DrMImpVDgllN0ZchtwGZqPkupnfjdy-wMGqms","lore_tm_v1_WQU42oiir5zqIOoxbR51LvBZF9K46XWzX6KkG4NYcMA","lore_tm_v1_Yd_EZsLz03idmJfp0kQquBnT6SSPirQeiapCwfR8FkQ","lore_tm_v1_KijpDeKQPO-niawTH0p-44pInt6nAbWbsicUqOeZj18","lore_tm_v1_qboRp1bg-t-9k3hpz4l3Boy8gSNsExVVJY6sN30B6w4","lore_tm_v1_B3UhgpGPI9LtIz_dBqDb-2uD7zDQb8N78sXcj3sQAT8","lore_tm_v1_9bwDIYZtkczp2b6XG_l4LuqYUNikWQQzb6yLtIrCuew","lore_tm_v1_G7hAFPTUHMkY4VrVokUanMFIJWUmjoQ2LVsu2eMI2iw","lore_tm_v1_rWGiT7wYAjektDDpgBWaS-eT6V2m_qXtZ4oQu3kRGn4","lore_tm_v1_VD9-6I_66H7KnR-7-ElFpK97IOBozKmtyW9Wusaplpo","lore_tm_v1_cW2VtfiuHmtzqer1hw961akEAyRKeHXlO4N5-ym9hVc"]
Date: Sep 10, 2026
clearAuth() in packages/cli/src/lib/db/auth.ts:439-465 deletes auth row id = 1, user_info row id = 1, all org_regions, and all pagination_cursors; calls clearAllIssueOrgCache(), resets identity-fingerprint/auth-token/auth-row/stored-credentials caches, calls clearTrustedHostState(), and dynamically imports ../response-cache.js to await clearResponseCache(), treating absent cache directories as non-fatal.getIdentityFingerprint() namespaces cache keys according to getAuthConfig precedence: forced env token > stored OAuth (prefers stable refresh_token, falls through expired access-only rows) > env token > ANON_IDENTITY ("<anon>"); its memoized fingerprint is reset by setAuthToken and clearAuth.useTestConfigDir() in packages/cli/test/helpers.ts:104-143 creates a unique config directory per test, stores the previous CONFIG_DIR_ENV_VAR/SENTRY_CONFIG_DIR, closes the DB and resets resetAuthTokenCache(), resetAuthRowCache(), resetHasStoredCredsCache(), and resetIdentityFingerprintCache() before and after each test, sets process.env[CONFIG_DIR_ENV_VAR] = dir, then cleans up the test directory.SENTRY_CONFIG_DIR value and never delete it; deleting it causes cross-file failures when later module-level code or beforeEach hooks receive undefined.preload.ts always sets SENTRY_CONFIG_DIR, so the saved prior config-directory value is always defined in practice.useEnvSandbox(keys) in packages/cli/test/helpers.ts:156-176 saves listed environment values, deletes every listed key before each test, then restores defined values verbatim and deletes keys that were initially missing after each test; intended for security/host-scoping tests.packages/cli/src/lib/db/regions.ts maintains process-local trustedRegionOrigins: Set<string> for origins vouched for by the active tokenβs issuing host through /users/me/regions/ responses or persisted org_regions entries; it lazy-seeds from distinct persisted region_url values after normalizeOrigin().registerTrustedRegionUrls(urls) normalizes and registers region origins before persistence; isTrustedRegionOrigin(origin) lazy-seeds then tests membership; setOrgRegion() and setOrgRegions() automatically register persisted region URLs to keep in-process and persistent trust state synchronized.clearTrustedHostState() in packages/cli/src/lib/db/regions.ts:90-95 clears trusted regional origins and resets lazy seeding; clearAuth() invokes it to evict identity-bound regional trust extensions, but it deliberately does not clear the token-host.ts login trust anchor because that anchor represents the current auth login intent and is required during re-authentication.org_regions caches organization-to-region mappings for multi-region Sentry support, including optional numeric org_id for offline DSN-host resolution (e.g. o1081365 β numeric ID 1081365 β org slug); getOrgRegion() records a "region" cache hit, while getOrgByNumericId() returns { slug, regionUrl } or undefined.packages/cli/src/lib/token-host.ts imports isTrustedRegionOrigin and calls it at line 119; clearTrustedHostState() is imported by packages/cli/src/lib/db/auth.ts and invoked at line 456.packages/cli/test/lib/db/auth.test.ts, auth.property.test.ts, auth.host.test.ts, and model-based.test.ts; auth.test.ts documents that environment mutation without resetAuthTokenCache() leaves the cache stale by design, while setAuthToken() must invalidate it automatically.packages/cli/test/lib/db/model-based.test.ts uses fast-check and Vitest to generate random SQLite database-operation sequences against a simplified DbModel, targeting unexpected state transitions, caching races, and invariants such as clearAuth() clearing regions.DbModel tracks stored auth fields (token, refreshToken, expiresAt, issuedAt), simulated SENTRY_AUTH_TOKEN and SENTRY_TOKEN, a regions map, project aliases plus fingerprint, and version-check state; tested DB functions include clearAuth, getAuthConfig, getAuthToken, isAuthenticated, isEnvTokenActive, setAuthToken, clearOrgRegions, getAllOrgRegions, getOrgRegion, setOrgRegion, and setOrgRegions.enrich403Detail() in packages/cli/src/lib/api/infrastructure.ts:41-84 treats "disabled this feature" as an org-policy failure rather than authentication: it advises requiring org:admin/manager/owner or team:admin, and rejects re-auth/token-scope guidance as actively wrong. Other 403s advise env-token users to check scopes at https://sentry.io/settings/account/api/auth-tokens/, or OAuth users to run sentry auth refresh --scope <scope> / sentry auth login.enrich401Detail() distinguishes seat-limit lockout ("member-disabled-over-limit") from authentication: it advises asking an org owner to upgrade/free a seat or targeting another org such as sentry init my-other-org/; otherwise env-token users are told to create a new token at https://sentry.io/settings/account/api/auth-tokens/, and OAuth users to run sentry auth login.packages/cli/src/lib/sentry-client.ts:116-172 prepareHeaders(input, init, token) first rejects untrusted request origins via isRequestOriginTrusted() with HostScopeError, then validates unsigned sntrys_ token claims through isHostTrustedForClaim() while allowing control-silo regional fan-out. It preserves caller/Request headers, sets Authorization: Bearer <token> and default User-Agent, injects sentry-trace/baggage telemetry headers when available, and applies URL-scoped custom proxy/IAP/mTLS headers.handleUnauthorized(headers) refuses a second refresh when RETRY_MARKER_HEADER is present; otherwise calls refreshToken({ force: true }), and if refreshed is true replaces the bearer token, sets RETRY_MARKER_HEADER: "1", and retries. Refresh failures are debug-logged and return false.packages/cli/src/lib/sentry-client.ts: recognizes 301, 302, 303, 307, and 308; rejects redirects with missing or invalid Location using ApiError; converts non-GET/non-HEAD requests to GET for 303 and POST requests to GET for 301/302; otherwise reconstructs a Request for the destination.getNextRedirectRequest() currently derives a new redirect request, extracts the bearer token from the prior headers, and calls prepareHeaders(nextRequest, undefined, getBearerToken(headers)) before carrying forward RETRY_MARKER_HEADER; comments state every redirect rebuilds headers only after destination host scoping passes.fetchWithTimeout() uses manual redirects (redirect: "manual"), an internal AbortController, and endpoint-specific timeout selection; assertRedirectLimit() throws ApiError once redirects reach MAX_REDIRECTS.