core: extract the store and sync engine into a shared crate (M12 step 1)
Desktop (Tauri) / Tauri desktop (Linux) (push) Failing after 48s
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 1m50s
Desktop (Tauri) / Update manifest (push) Skipped

Android becomes a native Kotlin client over this same code (Scribe note 2730), so
the local store and sync engine stop being modules of the desktop app and become
`thoughtsync-core`, a crate with no UI framework in it at all.

This is a move, not a rewrite, and the measurement is why: every file in local/
and sync/ already carried ZERO Tauri references — 4,980 of 6,372 lines. The
coupling was 473 lines of command shim, which stays behind in the desktop crate
as src/commands/. Kept as git renames so history follows the files.

The desktop imports them under their old names (`use thoughtsync_core::{local,
sync}`) so every call site reads exactly as before. What moved is where they
live, not what they are.

Two things a workspace changes that are easy to miss, both caught before pushing:

[profile.release] now lives at the workspace ROOT. Cargo silently ignores
profiles declared by a non-root member — leaving it in the desktop crate would
have dropped lto/strip/opt-level from every release build with only a warning.

And a workspace shares ONE target dir, so the bundles moved from
desktop/src-tauri/target to target/. Thirteen references across publish-release,
debundle-graphics, verify.sh, package-prebuilt and the workflow now point there.
Pinning target-dir back would have been the smaller diff, but the Android lane
also produces Rust artifacts and they do not belong under desktop/.

Also retires the Tauri Android lane in the same push rather than leaving a path
that is being replaced: gen/android, android.yml and docs/android-dev.md are
gone, the mobile_entry_point attribute with them, and the lib drops to rlib —
staticlib/cdylib existed for Tauri mobile, and the .so Android loads will be
built from the core crate instead. Rule 22, no parallel path.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-17 23:12:26 -04:00
co-authored by Claude Opus 5
parent c28f2bc00e
commit 0a7480cf9b
75 changed files with 246 additions and 1346 deletions
+18 -53
View File
@@ -9,11 +9,15 @@ edition = "2021"
# src/main.rs.
autobins = false
# App logic lives in the library (Tauri v2 pattern: a single `run()` entry point
# reusable across desktop and any future mobile target); main.rs is a thin shim.
# App logic lives in the library (Tauri v2 pattern: a single `run()` entry point);
# main.rs is a thin shim.
#
# rlib only. The staticlib/cdylib types existed for Tauri mobile, which Android no
# longer uses — it is a native Kotlin client over `thoughtsync-core` instead
# (Scribe note 2730), and the .so it loads is built from that crate, not this one.
[lib]
name = "thoughtsync_desktop_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
crate-type = ["rlib"]
# The shipped command is `thoughtsync` on every install channel, and the binary's
# own name is what the desktop actually keys on: GTK derives the window's WM_CLASS
@@ -32,58 +36,19 @@ path = "src/main.rs"
tauri-build = { version = "2", features = [] }
[dependencies]
# The framework-free client core: local SQLite store + sync engine. Shared with the
# Android client, which binds the same crate through uniffi (Scribe note 2730).
thoughtsync-core = { path = "../../core" }
tauri = { version = "2", features = [] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
# Local-first store (M10.4): bundled = compile SQLite in, so there's no system
# libsqlite dependency to vary across the AppImage / native / Windows builds.
rusqlite = { version = "0.32", features = ["bundled"] }
uuid = { version = "1", features = ["v4"] }
# RFC3339 timestamps for created_at/updated_at/remind_at (Date.parse-able on the JS side).
chrono = { version = "0.4", default-features = false, features = ["clock"] }
serde = { workspace = true }
serde_json = { workspace = true }
log = { workspace = true }
# Startup + operation logging to stdout AND a persistent file, so portability
# issues are diagnosable from any environment. `log` is the facade the code uses.
# issues are diagnosable from any environment.
tauri-plugin-log = "2"
log = "0.4"
# In-app updates (M10.9). Signature verification is minisign; the public half lives
# in tauri.conf.json and the private half only ever as a CI secret.
# in tauri.conf.json and the private half only ever as a CI secret. Desktop only —
# the plugin declares android support level "none", which is why the Android client
# gets a server-served update path instead (Scribe note 2725).
tauri-plugin-updater = "2"
# HTTP for the opt-in server handshake (M10.6) and, next, the sync engine (M10.7).
#
# native-tls, NOT rustls, deliberately: on x86_64-pc-windows-msvc native-tls
# resolves to `schannel` — pure-Rust bindings to the OS TLS stack — so nothing C or
# assembly has to cross-compile on the Windows lane, which is the fragile one (it
# builds on Linux via cargo-xwin, and a C dependency there is what broke it before).
# rustls would instead pull in ring/aws-lc-rs and their assembler. On Linux
# native-tls uses OpenSSL, whose headers (libssl-dev) ci-tauri already ships.
# default-features off drops http2/charset we don't need for a JSON API.
reqwest = { version = "0.12", default-features = false, features = ["json", "native-tls"] }
# Verifying downloaded attachment bytes against the sha256 the server advertised.
# Pure Rust (no C/asm beyond optional cpufeatures), so it costs the Windows
# cross-compile lane nothing — see ci-requirements.md on why that matters here.
sha2 = "0.10"
# Android has no system OpenSSL to link against, and `native-tls` resolves to
# OpenSSL there — unlike Windows, where it lands on schannel and costs nothing.
# Without this the build dies at `openssl-sys`: "Could not find directory of
# OpenSSL installation".
#
# `vendored` compiles OpenSSL from source with the NDK toolchain (hence perl + make
# in ci-tauri-android). The alternative was rustls on Android only, which builds
# faster — but rustls ships its own root store, so the phone would trust a
# DIFFERENT set of certificates than the desktop does. A self-hosted server behind
# a private or enterprise CA would then work on one surface and fail on another,
# and "the surfaces behave the same" is worth more here than build minutes.
#
# Declared as a direct dependency purely to turn the feature on: cargo's feature
# unification applies it to the copy `native-tls` pulls in transitively.
[target.'cfg(target_os = "android")'.dependencies]
openssl-sys = { version = "0.9", features = ["vendored"] }
# Tauri's default release profile: smaller, faster shipped binaries.
[profile.release]
codegen-units = 1
lto = true
opt-level = "s"
panic = "abort"
strip = true