Skip to content

chore: release v3.14.1 - #4172

Closed
kevindeforth wants to merge 8 commits into
release/v3.14from
release-prep/v.3.14.1
Closed

chore: release v3.14.1#4172
kevindeforth wants to merge 8 commits into
release/v3.14from
release-prep/v.3.14.1

Conversation

@kevindeforth

@kevindeforth kevindeforth commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

resolves #4174

actual logic is in commit 11d4235
release logic is in commit 37bcff1

gilcu3 and others added 6 commits August 18, 2026 16:05
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
(cherry picked from commit fb32ae3)
@kevindeforth
kevindeforth changed the base branch from main to release/v3.14 August 18, 2026 13:49
@kevindeforth kevindeforth changed the title Release prep/v.3.14.1 release v.3.14.1 Aug 18, 2026
@kevindeforth kevindeforth changed the title release v.3.14.1 chore: release v.3.14.1 Aug 18, 2026
@kevindeforth
kevindeforth force-pushed the release-prep/v.3.14.1 branch 3 times, most recently from 76a75f5 to 11d4235 Compare August 18, 2026 15:53
@kevindeforth
kevindeforth marked this pull request as ready for review August 18, 2026 16:11
@claude

claude Bot commented Aug 18, 2026

Copy link
Copy Markdown

Pull request overview

