Phase log 70: Roadmap R03, dependency modernisation
Goal
Complete roadmap R03 (project phase 47): replace the exact-pin-everything policy with caret requirements plus the root lockfile, modernise the listed Rust and npm families together, keep binary and cryptographic compatibility guarded by fixtures, and raise the cost of newly written encrypted backups without losing the ability to read existing ones.
Current Progress
R03 is complete locally from base 3710d7170f8e… at version 0.42.7; nothing was staged, committed, pushed, tagged, published, or deployed.
- Added workspace Rust MSRV
1.90and inherited it in all four member manifests.1.90is Tauri 2.12's published MSRV, rather than the roadmap's minimum suggestion of 1.89. - Direct constraints are caret requirements except the two data-format-sensitive pins:
rusqlite = 0.40.2andargon2 = 0.6.0. The rootCargo.lockrecords the resolved graph. - Removed the obsolete tracked
src-tauri/Cargo.lock.cargo metadata --format-version 1 --no-depshad SHA-2563dfb2718fd55…before and after removal, so it never selected that member-local lockfile. - Updated the requested compatible crates, including zeroize 1.9.1, webpki-roots 1.0.9, Tauri 2.12.2 with build 2.7.2 and shell/window-state plugins, RustCrypto's current API family, Argon2 0.6.0, rand 0.10.3, rcgen 0.14.10, reqwest 0.13.5, toml 1.1.8, dirs 7.0.0, notify 8.2.0, tower-http 0.7.1 and utoipa 6.0.0. Transitive older versions retained by upstream dependencies remain normal Cargo resolution, not direct project requirements.
- Removed the unused global-shortcut plugin registration and its dependency. There was no matching capability entry. There was also no direct
@tauri-apps/apiimport, so no unused npm API package was added. - Moved the frontend from
js-yamlplus its typings toyaml2.9.1 and TypeScript 6.0.3. The current import/export and formatting paths parse/stringify data and do not need comment preservation; R08's future template mode can make a separate preservation decision. - Repaired the family API migrations: Rand 0.10 uses
rand::rng, HMAC importsKeyInit, SHA digest formatting useshex::encode, Argon2 0.6 uses its password-hashing API, AES-GCM nonce construction validates length withtry_from, and thessh-key0.6 bridge implements that crate's older rand-core trait against the project's entropy source. - Changed newly generated
.vaultbakand.vaultarcheaders to PBKDF2-SHA256 with 600,000 iterations. Import still uses the iteration count in the envelope, so the 0.42.x fixtures at 210,000 iterations remain readable by both Rust and Web Crypto. - Added a byte-for-byte reviewed OpenAPI snapshot at
unv-server/tests/fixtures/openapi.json. Its SHA-256 matches the pre-upgrade canonical document:6658b21cc080…. - Added tests for the old desktop backup fixture, fresh CLI backup header cost, Utoipa document snapshot, and
dirsplatform data-directory semantics. Existing Argon2, node-signature, audit/history chain and tampered-request tests remain the compatibility coverage.
Verification completed:
cargo test --workspace --lockedpassed after lock generation. It includes 459 vault-core unit tests, 92 server unit tests, CLI backup restoration, node signature/tamper rejection, the Argon2 golden vector, and all integration/doc-test targets.npm run checkpassed: 91 test files and 1,561 tests; format, ESLint, TypeScript 6 typecheck and version consistency were clean.cargo clippy --workspace --all-targets -- -D warningspassed.cargo deny checkpassed advisories, bans, licences and sources. It printed only existing duplicate-transitive-crate and stale-ignore warnings while returning zero.npm audit --omit=devandnpm auditboth reportedfound 0 vulnerabilities.npm run preflightpassed end to end, including a second full Rust suite, the frontend check, and Vite build. Vite retained its existing dynamic-import and chunk-size warnings.
GitHub's Linux/Windows matrix cannot be run locally without a push, and an interactive native Tauri window was not opened. The upgraded desktop crate compiled and linked during both workspace test and preflight.
The bugs that mattered
- TypeScript 6 strengthened Web Crypto's typed-array declaration. The generic entropy helper previously allowed a
SharedArrayBuffer-backed view thatcrypto.getRandomValuesdoes not accept.fillRandomnow admits onlyArrayBuffer-backedUint8ArrayorUint32Array, preserving its actual browser contract instead of casting away the error. yaml.parsereturnsany. Two formatter paths inherited that unsafe value and ESLint correctly refused the migration. They now contain it asunknownbefore serialisation.- The generated OpenAPI JSON must not be reformatted. Prettier initially rejected the new canonical snapshot, so
unv-server/tests/fixtures/now follows the existing golden-fixture ignore policy. Formatting it would make the review assertion noisy rather than test a real document. - The RustCrypto and Rand upgrades changed APIs at compilation boundaries. The source updates preserve validation: malformed AES-GCM IVs are rejected before decryption, entropy remains the source for generated SSH keys, and digest output stays lowercase hex.
Decisions made
- No new ADR: R03 implements already-recorded roadmap policy and does not change the backup envelope's fields or the public API. The only user-visible policy choice, 600,000 PBKDF2 iterations for new backups, was prescribed by the phase and pinned with compatibility tests.
rust-version = 1.90, because this is the Tauri 2.12 MSRV verified during research. A lower declaration would promise a build the desktop dependency no longer supports.- Keep
ssh-keyon 0.6: 0.7 was only a release candidate at verification time. Its older rand-core traits require the tiny local bridge; jumping to an RC would create a larger compatibility risk than the necessary adapter. - Do not add
@tauri-apps/api: package parity means matching versions for packages in use, not creating an unused runtime dependency. - Keep the old
kdf.itersreader behaviour exactly. New files harden, old headers declare their historical cost, and guessing a current default for an old envelope would make valid backups unreadable.
What Worked / What Didn't Work
- Cargo's metadata output gave a definitive, cheap proof that deleting
src-tauri/Cargo.lockcannot alter workspace resolution. - The pre-upgrade OpenAPI server snapshot and Utoipa 6 test showed no document drift, so the fixture remains the exact pre-upgrade JSON rather than an accepted schema rewrite.
cargo generate-lockfile --offlinewas needed after removing an unnecessary Argon2 feature because--lockedcorrectly refuses any lockfile change.- The first frontend check caught fixture formatting and the second caught the two unsafe YAML assignments; both were fixed before the final preflight.
Next Steps
- The next roadmap item is R04,
unv-appextraction. - The maintainer must push the completed changes for the GitHub Linux and Windows matrix. No local action can reproduce the hosted runner matrix exactly.
- Commit the changed tracked files using the explicit per-file command provided with the completion report.
the session records/70-roadmap-r03-dependency-modernisation.mditself is ignored local session history.
Notes for whoever picks this up
- Do not reintroduce
src-tauri/Cargo.lock; the root lockfile is the sole workspace lockfile. - Keep exact pins only for
rusqliteandargon2. Any new exact pin needs an on-disk/derived-key rationale and a golden test. - The OpenAPI fixture is canonical generated output. Do not run a formatter over it; update it only after reviewing an intentional semantic specification diff.
- The 600,000 iteration setting applies to new backups only. Both Rust and TypeScript importers must continue to honour
kdf.itersfrom existing envelopes.
1 line(s) about the maintainer's own machines were left out of this page.