---
name: Slice 02 — Tauri runtime
type: architecture-map-page
slice: 02-tauri-runtime
last_verified: 2026/05/12
---

# Slice 02 — Tauri runtime

> **Where you are:** [Architecture map](../README.md) → Tauri runtime

**Plain English summary.** The Tauri runtime is the bridge between Lumotia's Svelte frontend and the Rust workspace crates. It owns app startup (database init, panic hook, plugin wiring, preferences injection), the system tray, the secondary windows (task float, transcript viewer, transcription preview), and the entire `#[tauri::command]` surface that the frontend invokes for audio capture, transcription, LLM cleanup, task and transcript CRUD, paste, TTS, hotkeys, diagnostics, and more. Everything that runs on the host process but is not pure crate logic lives here.

## At a glance

- Path: `src-tauri/`
- Total LOC (Rust + Cargo + JSON, excluding `gen/`): ~8,690.
- Tauri version: `2` (see `src-tauri/Cargo.toml:44`).
- Bundle identifier: `uk.co.corbel.lumotia` (`src-tauri/tauri.conf.json:5`).
- Plugins (always-on): `tauri-plugin-opener`, `tauri-plugin-dialog`, `tauri-plugin-notification`.
- Plugins (desktop-only, gated `cfg(not(target_os = "android"))`): `tauri-plugin-global-shortcut`, `tauri-plugin-autostart` (LaunchAgent), `tauri-plugin-window-state`. The `tray-icon` Tauri feature is also desktop-only.
- Workspace crates pulled in: `lumotia-core`, `lumotia-audio`, `lumotia-transcription` (default-features off, `whisper` re-enabled here), `lumotia-ai-formatting`, `lumotia-storage`, `lumotia-cloud-providers`, `lumotia-hotkey`, `lumotia-llm`.
- Tauri commands exposed via `invoke_handler` in `src-tauri/src/lib.rs:321`: 71 commands.
- Capability files: `src-tauri/capabilities/main.json` (main window) and `src-tauri/capabilities/secondary-windows.json` (task float, transcript viewer, transcription preview).
- Command modules: 22 `#[tauri::command]` modules plus 3 utility modules (`mod.rs`, `power.rs`, `security.rs`).
- Integration tests: `src-tauri/tests/config_hardening.rs` (3 tests guarding CSP, updater signing, secondary-window permissions).

## Map of this slice

App boot, config, tests:

- [App lifecycle](app-lifecycle.md). `src-tauri/src/main.rs` and `src-tauri/src/lib.rs`. Run entry, AppState construction, plugin wiring, preferences injection, Linux launcher-env warning, panic hook, error-log pruning, command registration.
- [System tray](system-tray.md). Desktop-only tray icon and menu (`src-tauri/src/tray.rs`).
- [Tauri config](tauri-config.md). `tauri.conf.json` plus the Linux native-decorations overlay; CSP, window defaults, bundle settings.
- [Capabilities and ACL](capabilities-and-acl.md). The two ACL files in `capabilities/`, what each scopes, and the Phase 9 high-risk-permission firewall.
- [Cargo and features](cargo-and-features.md). `Cargo.toml`, the `whisper` cargo feature, the per-target dependency blocks, `build.rs`, `.cargo/config.toml`.
- [Tests](tests.md). Config-hardening regression tests.

Command modules (entry index):

- [Commands index](commands/README.md). Every command file with a one-liner.

Individual command pages (linked from the commands index):

- [Audio capture](commands/audio.md), [Live transcription](commands/live.md), [Paste at cursor](commands/paste.md), [Models registry and runtime](commands/models.md), [Transcription](commands/transcription.md), [Local LLM](commands/llm.md), [Text to speech](commands/tts.md), [Tasks and decomposition](commands/tasks.md), [Transcripts CRUD](commands/transcripts.md), [Diagnostics and reports](commands/diagnostics.md), [Implementation intentions](commands/intentions.md), [Profiles](commands/profiles.md), [Window management](commands/windows.md), [Hotkey bridge](commands/hotkey.md), [Feedback capture](commands/feedback.md), [Power assertions and security](commands/power-and-security.md), [Small commands](commands/small-commands.md), [mod.rs registration](commands/mod.md).

## How this slice connects to others

