Skip to content

SDK sources and project registries ​

osdk has two independent network-selection mechanisms. They must not be conflated:

MechanismWhat it obtainsConfigurationDecision pointConsumer retries
SDK/tool sourceArtifacts and release metadata for Node, Go, Python, manager binaries, npm:<package>, and others[sources], [sources.<tool>], --sourcebefore backend resolution and installationartifact URLs may fail over; an external manager that has started is never rerun
Project dependency registrynpm-compatible packages resolved by npm/pnpm/Yarn/Bun/Deno project commands[registries.npm] plus native manager configurationbefore osdk exec or a shim starts the manageran eligible invocation makes at most one launch attempt after selection; if every candidate is unhealthy, no launch is attempted

The source for osdk install pnpm@11 determines where pnpm itself comes from. The registry for a later pnpm install determines where project dependencies are resolved. --source never rewrites the project registry.

SDK source ranking ​

effective_sources starts with backend defaults, removes disabled entries, adds custom sources (a matching id replaces a built-in), drops enabled=false, and sorts by ascending priority.

effective_sources_with_env folds a mirror taken from the environment on top of that. A backend declares its own native variables through Backend::env_mirror (rustup's RUSTUP_DIST_SERVER / RUSTUP_UPDATE_ROOT, go's GOPROXY) and its own endpoint rule through Backend::validate_env_endpoint. The first non-empty variable in declaration order wins and is validated before it enters the pool, so a malformed value is reported as a configuration problem rather than as an unreachable mirror. A value that validates joins the candidates under the reserved id env, as SourceKind::Custom with forward_credentials = false and priority = 1; a value equal to an existing candidate's endpoint is not added twice, so one host is never probed twice. Under mode = "env" that candidate replaces the list outright and a missing or invalid value is an error.

Because the fold happens before pin handling, an explicit pin and --source still win. The reserved id env never appears in a per-tool custom list, so Go's private-module narrowing (its retain keeps only custom and pinned ids) still excludes the ambient candidate, and a private module path is not sent to a public proxy just because GOPROXY is set. refresh probes the same set that selection ranks; otherwise the candidate-set fingerprint would never match and the cache would always be invalid. See source/env.rs.

ranked_source_list then applies this algorithm:

  1. A configured pin or one-shot --source moves the matching source first while keeping the others as fallbacks. The one-shot key currently uses the user-supplied tool name, so the invocation must use the canonical backend ID; aliases do not receive that override.
  2. Offline mode skips probes; it reuses a cached order only when the candidate-set fingerprint matches, otherwise it uses priority order.
  3. ordered and pinned selection also use that order directly.
  4. auto first reads the per-tool probe cache; it is usable only when every cached result is within the TTL. Cache schema 2 also validates a candidate-set fingerprint, so URL, order, priority, enabled-state, credential-forwarding, or header changes cannot reuse stale results; header values are stored only as hashes.
  5. When stale, all sources are probed concurrently, each bounded by probe_timeout_ms, reading at most about 1 MiB.
  6. Successful probes are sorted by the composite score throughput - ttfb_ms in descending order. Failed probes are appended, so real downloads can still use them as final fallbacks.

Each backend owns metadata lookup and artifact URL construction, so a source must actually implement that backend's expected layout. The shared pipeline performs a complete candidate attempt in URL order; one URL gets up to three transient-error attempts, then a download, checksum/attestation, extraction, or required-subdirectory failure moves to the next URL. A successful probe proves neither target-artifact availability nor integrity. Zig and Gradle merge ranked indexes and rebase their absolute artifact URLs; Conda queries and solves per source base, then verifies each candidate package URL against repodata SHA-256. See source/select.rs and pipeline/mod.rs.

