- Device key (DeviceSigner): Windows TPM via CNG with a DPAPI-sealed software fallback, Linux Secret Service with a 0600 file fallback (warned in Settings), macOS keychain for dev runs. The store used is recorded; no silent switching. - SyncService (Tauri-free): server URL and pins, create account with the server's setup code, sync after unlock/save/browser save, every 15 min while unlocked and on demand, status events, integrity alarm, device list with fingerprint approval and revoke. - Onboarding: "Use my phone" (join_start/poll, QR rendered locally, 6-digit code), Emergency Kit from PDF/PNG/JPEG (hayro + rqrr), paste setup code, new account. Then only the master password. - From a signed-in desktop: "Add a phone or tablet" QR with countdown (cancel, lock and quit revoke the ticket) and "Approve a computer" via pasted join code. - KESTROVE_DATA_DIR / KESTROVE_DEVICE_NAME for a second instance; ignored live test drives three instances against a real server. - deny: ignore three unmaintained notices for zbus 5 sub-crates (Linux keyring). Co-Authored-By: Claude Opus 5.5 <[email protected]>
5.2 KiB
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.
# 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-<user>, first instance only, local clients only, DACL for the current user, client token SID checked (compile-checked only).KESTROVE_IPC_DIRisolates an instance for tests. - Pairing (
channel.rs, mirrored by kestrove-browsersrc/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-nmhonly relays ciphertext. - Protocol (
broker.rs):query→ identities for the origin (items_for_url);fill/totpre-check that the item matches the origin and need an unlocked vault;saveshows a prompt in the app (new login or password update). - Native host manifests:
native-messaging/install.sh(Linux, macOS) andinstall.ps1(Windows, HKCU registry) fill in the host path and extension ids. - Tests:
cargo test(unit tests +tests/nmh_stdio.rs, which drives the realkestrove-nmhover stdio through the paired channel).examples/test-host.rsis 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.
Sync and onboarding (docs/03, docs/10)
- First start offers four ways in: Use my phone (default: type the server URL, scan the QR on screen
with a signed-in phone, compare the 6-digit code, then type only the master password), Emergency Kit
(PDF, or a PNG/JPEG photo of its QR), Paste setup code, and New account (server URL + the server's
KV_SETUP_CODE). - Device key (
device_key.rs): Windows TPM via CNG, else a DPAPI-sealed software key; Linux Secret Service, else a 0600 file (with a warning in Settings); macOS dev runs use the keychain.KESTROVE_DEVICE_KEY=fileforces the file store. - Sync (
sync.rs) runs after unlock, after a save, every 15 minutes while unlocked, and on "Sync now". Lock drops all keys (core), cancels a scan-to-join and revokes an "Add a device" ticket still on screen. An integrity alarm shows a hard alert and a banner; syncing that vault stops. - Settings → Devices: approve pending devices (compare fingerprints), remove devices, Add a phone or tablet (10-minute single-use QR; Done/Cancel revokes it) and Approve a computer (paste the join code a new computer shows under "No phone?").
- Two instances on one machine:
KESTROVE_DATA_DIR=/tmp/kv-b Kestrove.app/Contents/MacOS/kestrove-desktop(the second one has no browser integration).KESTROVE_DEVICE_NAMEoverrides the device name. - Live test:
tests/live_sync.rs(ignored) drives three instances against a running server; see its header.
Roadmap (M3, kestrove-spec/docs/07)
- Unlock with Windows Hello (KeyCredentialManager, TPM) and libsecret on Linux
- Persistent vault (
VaultCore::openin app data) - Sync, device approval and scan-to-join onboarding
- Auto-lock on idle, screen lock and suspend
- Local IPC between
kestrove-nmhand the app, plus the pairing AEAD channel - 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