- **Frontend (slice 01).** Every `#[tauri::command]` is invoked from Svelte via `@tauri-apps/api/core` `invoke()`. Events emitted via `app.emit(...)` are consumed via `listen()` in the frontend. Live transcription uses typed `tauri::ipc::Channel` instead of plain events; the channel pair is created on the JS side and passed in as command args.
- **Audio + transcription (slice 03).** `commands::audio` calls `lumotia_audio::{MicrophoneCapture, WavWriter, decode_audio_file_limited, resample_to_16khz, probe_audio_duration_secs}`. `commands::transcription` and `commands::live` call `lumotia_transcription::LocalEngine` plus `lumotia_audio::StreamingResampler`. `commands::models` calls `lumotia_transcription::{model_manager, load_whisper, load_parakeet}`.
- **LLM + formatting + MCP (slice 04).** `commands::llm` calls `lumotia_llm::{LlmEngine, model_manager, ContentTags, LlmModelId}` and `lumotia_ai_formatting::{llm_cleanup_text, LlmPromptPreset}`. `commands::tasks` calls `lumotia_llm::prompts::FeedbackExample` and the engine's `decompose_task_with_feedback` / `extract_tasks_with_feedback` / `extract_content_tags`. `commands::transcription` and `commands::live` call `lumotia_ai_formatting::{post_process_segments, FormatMode, PostProcessOptions}`. `commands::profiles` calls `lumotia_ai_formatting::extract_corrections` for auto-learned vocabulary.
- **Core + storage + hotkey + build (slice 05).** Everything DB-touching goes through `lumotia_storage` (`init`, `database_path`, `get_setting`, `set_setting`, `prune_error_log`, the full set of CRUD helpers, `app_data_dir`, `crashes_dir`, `logs_dir`, `list_recent_errors`, `log_error`). `commands::hardware` and `commands::models` call `lumotia_core::{hardware, model_registry, recommendation, types, constants}`. `commands::meeting` calls `lumotia_core::process_watch`. `commands::hotkey` is a thin Tauri wrapper around `lumotia_hotkey::{EvdevHotkeyListener, HotkeyCombo, HotkeyEvent}`. `build.rs` is the build-system half of the slice (CSP regression guard plus ggml multi-definition link arg).

## Open questions / debt

- `commands/live.rs` is 1,737 LOC. The runtime, loop state, speech gate, dedup, and chunking logic share the file. Splitting per concern would track against the broader refactor pass already mooted in the in-repo code review (`docs/code-review-2026-04-22.md`). See [`commands/live.md`](commands/live.md) for the breakdown.
- `commands::update::install_update` returns a hard-coded "Updates are disabled until release signing is configured." (`src-tauri/src/commands/update.rs:15`). The integration test `updater_is_signed_or_absent` (`src-tauri/tests/config_hardening.rs:35`) only asserts that *if* an updater config ships, it carries a non-empty pubkey. There is currently no updater config in `tauri.conf.json`, so the test is an empty no-op.
- `commands::power::PowerAssertion` is a no-op on Linux and Windows (`src-tauri/src/commands/power.rs:90`). Only macOS has a real implementation via `objc2`. The doc comment promises `SetThreadExecutionState` (Windows) and logind inhibitors (Linux), but neither is wired up. Symptom: long live-dictation sessions on Linux can be idled by the compositor.
- `src-tauri/.cargo/config.toml` hard-codes `LIBCLANG_PATH = "C:\\Program Files\\LLVM\\bin"` (Windows). It is harmless on non-Windows hosts (env var is just unused) but it is a foot-gun if someone moves Clang elsewhere on Windows. See [Cargo and features](cargo-and-features.md).
- The Linux rendering workaround in `lib.rs` (`warn_if_x11_env_unset_on_wayland`) now warns when the launcher has not set the expected env vars; it no longer mutates the process environment. In development, `run.sh` / `npm run dev:tauri` owns the defaults (`WEBKIT_DISABLE_DMABUF_RENDERER=1` on Linux; `GDK_BACKEND=x11` and `WINIT_UNIX_BACKEND=x11` on Wayland). The user opt-out remains `WEBKIT_DISABLE_DMABUF_RENDERER=0`, set before launching.
- `commands::diagnostics::install_panic_hook` writes a "minimal text dump" without backtraces unless the user has `RUST_BACKTRACE=1` set (`src-tauri/src/commands/diagnostics.rs:42`). The packaged binary does not set it, so production crash dumps will lack stack traces. Document or default-enable.
- `commands::audio::list_audio_devices` is gated `ensure_main_window` but the `secondary-windows` capability does not invoke it, which is correct. The `clipboard::copy_to_clipboard` command, by contrast, has no main-window guard and any window with the `core:default` permission can call it; intentional, but worth flagging.

## Existing in-repo docs

- `docs/code-review-2026-04-22.md`. The MAJOR / MINOR review that motivated several of the safety helpers seen here (the parallel-mode loopback CSP guard in `build.rs`, secondary-window high-risk-permission test, RB-06 worker-join in `commands::audio`, RB-07 `compose_accelerators` in `commands::models`, RB-08 macOS App Nap power assertion in `commands::power`).
- `docs/issues/`. Open issue threads, several of which the diagnostic-report bundler exists to feed.
- `docs/whisper-ecosystem/brief.md`. Source of the numbered "brief items" cited in code comments (item #2 = loopback LLM CSP, item #9 = App Nap, items #10/#17 = paste / replace flows, item #19 = progressive WAV writer, item #28 = sequential-GPU mode).
- `docs/handovers/`. Daily handover docs that cite specific command surfaces; useful when the in-source comments cite a "RB-NN review point".
- `docs/dev-setup.md`. Linux + Windows + macOS toolchain setup, including the Vulkan loader install required for GPU-backed whisper.cpp.
