Dashboard › cli › Distillation
4071e8a7-b1ea-48c5-8468-a606ce3b7317["lore_tm_v1_uoSxVx4vqF6Kue1GWNoRoVuuOPVj70tcN2hjpW6zbx0","lore_tm_v1_NplQu5jAIFE-beI7CbqSmwhiHseh_rDN5Wbz2iAlBL4","lore_tm_v1_qSyOzhYI684muLBWwIrq0hvckErgcDLHS_d6E5BfmLY","lore_tm_v1_ZJLuu4etgo9Iln2eZRDds1B-Z1yjuVjpwIpdumWOSYc","lore_tm_v1_8EmWotuiQyWD_Cmhb17uY1tuhB71yMfDf8ySHecGF5g","lore_tm_v1_SkZsZcQseMl2RcxV_Fh6xF82QWK-rgPIVuiDzOuYS_Y","lore_tm_v1_yGSST7rtAj5ImyNh7LLOVRcFZdk9GzlbAhEFVWxnApA","lore_tm_v1_VrJWUbX9lWFlWqe32OFM3WqgAqhA9rw4m8agzyMcyms","lore_tm_v1_F_W7nAGDIlDFCg2pYe-Jy1rT7K29d4WPIOnqRKG3VxM","lore_tm_v1_gopRj_DCZf3BNxvqcvNsc4V0v7bSjhP79gfFGMoaPTE","lore_tm_v1_XxbJMt-UoH8oWEvh61eHq4-492AmL-hKzXzb-s0HdaM","lore_tm_v1_XvKXHW_vcdZJ5_PZ2KErMmichVK_ngWMGfT-1W1slDE","lore_tm_v1_GEOEIqhJGOk5q1GQsbE_rZz947vMG1ynMvCwUU_4yVk","lore_tm_v1_iHohgIR9qJYVZBgaNV7_vdSRB_sK0msgQWlX_7XGMb8","lore_tm_v1_IzZb8iky-JBdfd6KOTborj0rk6RDbhaGY6kvkEZxxmQ"]
packages/cli/src/lib/version-check.ts (prefetchNightlyPatches() line 237 and prefetchStablePatches() line 239), packages/cli/src/lib/upgrade.ts (attemptDeltaUpgrade() line 991), and packages/cli/src/lib/release-notes.ts (line 554); implementations are in packages/cli/src/lib/delta-upgrade.ts (fetchRecentReleases() line 155, resolveStableDelta() line 487, resolveNightlyDelta() line 505, attemptDeltaUpgrade() line 523, prefetchNightlyPatches() line 615, and prefetchStablePatches() line 622), with remaining matches in packages/cli/test/lib/delta-upgrade.test.ts and packages/cli/test/lib/delta-upgrade.mocked.test.ts.packages/cli/node_modules/binpatch contains exactly 4 entries: dist/, LICENSE, package.json, and README.md; packages/cli/node_modules/binpatch/dist contains exactly 3 entries: index.d.ts, index.js, and index.js.map.packages/cli/node_modules/binpatch/dist/index.d.ts is 614 lines and describes a product-neutral, dependency-free streaming TRDIFF10 binary-patch library adapted from Sentry CLI’s bspatch.ts.[0..8] magic "TRDIFF10", [8..16] controlLen as i64 LE, [16..24] diffLen as i64 LE, [24..32] newSize as i64 LE, then zstd(control) | zstd(diff) | zstd(extra); offtin() reads zig-bsdiff sign-magnitude signed 64-bit little-endian values rather than two’s complement.read()/pread through a single-block read-ahead cache, so the base “never sits fully in the JS heap”; only referenced windows are loaded and are served from the OS page cache populated by the reflink copy.node:zlib’s createZstdDecompress(); output is incrementally written with fs.openSync + fs.writeSync, and the fd is closeSync’d before return to prevent an ETXTBSY race when spawning the output on Linux; SHA-256 is computed inline with node:crypto’s createHash.applyPatchChainInMemory(oldPath, patches, destPath, onBytes?) keeps all intermediate results in memory, so intermediates “never hit disk and only the final binary is hashed.” This avoids N−1 redundant disk writes, temp copies, and SHA-256 passes; only the running binary is copied to a temporary file, and reads/writes never use the same path.applyPatchToMemory(oldFile, patchData) applies a patch to an in-memory base; applyPatch(oldPath, patchData, destPath) is the documented one-shot wrapper over applyPatchChainInMemory() and returns the written output’s SHA-256 hex digest.MAX_OUTPUT_SIZE guards untrusted TRDIFF10 newSize before new Uint8Array(newSize) allocation and final SHA-256 verification; the declaration explains the gateway binary is approximately 310 MB and the ceiling is 2 GiB to prevent OOM denial of service.addDiffChunk() performs wrapping byte addition (old + diff mod 256) four bytes at a time with SWAR on Uint32Array: lows = (a & 0x7f7f7f7f) + (b & 0x7f7f7f7f), highs = (a ^ b) & 0x80808080, and result = lows ^ highs; a tail loop handles n % 4.<fromVersion>-<toVersion>.patch for raw patches and chain-<fromVersion>-<toVersion>.json for metadata; makeCache(cacheDir) injects the cache location, creates it lazily on first write, and exposes save(), load(), cleanup(), and clear(). ChainMeta stores fromVersion, toVersion, expectedSha256, cachedAt, and patches; each PatchStepMeta stores fromVersion, toVersion, and size.MAX_STABLE_CHAIN_DEPTH = 10, MAX_NIGHTLY_CHAIN_DEPTH = 30, SIZE_THRESHOLD_RATIO = 0.6, and PATCH_TAG_PREFIX = "patch-".PatchChain contains patches, totalSize, expectedSha256, and optional steps; DeltaResult contains sha256, patchBytes, and chainLength; the final binary SHA-256 is the sole trust anchor.InstrumentHook wraps each consumer-requested HTTP step and must transparently preserve the wrapped promise’s resolution or rejection; throwing from the hook aborts the operation just as the wrapped function throwing would.BinpatchErrorReason is exactly "network_error" | "execution_failed" | "version_not_found" | "offline_cache_miss"; BinpatchError carries one of those typed reasons and has no telemetry or SDK coupling."resolve" | "download" | "apply" | "verify"; events are phase, bytes (written and nullable total), or done; no handler means silence.safeProgress(handler) prevents a throwing consumer ProgressHandler from aborting the underlying operation because progress is always cosmetic; progress-handler implementations must never throw.SourceStrategy.resolveChain(currentVersion, targetVersion, signal?, report?) returns an oldest-first PatchChain or null; a null result always falls back to a full download.UnavailableReporter classification “never changes control flow (a null return is always a full-download fallback)”; DeltaUnavailableReason is exactly "no_patches" | "malformed_chain" | "too_long" | "over_budget" | "network", and telemetry lets consumers distinguish benign unpublished patches from poisoned or malformed published manifests.DeltaSource is exactly "cache" | "network" | "offline_miss"; DeltaTelemetry supports onResolved, onOfflineMiss, and onUnavailable, but the caller always falls back to a full download regardless of unavailable reason.resolveAndApply(opts) checks the optional patch cache first, then the source unless offline is true; it applies the chain to oldPath, verifies SHA-256, writes destPath, and returns DeltaResult | null. It throws only for genuine apply/verification failures such as a corrupt patch or SHA mismatch, which callers treat as a full-download fallback.ResolveAndApplyOpts injects source, currentVersion, targetVersion, oldPath, destPath, optional cache, offline, onProgress, telemetry, and signal; offline: true means never touching the network—cache hit or bust.OciClient is an anonymous, read-only OCI registry client configured with injected registry, repo, userAgent, and optional fetch; it exposes getAnonymousToken(), fetchManifest(), listTags(), downloadBlob(), and downloadBlobBuffer(), with optional AbortSignal support.Authorization header because ghcr.io returns HTTP 307 to Azure Blob Storage and automatic forwarding of authorization would produce 404.ghcrSource(config) resolves OCI patch manifests tagged <patchTagPrefix><version>; manifests require from-version=<prev>, sha256-<binaryName>=<hex>, and a patch layer titled <binaryName>.patch. The target manifest’s <binaryName>.gz layer supplies the full-download size for the ratio gate.getPatchFromVersion(), getPatchTargetSha256(), filterAndSortChainTags(), and validateChainStep(); StepFailureReason is "malformed" | "over_budget", while NightlyChainFailure.failure is "malformed_chain" | "over_budget".GhcrSourceConfig injects binaryName, targetTag(version), compareVersions(a, b), and optional instrument, in addition to OciClientConfig; instrumentation wraps token exchange, manifest fetches, tag listing, and blob downloads.githubReleaseSource(config) resolves stable patch chains from GitHub Release assets named <binaryName>, <binaryName>.gz, and <binaryName>.patch; their roles are respectively expected SHA-256, ratio-gate size, and previous-release delta. Chains are oldest-first and capped by MAX_STABLE_CHAIN_DEPTH and SIZE_THRESHOLD_RATIO.extractSha256(), getStableTargetSha256(), and pure extractStableChain(); StableChainFailure.failure is exactly "no_patches" | "malformed_chain" | "too_long" | "over_budget". GitHubReleaseSourceConfig injects releasesUrl, binaryName, userAgent, optional fetch, and optional per-request instrument.packages/cli/test/lib/ghcr.test.ts added tests that getAnonymousToken(UPGRADE_SOURCES[0]) requests a token scope containing scope=repository:getsentry/toolkit:pull and resolves "toolkit-token", and that fetchNightlyManifest("token", undefined, UPGRADE_SOURCES[0]) requests /v2/getsentry/toolkit/manifests/nightly.packages/cli/test/lib/install-script.test.ts added a test that parses UPGRADE_SOURCES=(...) from the install script and requires its whitespace-separated repositories to equal UPGRADE_SOURCES.map((source) => source.githubRepo), preserving the shared source ordering.packages/cli/test/commands/cli/upgrade.test.ts line 168 says it mocks fetch to simulate a GHCR manifest returning a specific nightly version.packages/cli/src/lib/version-check.ts lines 286–287 choose fetchLatestNightlyVersion(signal) or fetchLatestFromGitHub(signal); packages/cli/src/lib/upgrade.ts defines fetchLatestFromGitHub() line 399, fetchLatestNightlyVersion() line 467, fetchLatestVersion() line 498, versionExists() line 551, downloadBinaryToTemp() line 902, and executeUpgrade() line 1122; packages/cli/src/commands/cli/upgrade.ts calls these around lines 289, 325, 642, and 727.GITHUB_RELEASES_URL, GitHub tag URLs, or binary download URLs: packages/cli/src/lib/upgrade.ts still uses GITHUB_RELEASES_URL for /latest at line 403 and /tags/${version} at line 562 and calls getBinaryDownloadUrl(version) at line 766; packages/cli/src/lib/delta-upgrade.ts uses the constant for githubReleaseSource and ?per_page=12; packages/cli/src/lib/release-notes.ts uses ?per_page=${CHANGELOG_MAX_RELEASES}.UpgradeErrorReason and UpgradeError are defined in packages/cli/src/lib/errors.ts at lines 586 and 600 respectively.