# kestrove-desktop **Windows and Linux** app built on Tauri 2. The Rust side links `kestrove-core`'s `kv-ffi` directly. The web UI only renders and never touches keys. macOS uses the native `kestrove-apple` app. Also ships `kestrove-nmh`, the **native-messaging host** that bridges `kestrove-browser` to the app. ```bash # prerequisites: rustup, Node 20+, and Tauri's OS deps (https://tauri.app/start/prerequisites/) npm install npm run tauri dev npm run tauri build # MSI/NSIS on Windows, AppImage/deb on Linux npm run tauri build -- --debug --bundles app # macOS dev build (Kestrove.app) npm run tauri icon assets/logo.png # regenerate src-tauri/icons (placeholder logo) (cd src-tauri && cargo clippy --all-targets -- -D warnings && cargo test) ``` The vault lives in the OS app-data dir (`vault.sqlite`, plus `pairings.json`, `settings.json` and `secret-key`, all owner-only). Closing the window keeps Kestrove in the tray so the browser extension keeps working; Quit is in the tray menu. ## Browser integration (docs/05) ``` extension ─ native messaging (stdio) ─▶ kestrove-nmh ─ local IPC ─▶ app (src-tauri/src/broker.rs) └──────────── pairing channel: X25519 → 6 words → AES-256-GCM, end to end ───────────┘ ``` * **IPC** (`ipc.rs`): Unix socket `$XDG_RUNTIME_DIR/kestrove/nmh.sock` (macOS: the per-user temp dir), dir 0700, socket 0600, peer uid checked on both ends. Windows: `\\.\pipe\kestrove-nmh-`, first instance only, local clients only, DACL for the current user, client token SID checked (compile-checked only). `KESTROVE_IPC_DIR` isolates an instance for tests. * **Pairing** (`channel.rs`, mirrored by kestrove-browser `src/channel.ts`, shared test vectors): both UIs show 6 words; the user confirms in the app (needs an unlocked vault) and in the extension. Each connection derives a fresh session key from both sides' nonces; messages carry strict counters, so replay and reordering fail. `kestrove-nmh` only relays ciphertext. * **Protocol** (`broker.rs`): `query` → identities for the origin (`items_for_url`); `fill`/`totp` re-check that the item matches the origin and need an unlocked vault; `save` shows a prompt in the app (new login or password update). * **Native host manifests**: `native-messaging/install.sh` (Linux, macOS) and `install.ps1` (Windows, HKCU registry) fill in the host path and extension ids. * **Tests**: `cargo test` (unit tests + `tests/nmh_stdio.rs`, which drives the real `kestrove-nmh` over stdio through the paired channel). `examples/test-host.rs` is a headless, auto-approving stand-in for the app used by kestrove-browser's interop and Chrome end-to-end tests. ## Auto-lock 10 minutes idle by default (Settings), plus screen lock and sleep (`autolock.rs`). Idle time is the system's on Windows (`GetLastInputInfo`) and macOS; on Linux it is activity inside Kestrove (UI input and fills). Screen lock: Windows input-desktop check, Linux logind `LockedHint`, macOS session dictionary. Sleep: a jump in the wall clock between polls. ## Roadmap (M3, kestrove-spec/docs/07) - [ ] Unlock with Windows Hello (KeyCredentialManager, TPM) and libsecret on Linux - [x] Persistent vault (`VaultCore::open` in app data); sync UI still to do - [x] Auto-lock on idle, screen lock and suspend - [x] Local IPC between `kestrove-nmh` and the app, plus the pairing AEAD channel - [x] Native-messaging manifest installers (`native-messaging/install.sh`, `install.ps1`) - [ ] **Quick Access** global hotkey (Ctrl+Shift+Space): search, then copy or auto-type (Windows `SendInput`, X11 XTest; Wayland gets copy only) - [ ] MSI/deb installers run the manifest installers - [ ] Windows 11 passkey plugin provider