Reading changelogs before bumping three stale dependencies
The same repo review that found no dependency scanning also flagged three specific dependencies in Greenhouse’s Cargo.toml as stale: serde_yaml 0.9 is archived and unmaintained, rusqlite 0.31 was statically linking a two-year-old bundled SQLite missing that entire window of upstream fixes, and thiserror 1 was a duplicate major version already superseded everywhere else in the dependency tree.
Why this approach
None of these needed a design decision, just verification that the upgrade path was actually safe before touching anything. A version bump on a database driver and a serialization library is exactly the kind of change that looks trivial and occasionally isn’t.
Implementation
Before editing a single line, I grepped every call site of all three crates across the codebase: four serde_yaml:: uses, eight-ish thiserror-derived variants in one error enum, and a dozen-plus rusqlite calls in the database layer (connections, transactions, prepared statements, the params! macro, specific error variants). Then I checked each usage against what actually changed upstream, not just the version number:
- serde_yaml → yaml_serde 0.10.4: confirmed on crates.io as the YAML organization’s maintained fork, API-identical to serde_yaml (from_str/to_string/Value/Error all match). It’s a Cargo package rename, not a code migration -
serde_yaml = { package = "yaml_serde", version = "0.10" }and every existingserde_yaml::call site in the source keeps compiling unchanged. - rusqlite 0.31 → 0.40.1: nine minor versions, bundled SQLite jumping from 3.45.1 to 3.53.2. I pulled the GitHub release notes for every version in between and checked each breaking-change line against what Greenhouse’s db.rs actually touches. The breaking changes clustered around virtual tables, the statement cache, and u64/usize type conversions - none of which this codebase uses (i64 timestamps and UUID-string IDs throughout, no vtab/functions/backup/blob features).
- thiserror 1 → 2: Tauri’s own dependency tree was already on thiserror 2 for everything except our crate. The 2.0 breaking changes are format-string edge cases (positional argument capture, tuple-index ambiguity) that don’t apply to a plain derived error enum.
Gotcha
None, which was itself the interesting part. Three dependencies, nine minor versions of drift on the worst one, and the actual bump was cargo build succeeding on the first try. The work wasn’t in writing code, it was in reading enough changelog to know in advance that nothing would break - grep the call sites first, then check the exact API surface those call sites touch against the exact list of what changed, instead of bumping the version and finding out from the compiler.
Results
All 95 tests pass, including two that already did a full serialize-write-read-deserialize round trip through the same Config types the yaml_serde swap touches. Clean cargo build, clippy (deny warnings), and fmt check. Cargo.lock confirms the old serde_yaml package is gone entirely and thiserror 1.0.69/2.0.18 now coexist cleanly, since a handful of unrelated transitive deps (GTK/Android bindings pulled in by Tauri’s non-macOS backends) are still pinned to 1.x.
Related reading
Closing the PRD drift found in a code review pass
Four spots where Greenhouse's spec and its code disagreed - none of them bugs, all of them decisions I made in code and never wrote down.
Two notes nobody ever saw
Greenhouse saved a capture note and a handoff note faithfully, and showed neither: one had no field in the wire type, the other had a working command nobody called.
Two stats, two definitions of "captured"
The streak and the badge computed the same concept two different ways, and imports were quietly crediting six-month-old ideas as today's creative act.