Dashboard › cli › Distillation
113329c2-10fd-48a2-9dbd-9fe10c8049fc["lore_tm_v1_oQNV54D0MtzKa-XdSTs8X0QPX35FBQD7MWBxd9wFUHU","lore_tm_v1_Uh_ieqddJM54Ac6hHVJWGPZJ0FyxXV0IN_9mnHOjgBc","lore_tm_v1_EKb1eu95GtRk8-LRWp80Hl01mYbIBjN-rf5QXToiIx4","lore_tm_v1_oYoMJkCvxhnuBRb3hmBjAjrqTxJQRNMXeqZoIB11lX0","lore_tm_v1_QiBP5wCa1uIAyeq31fmsHx_76O-SVajHA3mpQsnn3Xs","lore_tm_v1_4bEPpIl0-XZ4g5ksHhKcTZL3fUXwKIqJ_YKkoewrW8o","lore_tm_v1_HNRVrg7CyJ0S6uRp2z11SA_CtMtyOo43wIb-au7rtNE","lore_tm_v1_3PT-jQXMJBYSGKFnmNB_TWOvjrLSasG0VIZjL7rp2Q8"]
src/sources/github-release.ts implements the stable-channel githubReleaseSource() using GitHub Release assets named <binaryName>, <binaryName>.gz, and <binaryName>.patch; owner/repository URL, binary name, user agent, fetch implementation, and instrumentation are injected through GitHubReleaseSourceConfig.extractSha256(asset) accepts case-insensitive digests matching ^sha256:([0-9a-f]+)$, lowercases the captured hexadecimal value, and returns null for absent or malformed digests; getStableTargetSha256(release, binaryName) finds the exact binary asset and delegates to extractSha256().extractStableChain() returns either StableChainInfo or a classified StableChainFailure with one of "no_patches", "malformed_chain", "too_long", or "over_budget".extractStableChain() finds target/current release indexes and returns "no_patches" if either is absent or targetIdx >= currentIdx; it slices releases from target through immediately before current, rejects chains longer than MAX_STABLE_CHAIN_DEPTH as "too_long", and rejects a missing target binary SHA-256 as "malformed_chain".${binaryName}.patch; a missing published patch is classified as "malformed_chain". It sums listed patch-asset sizes and returns "over_budget" once the total exceeds fullGzSize * SIZE_THRESHOLD_RATIO.steps begin at currentVersion and traverse reversed chain releases as { fromVersion, toVersion: release.tag_name }; successful extraction returns { patchUrls, expectedSha256, steps }.githubReleaseSource() wraps each network request with optional InstrumentHook: "fetch-releases" for the release list and "download-patch" for each patch asset. Without a hook, the underlying async call runs directly.fetchRecentReleases() requests ${releasesUrl}?per_page=${MAX_STABLE_CHAIN_DEPTH + 2} with Accept: application/vnd.github.v3+json, the configured "User-Agent", and optional AbortSignal; thrown fetch failures and non-OK responses return null.downloadPatch() sends the configured "User-Agent" and optional signal, returns Uint8Array data for an OK response, and returns null for thrown fetch failures or non-OK responses.githubReleaseSource().resolveChain() reports "network" when release retrieval fails; "no_patches" when the target release is absent; and "malformed_chain" when the target exists but lacks ${binaryName}.gz. It passes that gzip assetβs size to extractStableChain() and reports any returned classified failure.Promise.all(). A listed asset that fails to download is treated as transient and reported as "network" rather than a malformed publish; success returns a PatchChain containing downloaded { data, size } links, actual downloaded totalSize, expectedSha256, and steps.feat/toolkit-bridge-upgrade was synchronized with origin/feat/toolkit-bridge-upgrade; HEAD was commit 4094ae9a7 (feat(cli): add toolkit upgrade bridge), based on bd065083c (feat(local): Add Vercel Analytics (#1563))..github/workflows/ci.yml, root package.json, packages/cli/install, packages/cli/package.json, packages/cli/src/commands/cli/upgrade.ts, packages/cli/src/lib/binary.ts, packages/cli/src/lib/delta-upgrade.ts, packages/cli/src/lib/ghcr.ts, packages/cli/src/lib/release-notes.ts, packages/cli/src/lib/upgrade.ts, packages/cli/src/lib/version-check.ts, packages/cli/test/commands/cli/upgrade.test.ts, packages/cli/test/lib/binary.test.ts, packages/cli/test/lib/delta-upgrade.test.ts, packages/cli/test/lib/ghcr.test.ts, packages/cli/test/lib/install-script.test.ts, packages/cli/test/lib/release-notes.test.ts, packages/cli/test/lib/upgrade.test.ts, and packages/cli/test/lib/version-check.test.ts./home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/custom-ca.ts loads custom CA bundles in priority order: 1. sentry cli defaults ca-cert stored in SQLite; 2. NODE_EXTRA_CA_CERTS.readCaCertFile(path) synchronously reads UTF-8 via readFileSync(path, "utf-8"); unreadable/missing files return { ok: false, reason: "CA certificate file not found or not readable: <path>" }, and content lacking -----BEGIN CERTIFICATE----- returns a PEM-validation failure.tryReadPem(path) enforces this by calling readCaCertFile(), logging result.reason as a warning on failure, and returning undefined.custom-ca.ts dynamically accesses optional Node 24+ tls.setDefaultCACertificates() through createRequire(import.meta.url); Node 22 lacks this API, while Bun uses per-request tls.ca.injectIntoNodeTls(customPem) is a no-op when setDefaultCACertificates is unavailable. Otherwise it calls setDefaultCACertificates([...rootCertificates, customPem]), logs successful injection at debug level, and catches/logs failures rather than throwing.resolved, resolvedSource, resolvedLabel, and hasResolved. CaSource is "default" | "env" | "none".resolve() catches failures from getDefaultCaCert() and falls through to environment sources. It trims env.NODE_EXTRA_CA_CERTS, tries the stored default before the environment path, and selects the first readable valid PEM.resolve() combines it with Nodeβs rootCertificates using newline joins because Bunβs tls.ca replaces rather than augments the built-in Mozilla CA bundle; it stores { tls: { ca: combined } }, records source/label, logs the loaded path, and calls injectIntoNodeTls(pem).getCustomTlsOptions() returns the cached Bun-shaped { tls: { ca: string } } or undefined; getCustomCaSource() returns the resolved source.warnIfSaasWithEnvCa(targetUrl) emits at most one warning, only when the selected source is "env" and isSentrySaasUrl(targetUrl) is true. Stored defaults are treated as explicit acknowledgment and suppress the warning; the warning recommends sentry cli defaults ca-cert /path/to/cert.pem.TLS_ERROR_PATTERNS: "unable to get local issuer certificate", "unable to verify the first certificate", "UNABLE_TO_VERIFY_LEAF_SIGNATURE", "DEPTH_ZERO_SELF_SIGNED_CERT", and "SELF_SIGNED_CERT_IN_CHAIN". It deliberately excludes CERT_HAS_EXPIRED and ERR_TLS_CERT_ALTNAME_INVALID because expiration and hostname mismatch are not CA-trust failures.customFetch() is defined at line 305 of /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/custom-ca.ts.getCustomCaCerts() returns resolved?.tls.ca as a raw combined PEM string for Node.js https.RequestOptions.ca and Sentry SDK NodeTransportOptions.caCerts, or undefined when no custom CA is configured.customFetch(input, init?) is the required drop-in fetch wrapper for non-authenticated calls: it calls bare fetch(input, init) when no custom TLS options exist, otherwise calls fetch(input, { ...init, ...tlsOpts }). Authenticated API calls instead use fetchWithTimeout() in sentry-client.ts, which applies TLS options alongside the SaaS warning.__resetForTests() resets custom-CA process state exactly by setting resolved = undefined, resolvedSource = "none", resolvedLabel = "", hasResolved = false, and warnedSaas = false.