M3: working desktop app + browser pairing channel

- Builds and runs (tauri build --debug); placeholder icons; persistent VaultCore::open in the
  OS app-data dir; Secret Key remembered on the device; tray keeps the app serving the extension.
- Auto-lock: idle (system idle on Windows/macOS, in-app activity on Linux), screen lock, sleep.
- Local IPC for kestrove-nmh: 0700 dir + 0600 Unix socket with peer-uid checks; Windows named
  pipe (first instance, local only, user DACL, client SID check) behind cfg.
- Pairing channel: X25519 → HKDF → 6-word fingerprint confirmed in both UIs, per-connection
  session keys, AES-256-GCM with strict counters. Test vectors shared with kestrove-browser.
- Broker: query/fill/totp/save with origin re-checks; pairing and save prompts in the UI.
- kestrove-nmh relays ciphertext only; native-host installers for Linux/macOS/Windows.
- Tests: unit tests, tests/nmh_stdio.rs (real kestrove-nmh over stdio), examples/test-host.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-16 20:13:54 +09:00
co-authored by Claude Opus 5.5
parent 30cdcee3d2
commit 923c466dea
44 changed files with 9289 additions and 270 deletions
+48
View File
@@ -0,0 +1,48 @@
//! 256 words for pairing fingerprints: one word per byte, 6 words = 48 bits, compared by a person.
//! The same list, in the same order, is in kestrove-browser/src/words.ts.
pub const WORDS: [&str; 256] = [
"acid", "acorn", "actor", "adult", "agent", "alarm", "album", "alley",
"amber", "angle", "ankle", "apple", "april", "apron", "arena", "armor",
"arrow", "atlas", "attic", "audio", "aunt", "autumn", "award", "bacon",
"badge", "bagel", "baker", "bamboo", "banjo", "barn", "basil", "basket",
"beach", "beard", "beetle", "bell", "bench", "berry", "bike", "birch",
"bison", "blade", "blanket", "blimp", "bloom", "boat", "bonus", "boot",
"bottle", "boxer", "brain", "brick", "bridge", "broom", "brush", "bucket",
"bugle", "cabin", "cable", "cactus", "camel", "camera", "canal", "candle",
"canoe", "canyon", "carbon", "cargo", "carpet", "castle", "cedar", "cello",
"chalk", "cherry", "chess", "chief", "cider", "cinema", "circus", "clay",
"cliff", "clock", "cloud", "clover", "cobra", "cocoa", "comet", "coral",
"cotton", "cousin", "coyote", "crane", "crayon", "cricket", "crown", "cup",
"daisy", "dancer", "delta", "denim", "desert", "diary", "diesel", "dingo",
"disco", "doctor", "dolphin", "donkey", "dragon", "drum", "duck", "eagle",
"earth", "easel", "echo", "eclipse", "elbow", "elder", "ember", "emerald",
"engine", "falcon", "fang", "farmer", "feather", "fence", "ferry", "fiddle",
"finch", "flag", "flute", "forest", "fossil", "fox", "frost", "galaxy",
"garden", "garlic", "gecko", "ghost", "ginger", "giraffe", "glacier", "globe",
"goat", "gold", "gorilla", "grape", "gravel", "guitar", "hammer", "harbor",
"harp", "hawk", "hazel", "helmet", "heron", "hiker", "honey", "hornet",
"hotel", "igloo", "index", "iris", "island", "ivory", "jacket", "jaguar",
"jelly", "jewel", "jungle", "kayak", "kettle", "kitten", "koala", "ladder",
"lagoon", "lake", "lantern", "laser", "lemon", "lentil", "lily", "lion",
"lizard", "lobster", "locket", "lotus", "magnet", "mango", "maple", "marble",
"meadow", "melon", "mint", "mirror", "monkey", "moose", "mosaic", "motor",
"mountain", "mulberry", "museum", "napkin", "nectar", "needle", "nickel", "noodle",
"novel", "nugget", "oasis", "ocean", "olive", "onion", "orange", "orbit",
"orchid", "otter", "owl", "oyster", "paddle", "palace", "panda", "paper",
"parrot", "peach", "pebble", "pepper", "piano", "pickle", "pilot", "pine",
"planet", "plum", "poem", "pony", "puzzle", "quartz", "quill", "rabbit",
"radar", "radio", "raven", "ribbon", "river", "robin", "rocket", "rose",
"ruby", "saddle", "salmon", "sandal", "satin", "scarf", "scout", "sugar",
];
#[cfg(test)]
mod tests {
#[test]
fn unique() {
let mut v = super::WORDS.to_vec();
v.sort_unstable();
v.dedup();
assert_eq!(v.len(), 256);
}
}