Supply chain checks and vendor drift verification
供应链检查与 vendor 漂移验证
The vendor manifest ([the vendoring decision](../../implemented/process/2026-06-11-vendor-cordis-as-source.md)) is enforced at commit time in the *forward* direction (vendored change ⇒ manifest update) but nothing verifies the manifest's *claims*: that vendor/ actually equals upstream-at-SHA plus exactly the logged modifications. And the handful of true npm dependencies have no advisory monitoring or update cadence.
English
Problem
The vendor manifest (the vendoring decision) is enforced at commit time in the forward direction (vendored change ⇒ manifest update) but nothing verifies the manifest's claims: that vendor/ actually equals upstream-at-SHA plus exactly the logged modifications. And the handful of true npm dependencies have no advisory monitoring or update cadence.
Proposal
- Vendor drift check (nightly CI): clone the upstream repos at the manifest SHAs (shallow), copy the corresponding package sources, and diff against
vendor/*/src. The job fails unless the diff matches the logged local modifications (kept as a checked-in patch file per modification — the log entries become verifiable artifacts rather than prose). - Dependency advisories: osv-scanner (or
pnpm audit) job on the lockfile, scheduled + on lockfile-touching PRs. - License inventory: a script asserting every vendored package carries its LICENSE and that package.json
licensefields match the inventory in vendor/README.md (we mix vendored MIT with our BSD-3) — CI step. - Renovate (or a scheduled agent task) proposing npm dependency updates in small PRs that ride the full gate suite; vendored packages are excluded (their updates follow the manifest sync procedure, ideally as a semi-automated agent workflow: fetch upstream, re-apply patches, run gates, open PR with the manifest table updated).
Plan
3 is trivial — do first. 1 requires network access from CI to the upstream repos (private — needs a token) and converting the two existing logged modifications into patch files. 2 and 4 are config.
Alternatives considered
pnpm auditinstead of osv-scanner — either satisfies the advisory-scanning shape; the choice is deferred to implementation.- A scheduled agent task instead of Renovate — equivalent for proposing small update PRs that ride the full gate suite; vendored packages stay excluded either way (their updates follow the manifest sync procedure).
Acceptance criteria
- The license inventory script runs in CI and fails on a missing LICENSE or a
licensefield that contradicts the inventory invendor/README.md. - The nightly drift job reconstructs
vendor/from the manifest SHAs plus checked-in patch files and fails on any unexplained diff. - Advisory scanning runs on the lockfile on schedule and on lockfile-touching PRs.
Risks
Upstream repos are private mirrors; CI credentials and availability are the main friction for the drift check. If blocked, run it as a local scheduled agent task instead of CI.
中文
问题
vendor manifest(元数据清单)(见引入 vendor 的决策)在提交时仅在正向强制执行(vendor 变更 ⇒ manifest 更新),但没有任何机制验证 manifest 的声明:即 vendor/ 确实等于上游指定 SHA 的内容加上所记录的修改。此外,少量真正的 NPM 依赖也没有安全公告监控或更新节奏。
提案
- Vendor 漂移检查(夜间 CI):以 manifest 中记录的 SHA 浅克隆上游仓库,复制对应的包源码,与
vendor/*/src做 diff。除非 diff 与已记录的本地修改一致(每项修改以签入的 patch 文件保存——日志条目从行文描述变为可验证的产物),否则任务失败。 - 依赖安全公告:对 lockfile 运行 osv-scanner(或
pnpm audit),按计划定期执行,并在涉及 lockfile 变更的 PR(Pull Request)上触发。 - 许可证清单:一个脚本断言每个 vendor 包都携带其 LICENSE 文件,且 package.json 的
license字段与 vendor/README.md 中的清单一致(我们混合了 vendor 的 MIT 与自有的 BSD-3)——作为 CI 步骤运行。 - Renovate(或定时 agent(智能体)任务)以小 PR 的形式提议 NPM 依赖更新,这些 PR 走完整门禁套件;vendor 包不在其列(它们的更新遵循 manifest 同步流程,理想情况下是半自动化的 agent 工作流:拉取上游、重新应用 patch、运行门禁、以更新后的 manifest 表格开 PR)。
计划
第 3 项最简单,先做。第 1 项需要 CI 能通过网络访问上游仓库(私有仓库,需要 token),并将现有两项已记录的修改转换为 patch 文件。第 2 项和第 4 项是配置工作。
曾考虑的替代方案
- 用
pnpm audit替代 osv-scanner:两者都满足安全公告扫描的需求;具体选择推迟到实现阶段决定。 - 用定时 agent 任务替代 Renovate:在提议小型更新 PR 并走完整门禁套件方面效果等价;vendor 包无论哪种方案都不在其列(它们的更新遵循 manifest 同步流程)。
验收标准
- 许可证清单脚本在 CI 中运行,缺少 LICENSE 或
license字段与vendor/README.md中的清单矛盾时失败。 - 夜间漂移任务从 manifest SHA 加签入的 patch 文件重建
vendor/,出现任何无法解释的 diff 时失败。 - 安全公告扫描按计划定期运行,并在涉及 lockfile 变更的 PR 上运行。
风险
上游仓库是私有镜像;CI 凭证与可用性是漂移检查的主要阻力。如果受阻,可改为本地定时 agent 任务而非 CI。