Phase 9 of the rebrand cascade. Sweep covers everything the Phase 8
frontend pass deliberately skipped: docs/, root markdown, scripts,
Cargo.toml descriptions, code comments that survived earlier
word-boundary sed, plus a handful of identifiers caught on the final
verify pass.
transcription-app changes:
- README.md, HANDOVER.md, KNOWN-ISSUES.md, run.sh — magnotia/Magnotia
-> lumotia/Lumotia.
- docs/ — sweep across all subdirs except docs/handovers/ (preserved
as immutable audit trail). Includes architecture-map references
to magnotia_core::*, magnotia_storage::*, etc. now pointing at
lumotia_*; dev-setup.md tracing output examples (lumotia_startup
target); brief/ + superpowers/ + issues/ + whisper-ecosystem/ +
audit/.
- Cargo.toml descriptions on 9 crates (core, audio, cloud-providers,
hotkey, llm, mcp, plus referenced others).
- crates/core/src/{error,hardware,recommendation,paths}.rs +
crates/audio/src/wav.rs + crates/llm/src/model_manager.rs +
crates/cloud-providers/src/keystore.rs + crates/mcp/src/lib.rs —
doc comments and a model-manager user-agent string.
- Caught on final pass: BroadcastChannel("magnotia_task_sync") -> ...
("lumotia_task_sync"); magnotia_locale i18n localStorage key
renamed + migration shim added; CSS keyframe names
magnotiaPulse / magnotiaBar / magnotiaFade renamed in the design-
system kit; magnotia_viewer_item / magnotia_viewer_mode handoff
keys renamed in HistoryPage + viewer/+page.svelte; src/assets/
wordmark.svg text.
- src-tauri/src/lib.rs comment cleanup ("magnotia era" was sed'd
to "lumotia era" earlier — restored).
Preserved (intentional):
- crates/core/src/paths.rs — keeps "magnotia" / "Magnotia" / ".magnotia"
legacy detection strings in legacy_and_target_paths() so the
migration shim can still find user data from the magnotia era.
- src/lib/stores/{page,focusTimer}.svelte.ts + src/lib/i18n/index.ts
— migration call sites reference the legacy magnotia keys
deliberately.
- docs/handovers/ — historical audit trail.
cargo build --workspace passes. npm run check: 0 errors / 0 warnings
(3958 files). cargo test --workspace: 339 pass / 0 fail.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
153 lines
8.0 KiB
Markdown
153 lines
8.0 KiB
Markdown
---
|
||
name: Cargo and features
|
||
type: architecture-map-page
|
||
slice: 02-tauri-runtime
|
||
last_verified: 2026/05/09
|
||
---
|
||
|
||
# Cargo and features
|
||
|
||
> **Where you are:** [Architecture map](../README.md) → [Tauri runtime](README.md) → Cargo and features
|
||
|
||
**Plain English summary.** This page walks the Tauri crate's `Cargo.toml`, its `build.rs`, and its `.cargo/config.toml`. The crate is the binary entry for the desktop app and the library entry for the Android target. The `whisper` cargo feature is the kill-switch for the whisper.cpp backend. Per-target dependency blocks gate macOS objc2 bindings, Linux GTK / WebKitGTK, and Windows base64 (used by the TTS PowerShell shim). `build.rs` enforces the CSP regression guard documented in `docs/whisper-ecosystem/brief.md` item #2.
|
||
|
||
## At a glance
|
||
|
||
- Path: `src-tauri/Cargo.toml` (108 LOC), `src-tauri/build.rs` (81 LOC), `src-tauri/.cargo/config.toml` (3 LOC).
|
||
- Tauri commands exposed: none. Build-system files only.
|
||
- Events emitted: none.
|
||
- Depends on: every workspace crate (slices 03–05) plus the Tauri ecosystem.
|
||
- Called from frontend at: nothing direct. The build outputs land in the dev / packaged binary.
|
||
|
||
## What's in here
|
||
|
||
### `Cargo.toml`
|
||
|
||
Package metadata: `name = "lumotia"`, `version = "0.1.0"`, `description = "Lumotia — Think out loud"`, `authors = ["CORBEL Ltd"]`, `edition = "2021"`.
|
||
|
||
Lib stanza (`src-tauri/Cargo.toml:8`):
|
||
|
||
```
|
||
name = "lumotia_lib"
|
||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||
```
|
||
|
||
`staticlib` and `cdylib` are needed for the Android target where Tauri builds an `.aar` from a `cdylib`. `rlib` makes it consumable from `main.rs`.
|
||
|
||
#### `[features]`
|
||
|
||
```
|
||
default = ["whisper"]
|
||
whisper = ["lumotia-transcription/whisper"]
|
||
```
|
||
|
||
The `whisper` feature transitively enables `lumotia-transcription/whisper`. The crate-level `default-features = false` on `lumotia-transcription` (`src-tauri/Cargo.toml:33`) means a `--no-default-features` workspace build drops `whisper-rs-sys` entirely; Parakeet still works. `commands::models::load_model_from_disk` returns a clear runtime error for `Engine::Whisper` when the feature is off.
|
||
|
||
#### `[build-dependencies]`
|
||
|
||
`tauri-build = "2"`, plus `serde_json = "1"` for the CSP regression guard in `build.rs`.
|
||
|
||
#### `[dependencies]` — workspace crates
|
||
|
||
```
|
||
lumotia-core
|
||
lumotia-audio
|
||
lumotia-transcription { default-features = false }
|
||
lumotia-ai-formatting
|
||
lumotia-storage
|
||
lumotia-cloud-providers
|
||
lumotia-hotkey
|
||
lumotia-llm
|
||
```
|
||
|
||
The `cloud-providers` crate is referenced here even though no command file currently imports it. Likely reserved for the Phase-N upload flow that the diagnostic-report bundler hints at.
|
||
|
||
#### `[dependencies]` — Tauri
|
||
|
||
```
|
||
tauri = { version = "2" }
|
||
tauri-plugin-opener = "2"
|
||
tauri-plugin-dialog = "2"
|
||
tauri-plugin-notification = "2"
|
||
```
|
||
|
||
These three plugins are unconditional. `notification` supports Android natively (Phase 6 nudges) so it stays out of the desktop-only block.
|
||
|
||
#### `[dependencies]` — runtime
|
||
|
||
```
|
||
serde = { version = "1", features = ["derive"] }
|
||
serde_json = "1"
|
||
tokio = { version = "1", features = ["rt", "sync"] }
|
||
arboard = "3.6.1"
|
||
sqlx = { version = "0.8", default-features = false, features = ["runtime-tokio", "sqlite"] }
|
||
uuid = { version = "1", features = ["v4"] }
|
||
```
|
||
|
||
The `sqlx` block has `default-features = false` and only opts into `runtime-tokio` and `sqlite`. `lumotia-storage` already pulls the macros / migrate / any / json features via its own re-export, so duplicating them here would just bloat compile time. `sqlx` is named directly because `AppState` types it as `SqlitePool`; naming a transitive dep type still requires the dep be listed.
|
||
|
||
#### `[dev-dependencies]`
|
||
|
||
`tempfile = "3"` for the Phase 9 `commands::fs::write_text_file_cmd` tests.
|
||
|
||
#### `[target.'cfg(not(target_os = "android"))'.dependencies]`
|
||
|
||
```
|
||
tauri = { version = "2", features = ["tray-icon"] }
|
||
tauri-plugin-global-shortcut = "2"
|
||
tauri-plugin-window-state = "2"
|
||
tauri-plugin-autostart = "2"
|
||
```
|
||
|
||
Each is justified inline in `src-tauri/Cargo.toml:74`. Tray icons, global shortcuts, multi-window state, and autostart all either fail to compile against the Android NDK or are structurally meaningless on a single-window mobile activity. The Cargo gate matches the `#[cfg(not(target_os = "android"))]` blocks in `lib.rs` and `commands/windows.rs`.
|
||
|
||
#### Per-OS dependency blocks
|
||
|
||
```
|
||
linux: webkit2gtk = "2.0", gtk = "0.18", gdk = "0.18"
|
||
macos: objc2 = "0.6.4", objc2-foundation = { ... features = ["std", "NSString", "NSProcessInfo"] }
|
||
windows: base64 = "0.22"
|
||
```
|
||
|
||
- `webkit2gtk`/`gtk`/`gdk` are used in `lib.rs` (auto-grant audio capture) and `commands/windows.rs` (set GTK `WindowTypeHint::Utility` on the preview overlay). Versions track what `webkit2gtk` 2.0 transitively depends on.
|
||
- `objc2` + `objc2-foundation` power the macOS App Nap power assertion (`commands/power.rs::objc_bridge`).
|
||
- `base64` is the Windows TTS encoder. PowerShell `-EncodedCommand` requires UTF-16-LE base64.
|
||
|
||
### `build.rs`
|
||
|
||
Two responsibilities:
|
||
|
||
1. **Linker workaround.** `--allow-multiple-definition` is passed to GNU ld / lld on Linux because `llama-cpp-sys-2` and `whisper-rs-sys` both statically link their own copy of `ggml`, leading to duplicate symbols (`src-tauri/build.rs:8`). Documented as INTERIM; the intended fix is system-ggml shared-lib linking. Only emitted on Linux.
|
||
2. **CSP regression guard.** `assert_loopback_llm_csp` (`src-tauri/build.rs:30`) parses `tauri.conf.json` with `serde_json`, finds the `connect-src` directive (full-name match, not prefix), and asserts the four required tokens: `http://127.0.0.1:*` and `ws://127.0.0.1:*` must be present, `http://localhost:*` and `ws://localhost:*` must be absent. Fails compilation with a brief-item-#2 reference if any of those break. Re-runs when `tauri.conf.json` changes.
|
||
|
||
`tauri_build::build()` is called last. Order matters: the CSP guard fails fast, before tauri-build does any of its own work.
|
||
|
||
### `.cargo/config.toml`
|
||
|
||
```
|
||
[env]
|
||
LIBCLANG_PATH = "C:\\Program Files\\LLVM\\bin"
|
||
```
|
||
|
||
Hard-coded Windows path so `bindgen` (used by Tauri 2's macros and a couple of dependencies) can find clang during a Windows build. Harmless on non-Windows hosts — the env var is just unused. Foot-gun: a Windows developer with Clang in a non-default path will have to override or remove this.
|
||
|
||
## Data flow
|
||
|
||
- `cargo build` reads `Cargo.toml`, runs `build.rs`, then compiles `src/lib.rs` and `src/main.rs`. The CSP regression guard fires before any source compiles.
|
||
- The default features include `whisper`. A workspace-wide `cargo build --no-default-features` drops both whisper.cpp and the Tauri default features (which would also drop tray-icon, etc., so this is a niche build).
|
||
- Plugin crates land in the dependency graph and contribute permission manifests that `gen/schemas/` is regenerated from at build time.
|
||
|
||
## Watch-outs
|
||
|
||
- Adding a workspace crate dependency here also requires that crate to be in the root `Cargo.toml`'s workspace members (or referenced by `path =` here, which is what is done now). All eight workspace crates appear in this `Cargo.toml`.
|
||
- The `--allow-multiple-definition` link arg is the kind of thing that hides bugs. If both ggml copies ever drift, the binary picks "the first definition" and the second copy's slightly-different symbol is silently shadowed. Track the `whisper-rs-sys` and `llama-cpp-sys-2` ggml pins together.
|
||
- Bumping any of `objc2`, `objc2-foundation`, `webkit2gtk`, `gtk`, `gdk` is an ABI move. Test on each platform.
|
||
- The hard-coded `LIBCLANG_PATH` should ideally come from an environment variable or a build-script probe. Until then, document it in `docs/dev-setup.md` for Windows contributors.
|
||
|
||
## See also
|
||
|
||
- [App lifecycle](app-lifecycle.md) — `lib.rs::run` is what consumes everything declared here.
|
||
- [Tauri config](tauri-config.md) — `build.rs` reads `tauri.conf.json` and pins the CSP shape.
|
||
- [Tests](tests.md) — runtime regression for the same CSP property.
|
||
- [Capabilities and ACL](capabilities-and-acl.md) — `gen/schemas/` files are regenerated when a plugin in this Cargo manifest changes.
|