build(l1,l2): resolve Cargo.lock updates under a 14-day publish-age cooldown - #7258
build(l1,l2): resolve Cargo.lock updates under a 14-day publish-age cooldown#7258pablodeymo wants to merge 3 commits into
Conversation
Ports Commit-Boost/commit-boost-client#492. Cargo's unstable min-publish-age (rust-lang/cargo#17009) excludes crate versions published less than N days ago from resolution, a cooldown against freshly compromised releases. The policy lives in .cargo/config.toml; stable cargo 1.93 ignores the tables silently, so locked builds and `make check-cargo-lock` are unaffected. Run from the repo root, the same file governs the twelve nested workspaces. `make update-cargo-lock` now runs `cargo tree` on a pinned nightly-2026-06-21 with -Z min-publish-age for every manifest, so each lockfile is resolved under the cooldown. A plain `cargo update` on stable bypasses it; CONTRIBUTING.md now points at the target instead. The escape hatch for an urgent bump younger than the window is CARGO_RESOLVER_INCOMPATIBLE_PUBLISH_AGE=allow on the same target; it lifts the filter for the whole resolution, so the diff must be reviewed. No lockfile changes and no CI changes: check-cargo-locks already rejects stale lockfiles, and a lockfile-level cooldown audit is not possible here because a full `cargo update` of the root workspace fails independently of this change (openvm git deps pin p3-baby-bear =0.4.1 and =0.4.3).
|
🤖 Kimi Code ReviewI'll review this PR which implements a supply-chain security measure using Cargo's unstable Overall AssessmentThis is a well-constructed supply-chain hardening PR. The core idea—using Cargo's nightly resolver to exclude freshly-published crate versions—is sound. However, there are several issues with the implementation that need addressing. Issues Found1. Nightly toolchain date is in the future —
|
| Priority | Item | Action |
|---|---|---|
| Critical | 1 | Fix future toolchain date |
| Critical | 3 | Verify cargo tree actually updates lockfiles; switch to cargo update if not |
| High | 2 | Remove silent failure on rustup install |
| High | 8 | Extend check-cargo-lock to cover all manifests |
| Medium | 6 | Verify env var name for bypass |
| Medium | 4 | Verify workspace root resolution behavior |
Correctness of Core Mechanism
The min-publish-age feature itself (.cargo/config.toml:11-15) is correctly configured per the tracking issue:
[unstable]
min-publish-age = true
[registry]
global-min-publish-age = "14 days"The "14 days" format matches Cargo's expected duration parsing. This part is correct, assuming the nightly toolchain exists and the feature is implemented in that nightly.
Summary
The PR's security intent is valid and well-documented, but the toolchain date is in the future (Item 1), which is a blocking issue. The use of cargo tree for lockfile updates (Item 3) needs verification as it may not achieve the stated goal. The silent failure mode (Item 2) and incomplete lockfile checking (Item 8) are additional concerns that should be addressed before merge.
Automated review by Kimi (Moonshot AI) · kimi-k2.6 · custom prompt
🤖 Codex Code ReviewFindings
No EVM, consensus, trie, gas-accounting, or RLP logic is touched here; the review concern is the effectiveness of the new supply-chain policy rather than runtime blockchain behavior. Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
🤖 Claude Code ReviewReview: Supply-chain cooldown for Cargo dependency resolution (PR 7258)This is a build-tooling / CI-adjacent change ( 1. The cooldown is not enforced by CI — only by convention
2. Silencing stderr on toolchain install can hide real failures
If this install fails (network issue, disk space, rustup misconfiguration, or the pinned nightly being pruned/unavailable), the failure is swallowed entirely. The next line ( 3. Pinned nightly will need periodic manual maintenance
4. Unstable config key names are worth double-checking for typos
Minor
Overall: reasonable, low-risk, well-documented change. The main gap is that the cooldown is easy to bypass unintentionally (plain Automated review by Claude (Anthropic) · sonnet · custom prompt |
There was a problem hiding this comment.
🟡 Changes recommended
The Makefile currently suppresses rustup install error output (stderr), which can make failures non-actionable and should be adjusted before merging.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR introduces a repo-wide dependency-resolution “cooldown” for Rust crates by enabling Cargo’s unstable min-publish-age feature (14 days) and ensuring lockfile refreshes are resolved with a pinned nightly toolchain, while leaving stable locked builds unaffected.
Changes:
- Enable Cargo’s unstable publish-age policy in
.cargo/config.toml(14-day minimum publish age). - Route
make update-cargo-lockthrough a pinned nightly +-Z min-publish-ageresolver invocation across all workspace manifests. - Document the intended lockfile-refresh workflow (and the emergency escape hatch) in
CONTRIBUTING.md.
File summaries
| File | Description |
|---|---|
| Makefile | Pins a nightly resolver and updates the lockfile refresh target to resolve under the min-publish-age policy across manifests. |
| CONTRIBUTING.md | Instructs contributors to use make update-cargo-lock (and documents the escape hatch) when changing Rust dependencies. |
| .cargo/config.toml | Enables unstable min-publish-age config and sets a global 14-day cooldown for crate resolution on nightly. |
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
MegaRedHand
left a comment
There was a problem hiding this comment.
This is missing the CI check
…the cooldown Review follow-up. `make cooldown-check` re-resolves each committed lockfile under the publish-age cooldown with `cargo update --dry-run` on the pinned nightly and fails if any pin is younger than the window. A cooldown-driven downgrade is annotated with the too-young version's publish date, and only those lines count: downgrades for other reasons (MSRV, tightened requirements) carry no such note and would otherwise be false positives. A resolution that fails for reasons unrelated to age only warns; the root workspace does today, since openvm's git deps pin conflicting p3-baby-bear versions and only `cargo tree` can refresh its lock, so the check gates the eleven nested workspaces and not the root. The check runs as a new `cooldown-check` job in the L1 workflow, gated like check-cargo-locks and folded into the required Integration Test aggregate. Known state: the four stateless-validator lockfiles pin crc32fast 1.5.1, log 0.4.34, rand 0.8.8, syn 3.0.4 and uuid 1.25.0, locked by the ERE v0.16.2 upgrade on 2026-08-26 and all younger than 14 days, so the job is red until they age out on 2026-09-09 or the pins are downgraded. Also from review: the Makefile comment above the resolver pin is trimmed to the toolchain split and the git-dependency caveat, and rustup's stderr is no longer swallowed (with --no-self-update so automation never triggers a self-update).
|
Added: |
…oldown The four stateless-validator lockfiles pinned crc32fast 1.5.1, log 0.4.34, rand 0.8.8, syn 3.0.4 and uuid 1.25.0, all published less than 14 days before the ERE v0.16.2 upgrade locked them, so the new cooldown-check job failed on each. This moves them to the highest version the cooldown allows (1.5.0, 0.4.33, 0.8.7, 3.0.3, 1.24.1) with a targeted `cargo update -p` on the pinned nightly; nothing else in the lockfiles changes. All five are transitive patch-level dependencies of the guest programs. Guest lockfiles pin the published ELF/VK bytes, so this changes them for the next stateless-validator release; that is the trade for a green gate today rather than waiting for the crates to age out on 2026-09-09.
|
Downgraded the five stateless-validator pins to the highest version the cooldown allows (crc32fast 1.5.0, log 0.4.33, rand 0.8.7, syn 3.0.3, uuid 1.24.1) with a targeted |
Motivation
Ports Commit-Boost/commit-boost-client#492 (also done for ethlambda in lambdaclass/ethlambda#607). Cargo's unstable
min-publish-age(rust-lang/cargo#17009) lets the resolver skip crate versions published less than N days ago, a cooldown against freshly compromised releases. This enables it at 14 days, routesmake update-cargo-lockthrough a pinned nightly so every lockfile in the repo is resolved under the policy, and adds a CI check that fails when a lockfile pins a crate younger than the window.Description
.cargo/config.toml:[unstable] min-publish-age = true,[registry] global-min-publish-age = "14 days". Stable 1.93 ignores both tables silently, so locked builds andmake check-cargo-lockare unaffected. Run from the repo root, the same file governs the 12 nested workspaces.Makefile:update-cargo-lockrunscargo +nightly-2026-06-21 -Z min-publish-age treefor each manifest via aCARGO_RESOLVEvariable; the target installs the toolchain on first use. Newcooldown-checkre-resolves each committed lockfile under the cooldown withcargo update --dry-runand fails if any pin is younger than the window. Only downgrades annotated with a publish date count: downgrades for other reasons (MSRV, tightened requirements) carry no such note and would otherwise be false positives..github/workflows/pr-main_l1.yaml: newcooldown-checkjob runningmake cooldown-check, gated likecheck-cargo-locksand folded into the required Integration Test aggregate.CONTRIBUTING.md: tells contributors to refresh lockfiles withmake update-cargo-lockrather than a plaincargo update, which resolves on stable and bypasses the cooldown.Root workspace limitation. A full
cargo updateof the root workspace fails independently of this change (openvm git deps pinp3-baby-bear =0.4.1and=0.4.3), which is why lockfiles are refreshed withcargo tree. The check therefore only warns for the root lockfile and gates the eleven nested workspaces. Git dependencies have no publish age and are not covered.Lockfile changes. The four stateless-validator lockfiles pinned crc32fast 1.5.1, log 0.4.34, rand 0.8.8, syn 3.0.4 and uuid 1.25.0, all published less than 14 days before the ERE v0.16.2 upgrade locked them, so the new job failed on each. They are moved to the highest version the cooldown allows (1.5.0, 0.4.33, 0.8.7, 3.0.3, 1.24.1) with a targeted
cargo update -pon the pinned nightly; nothing else in those lockfiles changes, and all five are transitive patch-level dependencies of the guest programs. Guest lockfiles pin the published ELF/VK bytes, so this changes them for the next stateless-validator release.How to test
Verified in a scratch crate depending on
smallvec = "1": the nightly resolver picks 1.15.2 and printsavailable: v1.16.0, published 3 days ago; stable picks 1.16.0; a--precise 1.16.0is refused.