Release PR cutting v3.14.1 off release/v3.14. It rolls up six already-merged chores (contract-migration rebase onto 3.14.0, a deny.toml advisory ignore, a dependabot bump, and the CI move to Ubuntu 26.04 runners / pinned-digest image builds) plus one new contract behavior change: DEFAULT_EXPIRATION_DURATION_SECONDS goes from 7 to 21 days, DEFAULT_LAUNCHER_HASH_UNUSED_TTL_SECONDS from 14 to 21 days, and the 3.14.0 -> 3.14.1 migration additively extends every stored Dstack attestation expiry so operators can vote in a new contract instead of running an emergency migration (#4174).

Changes:

  • Version bump 3.14.0 -> 3.14.1 (Cargo.toml, ABI snapshot, CHANGELOG.md).
  • Migration rebased: v3_13_0_state.rs deleted, v3_14_0_state.rs added; contract-history current_mainnet/current_testnet now point at the newly archived signer-3_14_0.wasm; AllowedLauncherImages::from_entries dropped as unused.
  • Attestation validity window tripled (7 -> 21 days); launcher unused-TTL raised (14 -> 21 days); migration calls the new TeeState::extend_dstack_attestation_expiries and raises launcher_hash_unused_ttl_seconds via .max(DEFAULT) so Config::validate still holds.
  • CI: all jobs moved to warp-ubuntu-2604-*; repro-env installed from apt instead of a checksum-pinned release; buildkit and skopeo pinned by digest in deployment/build-images.sh; scripts/build-and-verify-rust-launcher-docker-image.sh removed in favor of build-images.sh --rust-launcher.
  • deny.toml: ignore RUSTSEC-2026-0247/0248/0251 (im, bitmaps, sized-chunks) behind TODO(#4117).

Reviewed changes

Per-file summary
File Description
Cargo.toml, Cargo.lock Workspace version -> 3.14.1; dependabot group bump.
CHANGELOG.md New [3.14.1] section, all entries under "Miscellaneous Tasks".
crates/contract/src/lib.rs v3_13_0_state -> v3_14_0_state in migrate(); new unit test migrate__should_extend_dstack_expiries_and_raise_the_launcher_ttl + insert_attestation helper.
crates/contract/src/v3_14_0_state.rs New shadow state; From impl extends Dstack expiries and raises the launcher TTL.
crates/contract/src/v3_13_0_state.rs Deleted (previous migration retired).
crates/contract/src/tee/tee_state.rs New extend_dstack_attestation_expiries(Duration).
crates/contract/src/tee/proposal.rs AllowedLauncherImages::from_entries removed (was migration-only).
crates/contract/src/config.rs DEFAULT_LAUNCHER_HASH_UNUSED_TTL_SECONDS 14 -> 21 days.
crates/mpc-attestation/src/attestation.rs DEFAULT_EXPIRATION_DURATION_SECONDS 7 -> 21 days.
crates/contract-history/src/lib.rs, archive/signer-3_14_0.wasm 3.14.0 archived; current_mainnet/current_testnet repointed.
crates/contract/tests/sandbox/*, crates/test-utils/src/contract_types.rs Test TTL constants 14 -> 21 days; stale 3.13.0-specific comments dropped.
crates/contract/tests/snapshots/abi__abi_has_not_changed.snap ABI version string.
.github/workflows/* (15 files) Runners -> warp-ubuntu-2604-*; repro-env via apt; redundant skopeo installs removed.
deployment/build-images.sh buildkit + skopeo pinned by digest; skopeo run via podman; requirement list reshuffled.
scripts/build-and-verify-rust-launcher-docker-image.sh Deleted (was a thin, assertion-free wrapper).
docs/reproducible-builds.md, docs/running-an-mpc-node-in-tdx-external-guide.md podman/skopeo prerequisite updates.
deny.toml Three unmaintained-crate advisories ignored with a TODO(#4117).
third-party-licenses/licenses.html Regenerated for the release.

Findings

Blocking (must fix before merge):

  • crates/contract/src/v3_14_0_state.rs:60 — the migration extends expiries additively (expiry += 21d), which makes the post-migration validity depend on exactly the variable the fix is meant to neutralize: when each node last attested.

    • An entry that lapsed 20 days before the upgrade gets 1 day of validity; one that lapsed yesterday gets 20. Same intent, wildly different outcomes.
    • A live entry stamped just before the upgrade has expiry = T + 7d, so after +21d it is trusted until T + 28d, while launcher_hash_unused_ttl_seconds is exactly 21d. For a node that stops re-attesting at migration time, its launcher entry is evicted at stamp + 21d while its attestation is still unexpired — breaking the invariant documented at docs/design/auto-remove-launcher-hashes-design.md:73-81 ("a hash backing a valid participant attestation is never expired") that Config::validate exists to guarantee.

    Stamping an absolute expiry off the migration block fixes both and keeps validity bounded by the configured TTL:

    pub(crate) fn extend_dstack_attestation_expiries(&mut self, window: Duration) {
        let target = Self::current_time_seconds().saturating_add(window.as_secs());
        // ...
        dstack.expiry_timestamp_seconds = dstack.expiry_timestamp_seconds.max(target);
    }
  • crates/mpc-attestation/src/attestation.rs:28 + crates/contract/src/config.rs:45 — tripling the attestation window is a security-relevant change with no rationale recorded anywhere (no doc comment, no design note; the CHANGELOG.md:24 entry is a bare chore). It directly contradicts an in-repo design doc: docs/design/attestation-verifier-contract.md:214 names DEFAULT_EXPIRATION_DURATION_SECONDS as the lever bounding how long a wrongly-accepted or post-rotation entry survives, and proposes lowering it "to a shorter value — 1 day is a reasonable starting point". Concretely, MAX_COLLATERAL_AGE is 31 days (crates/tee-authority/src/tee_authority.rs:245), so an entry may now be trusted on Intel collateral up to ~52 days old (was ~38), well past Intel's 30-day nextUpdate. Per CLAUDE.md §Documentation alignment a superseded design must be updated or banner-marked, not left silently stale — please state the tradeoff in the constant's doc comment and reconcile that design doc.

  • Documentation drift from the two constants (review-blocking per CLAUDE.md):

    • docs/running-an-mpc-node-in-tdx-external-guide.md:1670 and :1829 — operator-facing, still "launcher_hash_unused_ttl_seconds, default 14 days".
    • docs/design/auto-remove-launcher-hashes-design.md:37,40,75,101,103,115-118,149-150 — "default 14 days", "currently 7 days", "now + 14d". Line 80-81's "the 14-day default is >= DEFAULT_EXPIRATION_DURATION_SECONDS … leaving ample margin" is now false: 21 vs 21 is zero margin, which is what makes the first finding reachable.
    • docs/design/operator-prepaid-attestation-storage.md:30 — "Reclamation waits for the entry to expire (7 days)"; operators now wait 3x longer for a grant to come back, which changes the "prepay for a spare" guidance in the same sentence.
    • docs/threat-model-diagram.md:286 — "verify_tee kicks nodes after 7 days" (T11).
  • CHANGELOG.md:24 / release-branch scope — extend_dstack_attestation_expiries returns no hits in GitHub code search over the default branch, while refresh_launcher_usage in the same file does; it is also the only changelog entry without a PR number. If this is a release-branch-only commit, the next release cut from main silently reverts the 21-day window and the migration. Note main has since moved migrate() into crates/contract/src/api/lifecycle.rs, so the forward-port is not a clean cherry-pick — please confirm the main PR exists/lands.

Non-blocking (nits, follow-ups, suggestions):

  • crates/contract/src/tee/tee_state.rs:500 — one-shot migration helper living in the production TeeState module with no doc comment and nothing tying its lifetime to v3_14_0_state. Its 3.13.0 predecessor (stamp_expiry_on_legacy_mocks) lived in the migration module carrying TODO(#3978): transitional one-time upgrade step — removed together with this module; without an equivalent marker this becomes orphaned dead code when v3_14_0_state.rs is retired next release.
  • crates/contract/src/lib.rs:8561-8564 — the test asserts mocks are deliberately left untouched, but MockAttestation is accepted by the production contract (TeeState::verify_and_store_mock) and its stored entries expire on the same window. Any node whose stored entry is a mock still lapses on the old schedule, so the release would not achieve its goal for those. Worth a one-line rationale in v3_14_0_state.rs for why Dstack-only is the right scope.
  • .github/workflows/ci.yml:52-56 (and the same swap in docker_build_node.yml:38-42) — repro-env moved from a checksum-pinned v0.4.3 download to apt-get install -y repro-env, i.e. whatever Ubuntu 26.04 ships at build time. repro-env is what makes the node/launcher manifest digests reproducible, and operators are told to install it from upstream (docs/reproducible-builds.md:19), so an unpinned CI version can make CI and operator-side reproductions disagree. This also sits oddly next to the same change's care in pinning buildkit and skopeo by digest (deployment/build-images.sh:104,143).
  • CHANGELOG.md:24 — the attestation-window change is filed under "Miscellaneous Tasks" because the commit is typed chore(contract):. Node operators read this file to decide whether to vote in a release; a tripled attestation validity window is a behavior change, not a chore.

⚠️ Issues found

pbeza
pbeza previously approved these changes Aug 18, 2026
Comment thread crates/contract/src/v3_14_0_state.rs
Comment thread crates/contract/src/lib.rs Outdated
Comment thread crates/contract/src/lib.rs

@gilcu3 gilcu3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Left a couple of minor comments

Comment thread CHANGELOG.md
Comment on lines +12 to +24
- (@gilcu3): Update contract migrations after 3.14 release (#4081)

- (@pbeza): *(deny)* Ignore the unmaintained advisories for `im` and its dependencies (#4116)

- (@dependabot[bot]): Bump the rust-minor-and-patch group with 4 updates (#4113)

- (@barakeinav1): Install catatonit for repro-env podman builds (#4125)

- (@barakeinav1): Install catatonit in the image-publishing workflows (#4128)

- (@gilcu3): Move runner images to ubuntu 26.04 (#4134)

- (@kevindeforth): *(contract)* Extend attestation expiry time during migration

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is where some links are missing, for example below in the file:

@kevindeforth kevindeforth Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh boy, I need to check why those links don't show when I generate the changelog...

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably easier to generate them manually as in any case the commits would be squashed being this a single PR adding all of them

Comment thread deny.toml
Comment on lines +36 to +39
# TODO(#4117): remove once nearcore moves `near-network` off `im`, whose maintained fork is `imbl`.
"RUSTSEC-2026-0247", # bitmaps is unmaintained
"RUSTSEC-2026-0248", # im is unmaintained
"RUSTSEC-2026-0251", # sized-chunks is unmaintained

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: would be better to avoid the commit that included this and the dep bumps in this release. We already have all the ci commits that unfortunately cannot be completely avoided, although they could be squashed so that a single line in the changelog explains them

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, I was worried about ci failing, hence I added most of these extra stuff.
Why would it be better to exclude them?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only so that there are the least amount of changes in this patch release, CI should not fail without any of these, as they are about advisories

@kevindeforth kevindeforth changed the title chore: release v.3.14.1 chore: release v3.14.1 Aug 19, 2026
@kevindeforth

kevindeforth commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

closing this, it has been replaced with a series of PRs:

@claude claude Bot mentioned this pull request Aug 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants