mirror of
https://github.com/hoornet/vega.git
synced 2026-06-29 21:52:08 -07:00
Add OS keychain for persistent nsec sessions (roadmap #1)
- Rust: store_nsec / load_nsec / delete_nsec Tauri commands via keyring crate (macOS Keychain, Windows Credential Manager, Linux Secret Service) - On nsec login: key is stored in OS keychain keyed by hex pubkey - On startup: restoreSession() auto-loads nsec from keychain and re-establishes the NDK signer — no manual re-login required after restart - On logout: keychain entry is deleted - Graceful degradation: if keychain is unavailable (e.g. Linux without a Secret Service daemon), the app starts logged-out — same UX as before, no crash Also updates ROADMAP.md with 4 new items from the Windows playtest (multi-account switcher, NWC wizard, system tray, zap history view) and reorders the list. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Generated
+18
-1
@@ -1807,6 +1807,16 @@ dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "keyring"
|
||||
version = "3.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eebcc3aff044e5944a8fbaf69eb277d11986064cba30c468730e8b9909fb551c"
|
||||
dependencies = [
|
||||
"log",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kuchikiki"
|
||||
version = "0.8.8-speedreader"
|
||||
@@ -4983,8 +4993,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wrystr"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"keyring",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri",
|
||||
@@ -5138,6 +5149,12 @@ dependencies = [
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
|
||||
|
||||
[[package]]
|
||||
name = "zerotrie"
|
||||
version = "0.2.3"
|
||||
|
||||
@@ -22,4 +22,5 @@ tauri = { version = "2", features = ["devtools"] }
|
||||
tauri-plugin-opener = "2"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
keyring = "3"
|
||||
|
||||
|
||||
+31
-4
@@ -1,14 +1,41 @@
|
||||
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
||||
use keyring::Entry;
|
||||
|
||||
const KEYRING_SERVICE: &str = "wrystr";
|
||||
|
||||
/// Store an nsec in the OS keychain, keyed by pubkey (hex).
|
||||
#[tauri::command]
|
||||
fn greet(name: &str) -> String {
|
||||
format!("Hello, {}! You've been greeted from Rust!", name)
|
||||
fn store_nsec(pubkey: String, nsec: String) -> Result<(), String> {
|
||||
let entry = Entry::new(KEYRING_SERVICE, &pubkey).map_err(|e| e.to_string())?;
|
||||
entry.set_password(&nsec).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
/// Load a stored nsec from the OS keychain. Returns None if no entry exists.
|
||||
#[tauri::command]
|
||||
fn load_nsec(pubkey: String) -> Result<Option<String>, String> {
|
||||
let entry = Entry::new(KEYRING_SERVICE, &pubkey).map_err(|e| e.to_string())?;
|
||||
match entry.get_password() {
|
||||
Ok(nsec) => Ok(Some(nsec)),
|
||||
Err(keyring::Error::NoEntry) => Ok(None),
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete a stored nsec from the OS keychain.
|
||||
#[tauri::command]
|
||||
fn delete_nsec(pubkey: String) -> Result<(), String> {
|
||||
let entry = Entry::new(KEYRING_SERVICE, &pubkey).map_err(|e| e.to_string())?;
|
||||
match entry.delete_credential() {
|
||||
Ok(()) => Ok(()),
|
||||
Err(keyring::Error::NoEntry) => Ok(()), // already gone — that's fine
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.invoke_handler(tauri::generate_handler![greet])
|
||||
.invoke_handler(tauri::generate_handler![store_nsec, load_nsec, delete_nsec])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user