Repository navigation
toolchain(rust): define deterministic build toolchain, explicit MSRV policy and Core/Tauri compatibility lanes #572
Description
Context
WorldScript Studio's Rust surface is growing in strategic importance because renderer-neutral Core work is a prerequisite/foundation for the Tauri→Qt path.
Current repository state is not yet a fully explicit Rust toolchain contract:
# src-tauri/Cargo.toml
edition = "2021"
rust-version = "1.77.2"but the repository currently has no root rust-toolchain.toml, while CI/release workflows install Rust through dtolnay/rust-toolchain and can therefore follow a broader/current toolchain policy than the manifest's declared minimum.
Current upstream stable Rust as of 2026-09-01 is Rust 1.98.0:
https://blog.rust-lang.org/releases/latest/
The large gap between a declared rust-version = 1.77.2 and a current floating/stable build environment is not automatically wrong: rust-version is an MSRV claim, not necessarily the version maintainers should build with. But those two concepts must be separated and tested deliberately.
This issue owns Rust toolchain determinism and support policy, not migration of additional application logic into Rust.
Related architecture owners include #445, #551–#553, #332 and the native roadmap.
Goal
Define three explicit Rust lanes:
DECLARED_MSRV
= oldest Rust version WorldScript intentionally claims to support
PINNED_BUILD_TOOLCHAIN
= deterministic Rust version/components used by normal CI/development/release builds
CURRENT_STABLE_QUALIFICATION
= forward-compatibility signal against upstream stable Rust
Then ensure Tauri and renderer-neutral Core crates use one coherent policy rather than incidental toolchain drift.
Phase 0 — inventory all Rust authorities
Before mutation, inventory:
src-tauri/Cargo.toml;- every manifest under
crates/; - both
Cargo.lockfiles; - workspace resolver/edition settings;
.github/workflows/ci.ymlRust gates;.github/workflows/tauri-build.yml;.github/workflows/tauri-intel-qualification.yml;- any release/container/native workflows using Rust;
dtolnay/rust-toolchainchannel/components arguments;- local setup/docs;
- rustfmt/clippy invocation;
- target triples installed by CI;
- Tauri CLI/build tooling that may impose its own Rust minimum;
- Candle/ML optional feature dependencies;
- workspace crates' actual MSRV requirements.
Produce a table:
| Rust surface | Edition | Declared rust-version | CI toolchain | Clippy/rustfmt | Targets | Notes |
|---|---|---|---|---|---|---|
src-tauri |
2021 | 1.77.2 | ||||
crates/* |
No Rust crate should have an accidental different support policy.
Decide the MSRV policy first
Do NOT simply change:
1.77.2 → current stable
because that converts a minimum-compatibility statement into a build-version pin and needlessly raises the compiler floor.
First determine whether 1.77.2 is still a truthful supported MSRV.
Run a real MSRV proof using the exact committed dependency graph and the required feature sets.
At minimum:
cargo +1.77.2 check --locked
cargo +1.77.2 test --locked where dependency/tool support permits
for:
- renderer-neutral Core workspace;
- Tauri crate/default features;
- security/storage-related crates;
- relevant feature combinations;
- optional
rust-computeseparately if its dependency MSRV differs.
If dependencies no longer support 1.77.2, classify the first actual blocker:
DIRECT_WORLD_SCRIPT_CODE
TAURI_RUNTIME
TAURI_PLUGIN
TRANSITIVE_DEPENDENCY
CORE_CRATE_DEPENDENCY
OPTIONAL_COMPUTE_FEATURE
Raise MSRV only to the minimum evidence-backed version required by the supported graph, not automatically to the latest stable release.
Introduce a deterministic build toolchain
After compatibility evidence, add a repository-owned Rust toolchain authority such as:
# rust-toolchain.toml
[toolchain]
channel = "<vetted exact stable release>"
profile = "minimal"
components = ["rustfmt", "clippy"]The exact selected version must be re-derived at implementation time.
Current Rust 1.98.0 is a candidate for qualification, not a pre-decided pin merely because it is newest.
Required properties:
- exact/reproducible version for developer + CI builds;
- rustfmt and clippy from the same toolchain;
- target components installed explicitly where required;
- workflows do not independently float to unrelated stable versions;
- release builds report toolchain identity in evidence/logs.
If the repository deliberately chooses a rolling stable build toolchain instead, document why that nondeterminism is worth the tradeoff and provide a canary strategy. The preferred default is a pinned stable version plus forward qualification.
Current-stable qualification lane
Separately run the Rust workspace against current upstream stable on an evidence-appropriate cadence.
Semantics:
PINNED_BUILD_TOOLCHAIN
= required merge/release authority
CURRENT_STABLE_QUALIFICATION
= advisory/scheduled forward-compatibility oracle
If upstream stable breaks WorldScript:
- required builds remain deterministic on the pin;
- open/classify the incompatibility;
- do not silently update the pin in every workflow;
- upgrade intentionally once fixed.
This reduces surprise when the pinned compiler is eventually advanced.
Pin-advance policy
Define when the pinned build toolchain should move forward.
Suggested gate for each pin advance:
cargo check --locked
cargo test --locked
cargo fmt --check
cargo clippy with repository warning policy
Tauri Rust gate
Core Rust gate
packaged native build smoke where relevant
security/OSV Cargo lock scan
Also record:
old pin
new pin
MSRV unchanged/raised
reason
new warnings/lints
binary/build-size change where material
Do not combine a compiler pin jump with unrelated Core authority changes unless one genuinely depends on the other.
Clippy policy
Compiler upgrades often surface new Clippy lints.
Treat them as:
NEW_REAL_DEFECT
STYLE/IDIOM IMPROVEMENT
FALSE_POSITIVE / INTENTIONAL PATTERN
TOOLCHAIN_TRANSITION_ONLY
Do not globally add broad allow(...) attributes merely to make a new compiler pass.
Any new suppression must have a narrow rationale and respect existing suppression-debt policy.
Cargo.lock and resolver behavior
A Rust toolchain change must not opportunistically update the entire Cargo dependency graph unless required.
Use --locked for compatibility and CI evidence.
If the new compiler requires dependency movement:
- prove why;
- split dependency modernization if substantial;
- run OSV/SCA against both
src-tauri/Cargo.lockandcrates/Cargo.lock; - preserve causal reviewability.
Coordinate dependency-provenance/security work with #529/#448 rather than duplicating it.
Tauri/Core distinction
The renderer-neutral Core workspace and transitional Tauri shell should consume the same toolchain policy, but their supported dependency graphs may impose different MSRVs.
If so, explicitly choose one of:
UNIFIED_MSRV = max(required Core, required Tauri)
or
SEPARATE_PUBLISHED_MSRV
= only if there is a real distribution/reuse reason
Do not let this become accidental divergence.
Because Qt will later consume Rust Core, prefer a Core toolchain contract that is not defined by incidental WebKit/Tauri implementation details.
Edition policy
Do not migrate Rust edition simply because a newer edition exists.
Audit whether edition 2021 remains appropriate or whether an edition migration has concrete value/requirements. If a future edition migration produces broad source churn, track it separately from toolchain pinning/MSRV establishment.
No edition bump is required to close this issue unless evidence says otherwise.
Release/build evidence
For packaged native builds record at minimum:
rustc --version --verbose
cargo --version
target triple
Tauri crate/CLI versions
Cargo.lock digest or commit SHA
This helps correlate future platform regressions with actual toolchain movement.
Coordinate packaging/platform evidence with #332 and #507.
CI efficiency relationship
#550 owns cost/latency.
This issue may introduce an MSRV/current-stable qualification lane, but #550 may later choose a scheduled cadence or path-awareness once support evidence exists.
Do not drop MSRV/current-stable evidence solely to save runner minutes.
Rollback
A build-toolchain pin advance must be reversible by reverting the toolchain file/config while leaving user data/application formats untouched.
If a newer compiler exposes a real undefined/incorrect application behavior, fix the defect rather than indefinitely pinning old Rust without an owner.
Acceptance criteria
- Every Rust manifest/workflow/toolchain authority is inventoried.
-
DECLARED_MSRV,PINNED_BUILD_TOOLCHAIN, andCURRENT_STABLE_QUALIFICATIONare explicitly distinguished. - The current
rust-version = 1.77.2claim is actually tested or deliberately raised to the minimum evidence-backed supported version. - No MSRV is raised merely to equal current stable.
- A repository-owned deterministic build toolchain is established, preferably via
rust-toolchain.tomlor an equivalently singular authority. - rustfmt/clippy use the same pinned toolchain.
- Normal CI/release workflows do not independently float Rust versions.
- Current upstream stable receives a forward-compatibility qualification lane/cadence.
- Core and Tauri MSRV/toolchain relationships are explicit.
- Pin advancement has a documented check/test/clippy/packaging/security gate.
- Cargo dependency graph changes remain separately reviewable where material.
- Packaged native evidence reports exact Rust toolchain identity.
- No Qt implementation or Core feature migration is bundled merely to establish toolchain policy.
Non-goals
- raising MSRV to Rust 1.98 just because it is current;
- moving more application logic into Rust;
- starting Qt implementation;
- performing a broad Rust edition/source-style migration;
- updating all Cargo dependencies without cause;
- weakening Clippy/security checks to accept a newer compiler;
- defining Core architecture inside a toolchain issue.
Activity
qnbs commentedon Sep 6, 2026
Fresh evidence 2026-09-06: src-tauri/Cargo.toml still declares rust-version = 1.77.2, while no root rust-toolchain pin was found and CI uses current stable toolchain action semantics. Keep #572 P2 and preserve the distinction between declared MSRV, pinned build toolchain, and current-stable qualification.
qnbs commentedon Sep 28, 2026
2026-09-28 deep-audit confirmation
The audit reconfirmed the architectural reason this issue exists: CI currently follows a floating stable Rust channel while multiple Cargo manifests claim rust-version = 1.77.2, and the claimed MSRV is not part of the normal tested matrix.
Post-v1.29.0 execution should separate:
Do not collapse rust-version into the build pin. The audit found no reason to reinterpret the iterative JSON-header scanner/guarded unwraps as a defect.
qnbs commentedon Oct 17, 2026
2026-10-17 — ZIP security advisories expose unavoidable MSRV decision boundary
The lockfile
zip@4.6.1(viatauri-plugin-updater@2.12.0) andzip@8.6.0(viacandle-core@0.11.0) now fail OSV for RUSTSEC-2026-0367/0368/0369 in #1077. RustSec listszip>=9.0.0as fixed; upstreamzipdocs state MSRV 1.88, while this repository's declared MSRV is 1.77.2. A direct bump cannot be assumed compatible and may also break Tauri updater version parity; current CI compiler version is not equivalent to a minimum-supported-compiler proof.For security triage (GH #911/QNB-162) explicitly separate: (1) declared MSRV guarantee and actual Rust-1.77.2 build evidence; (2) pinned ordinary toolchain; (3) current-stable qualification; (4) upstream compatible patched paths for both ZIP versions; (5) exact Extract API/privilege/input reachability and release exposure. Either obtain a proven MSRV-compatible remediation or a fresh, owner-approved security/MSRV decision. No automatic floor bump, audit ignore or GH branch protection workaround. Track dependency successor work via GH #927 / QNB-173 plan. No code changes admitted by this planning comment.
Current target graph and MSRV follow-up — 2026-10-17T15:39:13Z
Read-only cargo metadata against the exact current Tauri lockfile resolved Linux 423 packages, Windows 346, macOS ARM 352, and macOS Intel 353. Package-declared rust-version values above 1.77.2 occurred in those target graphs (63/55/52/53 respectively); highest observed is 1.89.0 (notify-rust 4.18.0). This is a metadata/support-contract inconsistency, not by itself proof that compilation fails.
Toolchain facts remain separate: declared MSRV is 1.77.2; desktop Rust is not pinned and CI uses floating stable; local stable 1.95.0 and Rust 1.77.2 are installed, but this is not four-platform exact-main qualification. zip 9 declares Rust 1.88. Updater 2.13.1/2.14 declare Rust 1.90 and still request zip ^4; candle-core 0.11 requests zip ^8.6, so zip 9 fits neither existing semver path. No complete compatible upstream remediation for both locked ZIP paths was identified.
The current-main OSV workflow 38998852956 is also red, not only #1077. No source/MSRV policy change was admitted. Require explicit owner decision or a resolver-proven compatible fix; do not silently raise the floor or infer a compile failure from metadata alone.
qnbs commentedon Oct 17, 2026
Maintainer maintenance-only security decision — 2026-10-17
Owner selects preserve declared Rust MSRV 1.77.2, delegate the tightly bounded ZIP security/dependency remediation and resulting qualified Dependabot train to local Codex CLI, while Claude remains PAUSED_BY_OWNER and all ordinary R-15/Gate4–7 feature source work stays forbidden. This is not an admission for unconditional compiler-floor advancement, broad refactoring, release, tag, or weakened OSV check. New Vercel SAFE-only operator identity is separately governed at GH #627.
Observed mismatch: all four desktop target graphs contain dependency manifest Rust requirements as high as 1.89.0; metadata alone is insufficient to claim a real compile failure. Investigate actual Rust 1.77.2 graph qualification, distinct
DECLARED_MSRV,PINNED_BUILD_TOOLCHAIN,CURRENT_STABLE_QUALIFICATION, and upstream-compatible remediation for BOTHzip@4.6.1(Tauri updater) andzip@8.6.0(Candle) affected by RUSTSEC-2026-0367/0368/0369.zip >= 9documents at least Rust 1.88 and is outside the current upstream semver ranges; no forced direct bump. Record full target/feature and actual extract-callsite proof; deliver smallest signed security PR only if resolver, OSV, tests and independent reviews all pass. Otherwise exact owner decision HOLD and no train merge under current red Security Audit. This comment does not claim a fix was found or a new train declared.qnbs commentedon Oct 17, 2026
Fresh upstream registry/MSRV check — 2026-10-17T16:14:19Z
Crates.io currently lists zip 9.0.4 as latest stable (rust-version 1.88); it lists no 4.6.2 or 8.6.1. Current updater requires zip ^4 and candle-core 0.11 requires zip ^8.6, so the patched zip9 line cannot resolve within either existing range.
Latest stable tauri-plugin-updater 2.14.0 declares Rust 1.90, lies outside the repository pin ~2.12.0 and still depends on target-Windows zip ^4. Candle 0.11.0 remains the only 0.11 release. Existing desktop graph metadata still includes dependency declarations up to Rust 1.89.0; that is a contract gap, not a compiler-failure proof.
No upstream release satisfying both the Rust 1.77.2 requirement and both vulnerable graph paths was found. Do not update MSRV or admit a dependency change without a separately reviewed, maintained backport/fork plan and resolver/compiler/platform proof. Current-main scheduled OSV remains failed.
qnbs commentedon Oct 17, 2026
2026-10-17 — exact Rust 1.77.2 ZIP source probes
The declared MSRV remains 1.77.2. Live
mainremainsa710b39bb2aeecee9a1e580cc367c930c45b58c1.tauri-plugin-updater 2.12.0 -> zip 4.6.1, zip feature set empty. Exact 1.77.2 compilation of the official source is blocked first by its declaredrust-version = 1.82.0; a private source copy with only that manifest field lowered then exposed three uses ofsize_ofoutside the prelude. Addingstd::mem::size_ofin that disposable copy allowedcargo +1.77.2 check --no-default-featuresto succeed. This demonstrates a small source compatibility adaptation, not a published-crate or updater-build qualification.rust-computegraph: lockedzip 8.6.0 -> candle-core 0.11.0 -> indexmap 2.14.0 -> hashbrown 0.17.1. A Cargo 1.77.2 private probe fails becausehashbrown 0.17.1requires Cargo Edition-2024 support. No manifest floor or repository lockfile was changed.The private backport prototype remains unqualified for shipment: no OSV-recognized dependency identity, complete platform/feature builds, or race-safety review. Status is
MSRV_PARTIAL: a source adaptation for zip4 is technically feasible; the current zip8 locked graph fails the 1.77.2 toolchain gate. The project-wide declared-floor mismatch remains open and this is not an MSRV PASS.qnbs commentedon Oct 17, 2026
2026-10-17 — ZIP feature graph across supported desktop targets
Fresh
cargo tree --lockedreads against exact maina710b39bb2aeecee9a1e580cc367c930c45b58c1show that whenrust-computeis enabled, all four graphs resolvezip 8.6.0 -> candle-core 0.11.0: Linux x86_64, Windows MSVC x86_64, macOS Intel, and macOS ARM64. The Windows updater path resolvestauri-plugin-updater 2.12.0 -> zip 4.6.1with no zip features enabled.This establishes target/feature reachability from the lockfile, not cross-compilation or hosted binary evidence. It means the current locked Edition-2024
hashbrown 0.17.1path is relevant whereverrust-computeis admitted, not just Linux. The declared MSRV remains 1.77.2; no target graph is qualified as passing that compiler floor for the current zip8 dependency graph. Full details and exact commands are in the GH #572 / #911-linked private prototype receipts.qnbs commentedon Oct 17, 2026
2026-10-17 — new zbus-family notices and 1.77.2 boundary
GH #911 exact-head Security Audit run
39061065120addsRUSTSEC-2026-0370/0371/0372forzvariant,zbus_names, andzvariant_derive. OSV classifies all three as informationalunmaintainednotices (no CVSS, affected functions, or fixed version), not exploit reports; the enforced scan still fails and no ignore was added. Details and the private ZIP prototype result: #911 (comment)Locked reverse paths are
zbus@5.16.0 -> zvariant@5.12.0 / zvariant_derive@5.12.0 / zbus_names@4.3.2through Tauri notification and single-instance plugins, andzbus@4.4.0 -> zvariant@4.2.0 / zvariant_derive@4.2.0 / zbus_names@3.0.0throughkeyring@3.6.3 -> secret-service@4.0.0in the optionalplatform-keystorefeature. The official advisory suggests migration intozbus 6; the current crates.io index declareszbus@6.0.0Rust 1.89. Current stable Tauri plugin lines still require zbus 5 and declare Rust 1.90;keyring@4.2.0declares Rust 1.88. This does not establish a migration compatible with the declared Rust 1.77.2 floor.A private ZIP4 candidate with handle-relative stream chmod now compiles under Rust 1.77.2 only with experiment-only
--ignore-rust-version; its package manifest declares Rust 1.82, so this is source-level evidence, not a supported package/MSRV pass. ZIP8/Candle remains unqualified at the Edition-2024 dependency path.DECLARED_MSRV=1.77.2remains unchanged;MSRV_STATUS=PARTIAL, no production lockfile or dependency changed.qnbs commentedon Oct 17, 2026
2026-10-17 — keyring successor does not clear the zbus notices
Additional current crates.io sparse-index evidence:
keyring@4.2.0splits its Linux backend, but the latestzbus-secret-service-keyring-store@1.0.1still depends onzbus ^5and declares Rust 1.88;dbus-secret-service-keyring-store@1.0.1also declares Rust 1.88 and usesdbus-secret-service ^4.1. So a keyring 4.x bump exceeds the declared 1.77.2 floor and does not remove the zbus 5 / zvariant advisory path. Current Tauri notification and single-instance releases likewise remain on zbus 5. No compatible upstream migration was established; no package or scanner policy changed.qnbs commentedon Oct 17, 2026
ZIP8 Rust 1.77.2 source probe — 2026-10-17T19:43Z
A disposable resolver experiment pinned
indexmap 2.11.0/hashbrown 0.15.5, then tested a private ZIP 8.6.0 source copy after adapting only that copy's manifest from Edition 2024/Rust 1.88 to Edition 2021/Rust 1.77.2. Cargo 1.77.2 initially reported 22 language/API errors; a bounded private source compatibility backport resolved those, and the focused parent-replacement test passed 1/1 under rustc 1.77.2. Exact private diff SHA-256:6d0d694494c347f9b5fd7439bce299770d27ceaaf0244d8c9da8df4b2a0b37e0.This is not a published-package or project MSRV pass: upstream ZIP 8.6.0 still declares Edition 2024 / Rust 1.88, and the adapted source retains its OSV-flagged version identity. It only demonstrates that a private backport requires both resolver and source compatibility work. No repository Cargo lockfile, package manifest, or PR changed. Details: #911 (comment).
qnbs commentedon Oct 18, 2026
2026-10-18 UTC MSRV follow-up:
notify-rust 4.17.0, passescargo +1.77.2 check --lib. This demonstrates one subset can compile; it does not qualify either complete product graph or clear the current advisories.--ignore-rust-versionis not an MSRV pass: official ZIP4.6.1 declares Rust 1.82. ZIP8's isolated adapted-source pass does not establish the full Candlerust-computegraph; that graph stops atgemm 0.19 -> pulp 0.22.3on Rust 1.77.2.No manifest floor was changed, and no full-platform MSRV pass is claimed. Current OSV remains failed; the isolated zbus pins retain advisory-affected package identities.
qnbs commentedon Oct 18, 2026
2026-10-18 UTC exact Pulp/Main-lock MSRV proof:
src-tauri/Cargo.lockpinspulp 0.22.2(official archive checksum2e205bb30d5b916c55e584c22201771bcf2bad9aabd5d4127f38387140c38632);gemm-common 0.19.0declarespulp = "0.22.0"with default features disabled.default-features=false, stdshape passescargo +stable check --locked --offline, but failscargo +1.77.2 check --locked --offlinewith E0658 forinline-constand raw-address syntax (2,654 compiler errors). The full stderr and manifest/lock hashes are in the private lab receipt.pulp 0.22.1fails the same way. Yanked0.22.0also contains those constructs, so it is not a floor-compatible resolver escape.Private current receipt:
SECURITY_FOLLOWUP_2026-10-18T0059Z.md(local operator artifact). Earlier exploratory notes naming 0.22.3 should be read as a separate Pulp-version experiment, not the current Main lock.qnbs commentedon Oct 18, 2026
New Rust 1.77.2 / Candle integration evidence — 2026-10-18
A new isolated source probe now resolves the exact locked
pulp 0.22.2package (archive checksum2e205bb30d5b916c55e584c22201771bcf2bad9aabd5d4127f38387140c38632) to a private, non-shipping adaptation.cargo +1.77.2 check --offline --lockedand the same check on stable both pass. The prototype patch SHA-256 is1d8f454c989472f296db258c1cc70a4458d96eaa0a02a51597990ba09e1ba509. It changes publiccast,cast_lossy, andiota_*functions fromconst fnto runtime functions and therefore has API/performance compatibility costs; this is compiler evidence only, not a production candidate or MSRV qualification.The full Candle 0.11.0
rust-computeprobe, using the private Pulp and ZIP8 paths, stops at the exactsafetensors = 0.8.0dependency, which requires Rust 1.80. The 1.77.2 run fails before compiling the Candle graph. No product Cargo lock or manifest changed. A metadata check of Candle 0.10.0 foundsafetensors 0.7.0but stillzip 7.2.0; it does not remove the ZIP vulnerability family (OSV currently reports fixed version 9.0.0), so no downgrade was applied.The declared Rust MSRV remains 1.77.2. Current status:
PULP_SOURCE_CHECK=PASSfor the private adapted crate;CANDLE_RESOLVES/COMPILES=NOT_PASSbecause the pinnedsafetensors 0.8.0MSRV gate stops the resolver before compilation; no integrated fix and no merge admission.