Explicit Source.headers applies to metadata requests and source probes made by osdk and is independent of forward_credentials. Headers are attached only when the initial URL has the configured index/download origin, survive same-origin redirects, and are permanently stripped after the first cross-origin redirect. Only hashes of header values participate in metadata/probe cache identity; clear values are not persisted. The managed npm/pnpm delegates receive only a registry override inside an otherwise empty osdk-owned configuration, so npm:<package> package fetches do not forward Source.headers. Project operations may use native trusted configuration; global npm-tool installs reject authenticated/private native pass-through while running in their isolated prefix. Go command tools add one stricter boundary: if custom sources exist, only those custom candidates (plus an explicitly pinned candidate) are ranked, so a private module path is not sent to public default proxies. Custom headers are rejected because go install cannot enforce osdk's per-request forwarding policy. A fresh resolution joins the preferred and remaining candidates with | as one GOPROXY, letting Go perform download failover inside one provider invocation; lock replay restores only its recorded primary proxy. Cargo Registry selection instead reads the sparse config.json and probes the exact .crate URL before fixing source identity, avoiding a rerun after build scripts may have started. pypi: probes the requested project page and injects the winner as uv/pip's default index.

Project registry preflight ​

The planner lives in package_registry.rs, called by apply_package_registry_plan. It handles only an explicit allow-list of commands that may fetch npm packages and first identifies the manager family. An unknown Yarn major is conservatively passed through.

Direct-shim ownership and shim generation share one Corepack command mapping: npm/npx, pnpm/pnpx, and yarn/yarnpkg. A valid independent backend selection wins; otherwise routing falls back to an existing Corepack launcher in the selected Node installation. Node does not count these names as its own commands, so reshim cannot delete a newly generated independent-manager shim as a conflict. npm and pnpm reached through Node/Corepack still enter registry planning; a Yarn major cannot be inferred from the Node version, so it is passed through conservatively.

Every eligible invocation performs fresh concurrent anonymous probes; it does not reuse the SDK-source probe cache. The endpoint is the standard npm-compatible <base>/-/ping and must return a successful status plus a non-empty JSON object no larger than 64 KiB. Each request has a bounded timeout. The redirect chain may contain at most three URLs, meaning at most two redirects are followed, and it must remain on the original HTTPS origin with no downgrade, cross-origin target, URL credentials, or loop. Probes send no registry token, cookie, or Authorization extracted from native configuration. Ordinary system HTTP(S) proxy settings still apply.

Candidate selection is intentionally precise:

  • Explicit [registries.npm].urls is the complete candidate set. Project configuration replaces the user-level block, preserves order, and chooses the first healthy entry.
  • Without explicit URLs, a recognized anonymous public native registry precedes the built-in npmmirror/npmjs fallbacks.
  • Only a purely built-in set chooses the lowest-latency healthy endpoint.
  • URLs are normalized and deduplicated.

The selected URL is injected only into the single child process using its native variable: npm npm_config_registry, pnpm pnpm_config_registry, Yarn Classic YARN_REGISTRY, Yarn Berry YARN_NPM_REGISTRY_SERVER, Bun BUN_CONFIG_REGISTRY, or Deno NPM_CONFIG_REGISTRY.

Single-launch and fail-closed behavior ​

For an eligible invocation that actually enters registry preflight, osdk makes at most one manager launch attempt after selecting a healthy candidate and never retries after launch; if every candidate is unhealthy, no launch is attempted. Process creation itself can still fail. Conservative pass-through invocations do not enter this fail-closed preflight path.

In the control flow, exec_cmd calls apply_package_registry_plan before its single Command::status() call. The direct-shim path likewise invokes the same planner before the sole exec in osdk-shim::real_main. RegistryPlan::Unavailable becomes an error before startup. A non-zero exit after manager startup is returned directly, without selecting another registry or replaying lifecycle scripts. Unix osdk exec integration tests cover:

Conservative pass-through and limits ​

The manager is passed through without probing, injection, or argument/config rewriting when there is an explicit registry CLI argument, an existing relevant registry environment variable, a strict offline flag, a command outside the network allow-list, an explicit cwd/config argument whose context cannot be reproduced safely, unreadable native configuration, a private or unknown registry, any scoped registry, authentication/TLS/native-proxy policy, or an unknown Yarn major. If osdk cannot establish “anonymous, public, and free of scope/auth policy,” it does not optimize.

A healthy registry proves only that its anonymous metadata endpoint works. Absolute tarball or Git URLs in lockfiles or metadata, local files, workspaces, Git dependencies, Deno JSR, and ordinary URL imports may bypass the selected default registry. osdk neither parses nor rewrites lockfiles and does not proxy credentials. An install pinned to a dead absolute URL may therefore fail, and it is never rerun after the manager starts even if another registry is healthy. The complete design boundary is documented in docs/package-registry-design.md.

Released under the MIT License