github zhitongblog/solomd v3.0.2
SoloMD v3.0.2

latest releases: v4.11.9, v4.11.8, v4.11.7...
3 months ago

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 String per fetch/push (Box::leak was being called on every call; now cached behind a process-local &'static).
  • SELF_WRITES and SYNC_REWRITE_WINDOWS watcher 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 being encodeURIComponent'd as a whole, turning slashes into %2F and 404'ing the request.

Self-test before release

  • MCP: stdio JSON-RPC drove initializetools/list (8 tools) → list_notes (3 notes) → search "needle" (2 hits)
  • CLI: solomd help / list / cat / search / new against a fresh fixture
  • cargo test: 111 tests pass, including the new github_sync_corrupted_config_fails_closed regression
  • .app boot 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.

Don't miss a new solomd release

NewReleases is sending notifications on new releases.