下载源与供应链安全
osdk 的 SDK/模型下载源与项目依赖 Registry 是两套控制面。本页说明前者,以及 offline、预发布、checksum、签名、GitHub attestation 和通用 GitHub Release backend。 npm-compatible Registry 见JavaScript 包管理器。
Source 命令参考
osdk source list TOOL_OR_PROVIDER
osdk source test TOOL
osdk source test huggingface|modelscope|civitai --model REFERENCE
osdk source add TOOL_OR_PROVIDER
--id ID
--download-url URL
[--index-url URL]
[--forward-credentials]
osdk source remove TOOL_OR_PROVIDER ID
osdk source pin TOOL_OR_PROVIDER ID
osdk source unpin TOOL_OR_PROVIDER| 命令/参数 | 作用 |
|---|---|
list TOOL_OR_PROVIDER | 列出有效来源、类型、URL 和 pin |
test TOOL | 强制重新探测普通 backend 并输出吞吐/TTFB 排名 |
test PROVIDER --model ... | 对 Hugging Face/ModelScope 仓库或精确 Civitai LoRA 版本的 metadata 与文件采样测速 |
add ... --id ID --download-url URL | 添加或替换同 ID 的用户级 custom source |
--index-url URL | metadata/index 与下载根不同时单独指定 |
--forward-credentials | 允许自定义模型 endpoint 接收 provider 凭据 |
remove TOOL_OR_PROVIDER ID | 删除用户级 custom source |
pin TOOL_OR_PROVIDER ID / unpin TOOL_OR_PROVIDER | 在用户配置中设置/移除 source pin |
add、remove、pin、unpin 都编辑用户 config.toml。--source ID 是一次性 优先来源并保留其他来源作为回退;同一调用里的工具请求必须使用规范 backend ID, 例如写 node 而不是 nodejs,否则当前实现不会应用覆盖。--refresh-sources 对 install、use、upgrade、exec 强制重新探测;对 model sync,仅在没有显式 endpoint 或 pin、选择策略为 auto 且非 offline 时刷新。当前对 lock、outdated、 list-remote 不生效。 模型 source test 缺少 --model 会失败,普通工具使用 --model 也会失败。
环境变量里的镜像
各工具链本身都支持用环境变量指定镜像:rustup 读 RUSTUP_DIST_SERVER (以及 RUSTUP_UPDATE_ROOT),go 命令读 GOPROXY,npm 系读 npm_config_registry、pnpm_config_registry、YARN_REGISTRY、 YARN_NPM_REGISTRY_SERVER、BUN_CONFIG_REGISTRY 等。
默认(mode = "auto")下 osdk 会先校验这些值,再把它们与内置镜像一起参与 探测并按实测速度择优,而不是无条件采用:
- 校验不通过(不是合法 URL、不是 https、带凭据、带 query 或 fragment)时, osdk 打印一条 warning 并忽略该值,继续用内置镜像,而不是静默丢弃;
- 校验通过则作为 id 为
env的候选加入探测,可在osdk source list <工具>中看到;若它与某个内置镜像地址相同,则不会重复出现; GOPROXY的off、direct以及逗号/竖线分隔的回退列表是合法的 go 设置, 但不是单一可探测的镜像,因此会被跳过并给出说明。
需要无条件遵循环境变量时(例如公司内网镜像即使较慢也必须使用)用 --source-mode env,此时缺失或不合法都会报错而不是回退,避免配置错误被 静默忽略。
优先级:显式选择始终高于环境变量。osdk source pin 与一次性的 --source ID 仍然优先,环境变量只在没有显式选择时参与竞争。
有效来源列表
[sources]
selection = "auto" # auto|pinned|ordered
mode = "auto" # auto|env,见下文「环境变量里的镜像」
probe_timeout_ms = 1500 # SDK / 工具来源探测
model_probe_timeout_ms = 8000 # 模型 metadata / 响应头 / 样本各阶段预算
cache_ttl = "6h"
[sources.node]
pin = "corp"
disable = ["tuna"]
[[sources.node.custom]]
id = "corp"
kind = "custom" # official|mirror|custom
download_url = "https://mirror.example/node/"
index_url = "https://mirror.example/node/index.json"
headers = [["X-Example", "value"]]
forward_credentials = false
priority = 0
enabled = true有效列表等于“内置来源减去 disable,再加 custom”。custom 的同名 ID 覆盖内置 来源,enabled=false 被过滤,较小 priority 排在前面。Civitai 内置 official(civitai.com)与 official-red(civitai.red)两个官方 source;可用 source pin 固定其中一个,auto 模式则按精确版本的实际可达性与速度选择。项目中的 source 设置需要 显式信任。
headers 是显式 source 配置,与 forward_credentials 不同。osdk 自己发起的 metadata 请求和 source probe 只在初始 URL 与该 source 的 index/download URL 同 origin 时附加 这些 header;同源 redirect 保留,第一次跨源 redirect 后永久移除,header 值也不会 明文写入 cache。受管的 npm/pnpm 子进程只会收到 registry 覆盖以及一份 osdk 自有的空配置, 因此 npm:<package> 的实际 package fetch 不转发这里的 header。项目包管理器调用可以使用原生 可信配置;全局 npm 工具为了隔离 prefix,会拒绝认证或私有原生配置透传,全局安装请使用 可匿名访问的已配置 Registry。
选择、探测与故障转移
selection | 行为 |
|---|---|
auto | 读取 TTL 内测速缓存,否则并发探测;以吞吐量为主、TTFB 为惩罚排序 |
ordered | 直接按 priority 顺序 |
pinned | 没有具体 sources.<tool>.pin 时与 ordered 相同 |
具体 pin 会把该来源移到第一位,但其余来源仍保留为失败回退,并非“只允许这一源”。 SDK / 工具来源探测默认预算为 1500 ms。模型探测改用独立的 model_probe_timeout_ms = 8000,metadata、响应头、64 KiB 样本读取三个阶段分别 拥有这份预算,并优先选择仓库中最小的非空文件。只要成功拿到响应,就认定来源可达; 样本 body 超时只会让吞吐未知,不再误报 unreachable。全部模型来源都失败的结果 不会按常规 6h TTL 缓存,因此短暂网络拥塞不会把所有来源长期钉死。非法 TTL 当前 仍静默回退为 6h。
由 osdk 自身执行的下载走共享流式管线,并非一次请求失败就停止。普通归档保持最多 3 次(等待 400 ms、800 ms);模型文件默认尝试 6 次,按 1/2/4/8/8 秒指数退避,并 输出可见警告。可通过 osdk config set 调整 sources.model_download_attempts 与 sources.model_download_retry_base_ms;sources.model_read_timeout_ms(默认 60000) 限定「无字节进展」时长,连接中途断流超过此值即让该次请求失败并进入上述重试,而不是永久挂起。 管线保留 .partial 文件及 ETag / Last-Modified,重试时用 Range + If-Range 续传;服务端忽略或返回错误 Range、对象 变化、来源 URL 改变时会安全重头下载。source probe 只负责排序,并不证明某个精确版本 存在;HTTP 200 也可能是镜像错误页。因此 osdk 直接处理的归档、裸二进制和自升级产物会 把下载、checksum/attestation 校验、解包及必需文件检查视为同一个候选尝试,任一步失败 都会清理该候选并继续下一个排序来源;receipt 只记录真正通过完整验证的 URL。模型在某个 来源耗尽尝试后也会继续剩余排序来源;所有来源都耗尽后才终止。
委托型安装器不能统一用“命令失败就重跑”处理,因为安装脚本可能已经产生副作用。osdk 改在安全边界内做目标级验证:Rust 对每个 source 重跑完整 rustup 下载命令;Cargo 在锁定 sparse index 前检查该 crate 精确版本的 config.json 下载端点;pypi: 用实际项目页而非 固定 pip 页探测,并把选中 index 作为 uv/pip 的默认 index;go: 把排序候选以 | 组成一次原生 GOPROXY 回退链。普通项目里的 npm/uv/pip 等命令仍只执行一次,不会在 可能已运行 lifecycle script 后盲目重放。HTTP metadata 在线请求失败后可使用 stale 缓存; 严格 offline 只读已有缓存,缓存产物仍会重新校验和解包。
离线模式
osdk --offline install bun@1.3.14
osdk --offline install # 可结合当前平台 lock
osdk --offline model sync qwen--offline 或 OSDK_OFFLINE=true 严格禁止网络:
- metadata、SDK archive、模型 metadata 和所选文件必须已缓存;
- 自动 source probe 被跳过;
source test及 SDK 安装类命令中的--refresh-sources会失败,model sync不会刷新,本就不支持该参数的命令仍忽略它; - 缺少缓存时明确报错,不会偷偷联网;
- 对支持通用 artifact receipt 的 backend,lock 中的 artifact URL/checksum 可支持离线 重装;pipeline 实际重装且有 checksum 时重新校验字节,已有完整 GitHub 安装仅在 receipt 的锁定文件名/checksum 与动态选项身份都匹配时复用;
npm:<package>不使用通用 artifact URL。schema 4osdk.lock延续 schema 3 的 npm metadata 模型,只保存 scope、installer 与可选原生 lock 身份,而不携带依赖图;仅靠这些 metadata 不能冷恢复依赖图。已有完整 安装也只在记录的选项匹配时复用;支持原生 lock 重放的操作还需要安装器拥有的 lock 与 已预热 cache/store。旧 lock schema 2 graph sidecar 仅用于兼容读取;cargo:工具只有在来源、selector、选项、平台和精确受管 Rust 身份都匹配时,才能 复用已有完整安装。全新离线安装或修复不受支持,因为 Cargo 原生 lock 与osdk.lock都不包含完整 source graph;go:工具也只能复用身份精确匹配的完整安装。其 schema 4 lock 会记录选中的 Go proxy、发现的 module root、公开构建选项与精确受管 Go 身份,但不记录全新离线构建所需 的传递 module graph;attestations=required还要求按 artifact SHA-256 缓存的证明 bundle,lock evidence 不能代替重新验证。
OSDK_OFFLINE 只控制 osdk 自己及其 hook 所管理的兼容环境;项目子进程是否完全 离线仍取决于下游工具的原生参数。
预发布版本
osdk install bun@canary
osdk install deno@beta
osdk install github:owner/repo@1.2.0-beta.1
osdk --prerelease allow install bun@latest
osdk --prerelease never install bun@canary| 策略 | 行为 |
|---|---|
never | 拒绝预发布,包括显式精确版本或通道 |
if-explicit | 默认;仅显式预发布版本或 `canary |
allow | latest、前缀和 range 也可隐式选择预发布 |
该策略用于支持预发布感知的 Python、Bun、Deno 和 GitHub backend。 list-remote 当前仍只显示稳定版本。lock 会同时保存原始请求与精确解析版本。 Cargo Registry 解析使用自己的固定规则:始终排除 yanked release,latest 与数字前缀 只选择稳定版本,只有精确 Cargo selector 可以选择明确的未 yanked 预发布版本。
完整性、签名与 Attestation
osdk --require-checksums install node@20
osdk --attestations if-available install github:cli/cli@latest
osdk --attestations required install github:cli/cli@latest普通 checksum 支持 SHA-256、SHA-512、BLAKE3;npm SRI 支持 sha256- 和 sha512-,同时存在时优先 SHA-512。--require-checksums 的精确含义是:必须有普通 checksum,或有已验证 attestation 提供的可信 artifact SHA-256。在线发现的 checksum 会随 archive 缓存持久化,并在 pipeline 实际执行离线重装时重新校验。
签名验证默认由 settings.verify_signatures=true 开启,也可用 OSDK_VERIFY_SIGNATURES=false 明确关闭。它只适用于 backend 内置可信公钥的 Minisign manifest;当前注册的是 github:jdx/mise。缺少 manifest/签名可继续寻找其他 checksum,签名存在但无效则硬失败。
GitHub Artifact Attestation 策略为:
| 策略 | 行为 |
|---|---|
off | 默认,不查询证明 |
if-available | 没有证明可继续;发现但无效、格式错误或仓库不匹配则失败 |
required | 必须存在并通过验证 |
验证绑定 artifact SHA-256、owner/repo、GitHub Actions OIDC issuer、Fulcio 证书链 与 SCT、DSSE subject、Rekor body/SET/checkpoint/Merkle inclusion 和签名时间。GitHub v0.3 TSA bundle 则验证内置 GitHub trust root、timestamp、证书链、签名、摘要与仓库 声明。证明 API 每次最多取 30 条;bundle_url 及重定向后地址都必须为 HTTPS, Snappy 输入与解压 JSON 上限均为 8 MiB。
TLS 证书校验
TLS 证书按操作系统信任库校验:Windows 证书存储、macOS Keychain、Linux 上的常规 OpenSSL 路径。osdk 不自带根证书副本。
实际影响是证书信任跟随机器。系统级安装的企业 CA,或被系统更新移除的已吊销根证书, 都无需等待 osdk 发版即可生效——这也是 osdk 能在做 TLS 审查的代理后面正常工作的原因。 代价是 osdk 依赖宿主机被正确配置:一个没有装 ca-certificates 的精简容器镜像,在装上 根证书之前所有 HTTPS 下载都会失败。
校验无法关闭。证书不受信任、已过期、自签名或域名不匹配时,下载会在写入任何字节之前 失败,并在错误信息中指出具体原因。
任意 GitHub Release 工具
github:owner/repo[@VERSION]osdk use -g github:sharkdp/fd
osdk install github:cli/cli@2.62.0
osdk list-remote github:sharkdp/fdAsset 选择选项
所有选项通过可重复的 -o|--opt KEY=VALUE 传入:
| 选项 | 取值与作用 |
|---|---|
asset-regex=REGEX | 正则选择 asset;必须恰好命中一个 |
asset-template=TEMPLATE | 精确文件名模板;支持 {version}、{os}、{arch}、{libc} |
bin=PATH | archive 内一个 binary 的安全相对路径 |
bins=P1,P2 | archive 内多个 binary;与 bin 互斥 |
rename=NAME | 重命名单个输出 binary;要求最终只有一个 bin |
strip-components=N | 安装后逐层进入 N 个唯一的非 .osdk-* 子目录 |
os=VALUE | `linux |
arch=VALUE | `x64 |
libc=VALUE | `gnu |
catalog-url=URL_OR_PATH | 使用 schema 1 静态 catalog,绕过 Releases API |
catalog-sha256=HEX | 使用 catalog-url 时必填,验证其精确内容 |
catalog-subdir=PATH | 为锁定 artifact 记录/恢复 archive 内子目录 |
asset-regex 与 asset-template 互斥。未给规则时按 host OS、架构、archive 类型 启发式评分,并排除 checksum、signature 和 source asset;零命中或多命中都失败。 未知 archive 后缀按裸二进制处理,Windows 自动补 .exe。 对 osdk 自有 GitHub 安装,受支持的 asset、平台、catalog 摘要与布局选项属于动态安装 身份。catalog-url 可用于获取, 但不会持久化到动态身份;必填的 catalog-sha256 标识 catalog 内容。含 userinfo、查询参数或 fragment 的 HTTP(S) catalog URL 会被拒绝,避免通过这个选项持久化凭据。未知公开选项会在安装前拒绝;若同一版本的现有安装缺少新身份或身份不同,osdk 不会执行它。每个规范身份都记录在 .osdk-install.json schema 1 中,带 b3-v2: install_id 并使用独立的指纹化根,因此同版本变体可以共存。复用、activation、shim、where、uninstall 与 reshim 都由配置的精确身份驱动;旧 .osdk-tool.json 状态只会被识别,绝不会被复用或执行。
osdk install github:owner/repo@1.2.3 \
-o 'asset-regex=^tool-.*-linux-x64\.tar\.gz$' \
-o bins=dist/tool,dist/toolctl -o strip-components=1
osdk install github:owner/repo@1.2.3 \
-o 'asset-template=tool-{version}-{os}-{arch}.zip' \
-o bin=tool.exe -o rename=mytool -o os=windows -o arch=x64静态 catalog
osdk lock github:owner/repo@latest \
-o catalog-url=/approved/github-catalog.json \
-o catalog-sha256=0123456789abcdef...catalog 可为 HTTP(S)、file:// 或普通本地路径;schema 1 的每个 asset 必须包含 name、url、checksum、os、arch,libc 可选,artifact URL 必须 HTTP(S)。 HTTP catalog 在线时以摘要缓存,offline 从缓存读取;本地文件可直接离线读取。
GitHub 访问、回退与 token
token 优先级是 OSDK_GITHUB_TOKEN、GITHUB_TOKEN、GH_TOKEN。Authorization 只发给精确的 api.github.com,绝不转发给代理。Releases API 最多读 10 页、每页 100 条。匿名限流时可从公开 Atom feed 和 expanded-assets HTML 尽力发现近期公开 release;不能替代完整历史。
内置 github 与 ghproxy source 会一致覆盖 API、release asset、Raw/Gist、 checksum/signature 文件和 attestation bundle,并按排序失败转移。代理前会先规范化为 官方 URL,确保 pin、缓存和身份不随代理形式漂移。