README: plain-language guide for users, hosting and building
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -1,87 +1,109 @@
|
||||
# kestrove-desktop
|
||||
# Kestrove for Windows and Linux
|
||||
|
||||
**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.
|
||||
The Kestrove desktop app for **Windows 10/11 and Linux**: your password manager, with a vault encrypted on
|
||||
the computer and synced through your Kestrove server. On a Mac, use the Mac app from `kestrove-apple`
|
||||
instead: it does everything this app does.
|
||||
|
||||
Also ships `kestrove-nmh`, the **native-messaging host** that bridges `kestrove-browser` to the app.
|
||||
On a Mac, the Kestrove Mac app serves the browser extension itself (Chrome, Edge, Brave, Vivaldi, Arc,
|
||||
Firefox), so this app isn't needed there; it still builds on macOS for development.
|
||||
**What it does:**
|
||||
|
||||
- Your vault: logins, one-time codes, tags and "Sign in with Google/Apple", with search and a password
|
||||
generator.
|
||||
- **Connects the Kestrove browser extension** (Chrome, Edge, Brave, Firefox) to your vault: filling, saving
|
||||
new logins, and **passkeys**. You approve each passkey in the app with your master password.
|
||||
- Adding this computer to your account: scan a QR code with your phone, use your Emergency Kit, or paste a
|
||||
setup code.
|
||||
- Locks itself after 10 minutes without use (you can change this), when you lock the screen, and when the
|
||||
computer sleeps.
|
||||
- Closing the window keeps Kestrove running in the tray, so the browser extension keeps working. **Quit** is in
|
||||
the tray menu.
|
||||
|
||||
## Install
|
||||
|
||||
Download from the [releases page](https://gitea.samialabri.com/kestrove/kestrove-desktop/releases):
|
||||
|
||||
| System | File |
|
||||
|---|---|
|
||||
| Windows (x64) | `Kestrove_<version>_x64-setup.exe` |
|
||||
| Debian, Ubuntu | `Kestrove_<version>_amd64.deb`, then `sudo apt install ./Kestrove_*.deb` |
|
||||
| Fedora, openSUSE | `Kestrove-<version>-1.x86_64.rpm`, then `sudo dnf install ./Kestrove-*.rpm` |
|
||||
|
||||
Then open Kestrove and add this computer to your account. The easiest way is **Use my phone**: type your
|
||||
server's address and scan the QR code on screen with the Kestrove app on your phone.
|
||||
|
||||
**Connect your browser:** install the Kestrove extension, open it, and choose **Pair with Kestrove**. The
|
||||
extension and the app show the same six words; confirm in both. After that, the browser fills from your vault
|
||||
whenever the app is unlocked.
|
||||
|
||||
## Build it
|
||||
|
||||
You need [Rust](https://rustup.rs), Node.js 22+, and
|
||||
[Tauri's system packages](https://tauri.app/start/prerequisites/) for your OS, with `kestrove-core` next to
|
||||
this folder.
|
||||
|
||||
```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)
|
||||
npm ci
|
||||
npm run tauri dev # run it from source
|
||||
npm run tauri build # an installer for the system you're on (Windows: .exe; Linux: .deb/.rpm)
|
||||
(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.
|
||||
**Release builds from a Mac** (both write to `../release/desktop/`):
|
||||
|
||||
## Browser integration (docs/05)
|
||||
```bash
|
||||
# Linux .deb and .rpm, built in a clean Debian 12 container (run from the folder holding the repositories)
|
||||
docker buildx build --platform linux/amd64 -f kestrove-desktop/scripts/linux.Dockerfile \
|
||||
--target out -o type=local,dest=release/desktop .
|
||||
|
||||
```
|
||||
extension ─ native messaging (stdio) ─▶ kestrove-nmh ─ local IPC ─▶ app (broker)
|
||||
└──────────── pairing channel: X25519 → 6 words → AES-256-GCM, end to end ───────────┘
|
||||
# Windows installer, cross-compiled. Setting XWIN_ACCEPT_LICENSE=1 accepts Microsoft's
|
||||
# license for the Windows SDK files it downloads; the script header lists what to install first.
|
||||
XWIN_ACCEPT_LICENSE=1 scripts/windows.sh
|
||||
```
|
||||
|
||||
The bridge is shared with the macOS app and lives in kestrove-core: `crates/kv-ipc` (framing, IPC),
|
||||
`crates/kv-nmh` (the host) and `kv-ffi`'s `browser-bridge` feature (`src/bridge/`: broker, pairing
|
||||
channel). This crate re-exports them under the old module names.
|
||||
**Publish them on Gitea:** raise `version` in `package.json`, `src-tauri/tauri.conf.json` and
|
||||
`src-tauri/Cargo.toml`, tag the commit (`git tag v<version> && git push origin v<version>`), then:
|
||||
|
||||
* **IPC** (`kv-ipc`): 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_DIR` isolates an instance for tests.
|
||||
* **Pairing** (`bridge/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** (`bridge/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 for development only, the Mac
|
||||
app registers its own) 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.
|
||||
```bash
|
||||
GITEA_TOKEN=<token with write:repository> scripts/gitea-release.sh
|
||||
```
|
||||
|
||||
## Auto-lock
|
||||
It creates the release for the tag and uploads the installers, the browser helpers and a `SHA256SUMS` file.
|
||||
|
||||
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.
|
||||
## How the browser connection works
|
||||
|
||||
## Sync and onboarding (docs/03, docs/10)
|
||||
```
|
||||
browser extension ─(native messaging)─▶ kestrove-nmh ─(local connection)─▶ Kestrove app
|
||||
└──────────── encrypted end to end with a key you confirm by comparing six words ──────────┘
|
||||
```
|
||||
|
||||
* **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=file`
|
||||
forces 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_NAME` overrides the device name.
|
||||
* **Live test**: `tests/live_sync.rs` (ignored) drives three instances against a running server; see its header.
|
||||
- `kestrove-nmh` is a tiny helper that the browser starts. It only passes encrypted messages along; it can't
|
||||
read them.
|
||||
- The browser has to be told where the helper is: `native-messaging/install.sh` (Linux) and
|
||||
`native-messaging/install.ps1` (Windows) do that, for the extension's id only.
|
||||
- The extension only ever learns logins for the site you're on, and fills only after you click. Saving a new
|
||||
login, and every passkey use, is confirmed in the app.
|
||||
- The same code runs inside the Mac app; it lives in `kestrove-core` (`kv-ffi`'s browser bridge, `kv-ipc`,
|
||||
`kv-nmh`).
|
||||
|
||||
## Roadmap (M3, kestrove-spec/docs/07)
|
||||
- [ ] Unlock with Windows Hello (KeyCredentialManager, TPM) and libsecret on Linux
|
||||
- [x] Persistent vault (`VaultCore::open` in app data)
|
||||
- [x] Sync, device approval and scan-to-join onboarding
|
||||
- [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
|
||||
## Where things are kept
|
||||
|
||||
The vault and the app's files are in your user's app-data folder (`vault.sqlite`, `pairings.json`,
|
||||
`settings.json`), readable only by you. The key that proves this is your device lives in the **TPM** on Windows
|
||||
(or is sealed with your Windows login), and in the **Secret Service** keyring on Linux (or, when there is none,
|
||||
in a private file, which Settings warns about).
|
||||
|
||||
## For developers
|
||||
|
||||
| Path | What it is |
|
||||
|---|---|
|
||||
| `src/` | The window's interface (TypeScript). It only displays things; it never holds keys. |
|
||||
| `src-tauri/src/` | The app (Rust): `main.rs` commands and prompts, `sync.rs` sync and onboarding, `autolock.rs`, `device_key.rs`. |
|
||||
| `src-tauri/examples/test-host.rs` | A stand-in for the app that approves everything automatically, for the browser extension's tests. Never ship it. |
|
||||
| `native-messaging/` | Registering the browser helper. |
|
||||
| `scripts/` | Release builds (`linux.Dockerfile`, `windows.sh`) and `gitea-release.sh`. |
|
||||
|
||||
Useful for testing: `KESTROVE_DATA_DIR=/tmp/kv-b` runs a second, separate instance, and `KESTROVE_DEVICE_NAME`
|
||||
sets the device name. `tests/live_sync.rs` (ignored by default) drives three instances against a running
|
||||
server; see its header.
|
||||
|
||||
The full design is in [`kestrove-spec`](https://gitea.samialabri.com/kestrove/kestrove-spec), especially
|
||||
`docs/05-autofill.md`.
|
||||
|
||||
Reference in New Issue
Block a user