Hardening release
Five fixes from a code-audit pass on the v3.0.x line. No new features.
Security
sync.json corruption no longer downgrades to plaintext push. When E2EE was enabled, the push and pull paths read sync.json to decide whether to route through the encrypted shadow. If that file ever became unreadable or malformed (truncated write after a crash, antivirus scan racing the writer, manual edit gone wrong), the code silently fell back to a default config (encrypted: false) and pushed the plaintext workspace to GitHub. Now refuses to run instead — fail-closed.
A regression test pins this behavior: github_sync_corrupted_config_fails_closed.
Reliability
Heavy Tauri commands no longer block the IPC pool. Following the workspace_index_init fix in v3.0.1, audited the rest of the surface and converted the remaining hot-path sync commands to async + spawn_blocking — so a slow read/write/search/git/encrypt call can never queue concurrent invokes the way workspace_index_init was queueing FileTree refreshes.
Converted: read_file, write_file, write_binary_file, copy_file, search_in_dir, crypto_encrypt_for_push, crypto_decrypt_after_pull, cjk_proofread, pandoc_export, convert_file_to_markdown.
CI / build
install-mcp.sh self-test no longer 404s on every release build. It was fetching the just-uploaded asset through the public GitHub URL, which returns 404 for draft releases (we publish manually after CI). Switched to running it against the local tarball directly via a new LOCAL_TARBALL env override. Self-test green for the first time since v2.4.
Polish
- libgit2 proxy options no longer leak a
Stringper fetch/push (Box::leakwas being called on every call; now cached behind a process-local&'static). SELF_WRITESandSYNC_REWRITE_WINDOWSwatcher maps no longer grow without bound on long sessions — opportunistic cleanup of expired entries before each insert.- Public share links on
solomd.app/share/?…now work for branches with/in them (e.g.feature/foo); the path was beingencodeURIComponent'd as a whole, turning slashes into%2Fand 404'ing the request.
Self-test before release
- MCP: stdio JSON-RPC drove
initialize→tools/list(8 tools) →list_notes(3 notes) →search "needle"(2 hits) - CLI:
solomd help / list / cat / search / newagainst a fresh fixture cargo test: 111 tests pass, including the newgithub_sync_corrupted_config_fails_closedregression.appboot smoke test on the locally-built dmg before upload
Downloads
Same matrix as v3.0.0/v3.0.1 — Mac universal dmg (notarized), Windows setup.exe + msi + portable.zip, Linux deb/AppImage/rpm × x64 + arm64, plus the standalone solomd-mcp archive for each platform and the browser clipper extensions.