mirror of
https://github.com/block/buzz.git
synced 2026-10-31 14:31:02 +00:00
feat(cli): use Buzz Desktop identity
Signed-off-by: Tom Brow <tomb@block.xyz> Co-authored-by: Codex <noreply@openai.com> Ai-assisted: true
This commit is contained in:
15
Cargo.lock
generated
15
Cargo.lock
generated
@@ -977,6 +977,7 @@ dependencies = [
|
||||
"buzz-core",
|
||||
"buzz-persona",
|
||||
"buzz-sdk",
|
||||
"buzz-secret-store",
|
||||
"buzz-ws-client",
|
||||
"bytes",
|
||||
"chrono",
|
||||
@@ -997,6 +998,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"url",
|
||||
"uuid",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1367,6 +1369,19 @@ dependencies = [
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "buzz-secret-store"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"keyring",
|
||||
"libc",
|
||||
"security-framework 3.7.0",
|
||||
"serde_json",
|
||||
"thiserror 2.0.18",
|
||||
"windows-sys 0.61.2",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "buzz-test-client"
|
||||
version = "0.1.0"
|
||||
|
||||
@@ -22,6 +22,7 @@ members = [
|
||||
"crates/buzz-pairing-cli",
|
||||
"crates/buzz-sdk",
|
||||
"crates/buzz-persona",
|
||||
"crates/buzz-secret-store",
|
||||
"crates/git-credential-nostr",
|
||||
"crates/git-sign-nostr",
|
||||
"crates/buzz-pair-relay",
|
||||
@@ -144,6 +145,7 @@ buzz-audit = { path = "crates/buzz-audit" }
|
||||
buzz-workflow = { path = "crates/buzz-workflow" }
|
||||
buzz-media = { path = "crates/buzz-media" }
|
||||
buzz-sdk = { path = "crates/buzz-sdk" }
|
||||
buzz-secret-store = { path = "crates/buzz-secret-store" }
|
||||
buzz-ws-client = { path = "crates/buzz-ws-client" }
|
||||
buzz-relay-mesh = { path = "crates/buzz-relay-mesh" }
|
||||
buzz-datastore-tracing = { path = "crates/buzz-datastore-tracing" }
|
||||
|
||||
@@ -44,6 +44,7 @@ chrono = { workspace = true }
|
||||
# Typed event builders for all write operations
|
||||
buzz-sdk = { workspace = true }
|
||||
buzz-core = { workspace = true }
|
||||
buzz-secret-store = { workspace = true }
|
||||
|
||||
# Base64 encoding — NIP-98 event serialization for Authorization header
|
||||
base64 = "0.22"
|
||||
@@ -86,6 +87,9 @@ rustls = { version = "0.23", default-features = false, features = ["ring", "std"
|
||||
# Random number generation — full jitter for exponential backoff in with_retry
|
||||
rand = { workspace = true }
|
||||
|
||||
# Clear transient private-key strings after parsing.
|
||||
zeroize = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
# Scratch files for channel-templates.json fixtures in tests
|
||||
tempfile = "3"
|
||||
|
||||
@@ -14,10 +14,19 @@ cargo install --path crates/buzz-cli
|
||||
|---------|------|----------|
|
||||
| `BUZZ_PRIVATE_KEY` | NIP-98 Schnorr signature | Agents with a keypair |
|
||||
|
||||
Use `--use-desktop-identity` to explicitly sign with the identity stored by the
|
||||
signed Buzz Desktop release. The flag is global, does not change relay
|
||||
selection, and cannot be combined with `--private-key` or `BUZZ_PRIVATE_KEY`.
|
||||
The CLI only reads the current secure-storage entry; it never migrates, writes,
|
||||
deletes, generates, or falls back to Desktop's plaintext identity file.
|
||||
|
||||
```bash
|
||||
# Private key identity (NIP-98 signed requests)
|
||||
export BUZZ_PRIVATE_KEY="nsec1..."
|
||||
buzz channels list
|
||||
|
||||
# Signed-in Buzz Desktop identity (global flag goes before the command)
|
||||
env -u BUZZ_PRIVATE_KEY buzz --use-desktop-identity channels list
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -516,7 +516,7 @@ buzz users set-profile 2>&1; echo "exit: $?"
|
||||
# Exit 3: No auth configured
|
||||
env -u BUZZ_PRIVATE_KEY \
|
||||
cargo run -p buzz-cli -- channels list 2>&1; echo "exit: $?"
|
||||
# stderr: {"error":"auth_error","message":"auth error: BUZZ_PRIVATE_KEY is required (use --private-key or set env var)"}
|
||||
# stderr: {"error":"auth_error","message":"auth error: BUZZ_PRIVATE_KEY is required (use --private-key, set the env var, or pass --use-desktop-identity)"}
|
||||
# exit: 3
|
||||
|
||||
# Not-found returns null, not an error (exit 0)
|
||||
@@ -539,8 +539,12 @@ BUZZ_PRIVATE_KEY="nsec1..." buzz channels list | jq .
|
||||
# No auth → exit 3
|
||||
env -u BUZZ_PRIVATE_KEY \
|
||||
cargo run -p buzz-cli -- channels list 2>&1; echo "exit: $?"
|
||||
# stderr: {"error":"auth_error","message":"auth error: BUZZ_PRIVATE_KEY is required (use --private-key or set env var)"}
|
||||
# stderr: {"error":"auth_error","message":"auth error: BUZZ_PRIVATE_KEY is required (use --private-key, set the env var, or pass --use-desktop-identity)"}
|
||||
# exit: 3
|
||||
|
||||
# Signed-in Desktop identity (read-only secure-storage access)
|
||||
env -u BUZZ_PRIVATE_KEY buzz --use-desktop-identity channels list | jq .
|
||||
# Should succeed when the signed Desktop release has an identity stored
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -10,6 +10,7 @@ use client::BuzzClient;
|
||||
use error::CliError;
|
||||
use nostr::Keys;
|
||||
use uuid::Uuid;
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
/// Run the Buzz CLI from raw arguments (including `argv[0]`).
|
||||
///
|
||||
@@ -69,7 +70,7 @@ Buzz CLI — interact with a Buzz relay
|
||||
|
||||
Configuration (flags override env vars):
|
||||
BUZZ_RELAY_URL Relay base URL [default: http://localhost:3000]
|
||||
BUZZ_PRIVATE_KEY Nostr private key (hex or nsec) [required]
|
||||
BUZZ_PRIVATE_KEY Nostr private key (hex or nsec)
|
||||
BUZZ_AUTH_TAG NIP-OA auth tag JSON [optional]
|
||||
|
||||
The 'pack' subcommand runs locally and does not require a relay connection.
|
||||
@@ -86,6 +87,10 @@ struct Cli {
|
||||
#[arg(long, env = "BUZZ_PRIVATE_KEY", hide_env_values = true)]
|
||||
private_key: Option<String>,
|
||||
|
||||
/// Sign with the identity stored by the signed Buzz Desktop release.
|
||||
#[arg(long, conflicts_with = "private_key")]
|
||||
use_desktop_identity: bool,
|
||||
|
||||
/// NIP-OA auth tag JSON (owner attestation). Injected into every signed event.
|
||||
#[arg(long, env = "BUZZ_AUTH_TAG", hide_env_values = true)]
|
||||
auth_tag: Option<String>,
|
||||
@@ -1948,6 +1953,70 @@ fn normalize_auth_tag_input(input: &str) -> String {
|
||||
trimmed.to_owned()
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum PrivateKeyOrigin {
|
||||
Explicit,
|
||||
Desktop,
|
||||
}
|
||||
|
||||
fn desktop_identity_auth_error(error: buzz_secret_store::ReadonlySecretError) -> CliError {
|
||||
use buzz_secret_store::ReadonlySecretError;
|
||||
let message = match error {
|
||||
ReadonlySecretError::LockedOrUnavailable => {
|
||||
"Buzz Desktop secure storage is locked or unavailable; unlock it and retry"
|
||||
}
|
||||
ReadonlySecretError::AccessDenied => "access to the Buzz Desktop identity was denied",
|
||||
ReadonlySecretError::Corrupt => "the Buzz Desktop secure storage entry is corrupt",
|
||||
ReadonlySecretError::Unavailable | ReadonlySecretError::Disabled => {
|
||||
"Buzz Desktop secure storage is unavailable in this environment"
|
||||
}
|
||||
};
|
||||
CliError::Auth(message.to_string())
|
||||
}
|
||||
|
||||
fn resolve_private_key<F>(
|
||||
explicit: Option<String>,
|
||||
use_desktop_identity: bool,
|
||||
load_desktop_identity: F,
|
||||
) -> Result<(Zeroizing<String>, PrivateKeyOrigin), CliError>
|
||||
where
|
||||
F: FnOnce() -> Result<Option<String>, buzz_secret_store::ReadonlySecretError>,
|
||||
{
|
||||
match (explicit, use_desktop_identity) {
|
||||
(Some(_), true) => Err(CliError::Usage(
|
||||
"--use-desktop-identity cannot be combined with --private-key or BUZZ_PRIVATE_KEY"
|
||||
.to_string(),
|
||||
)),
|
||||
(Some(private_key), false) => {
|
||||
Ok((Zeroizing::new(private_key), PrivateKeyOrigin::Explicit))
|
||||
}
|
||||
(None, true) => {
|
||||
let private_key = load_desktop_identity()
|
||||
.map_err(desktop_identity_auth_error)?
|
||||
.ok_or_else(|| {
|
||||
CliError::Auth(
|
||||
"Buzz Desktop identity is missing; sign in to the release app first"
|
||||
.to_string(),
|
||||
)
|
||||
})?;
|
||||
Ok((Zeroizing::new(private_key), PrivateKeyOrigin::Desktop))
|
||||
}
|
||||
(None, false) => Err(CliError::Auth(
|
||||
"BUZZ_PRIVATE_KEY is required (use --private-key, set the env var, or pass --use-desktop-identity)"
|
||||
.to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_private_key(private_key: &str, origin: PrivateKeyOrigin) -> Result<Keys, CliError> {
|
||||
Keys::parse(private_key).map_err(|error| match origin {
|
||||
PrivateKeyOrigin::Explicit => CliError::Key(format!("invalid BUZZ_PRIVATE_KEY: {error}")),
|
||||
PrivateKeyOrigin::Desktop => CliError::Key(format!(
|
||||
"invalid Buzz Desktop identity in secure storage: {error}"
|
||||
)),
|
||||
})
|
||||
}
|
||||
|
||||
async fn run(cli: Cli) -> Result<(), CliError> {
|
||||
let relay_url = client::normalize_relay_url(&cli.relay);
|
||||
|
||||
@@ -1961,11 +2030,13 @@ async fn run(cli: Cli) -> Result<(), CliError> {
|
||||
|
||||
// Auth: private key is required for all relay operations.
|
||||
// The keypair IS the identity — no tokens, no other auth.
|
||||
let private_key_str = cli.private_key.ok_or_else(|| {
|
||||
CliError::Auth("BUZZ_PRIVATE_KEY is required (use --private-key or set env var)".into())
|
||||
})?;
|
||||
let keys = Keys::parse(&private_key_str)
|
||||
.map_err(|e| CliError::Key(format!("invalid BUZZ_PRIVATE_KEY: {e}")))?;
|
||||
let (private_key, private_key_origin) = resolve_private_key(
|
||||
cli.private_key,
|
||||
cli.use_desktop_identity,
|
||||
buzz_secret_store::load_desktop_release_identity,
|
||||
)?;
|
||||
let keys = parse_private_key(private_key.as_str(), private_key_origin)?;
|
||||
drop(private_key);
|
||||
|
||||
// NIP-OA: parse and verify the auth tag if provided.
|
||||
//
|
||||
@@ -2078,6 +2149,108 @@ mod tests {
|
||||
Cli::command().debug_assert();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn desktop_identity_is_an_explicit_global_flag() {
|
||||
let cli = Cli::try_parse_from([
|
||||
"buzz",
|
||||
"--relay",
|
||||
"wss://relay.example",
|
||||
"--use-desktop-identity",
|
||||
"channels",
|
||||
"list",
|
||||
])
|
||||
.expect("desktop identity flag should parse before the command");
|
||||
assert!(cli.use_desktop_identity);
|
||||
assert!(cli.private_key.is_none());
|
||||
assert_eq!(cli.relay, "wss://relay.example");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn desktop_identity_conflicts_with_explicit_private_key_argument() {
|
||||
assert!(Cli::try_parse_from([
|
||||
"buzz",
|
||||
"--use-desktop-identity",
|
||||
"--private-key",
|
||||
"not-a-real-key",
|
||||
"channels",
|
||||
"list",
|
||||
])
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn explicit_private_key_does_not_touch_desktop_storage() {
|
||||
let (key, origin) = resolve_private_key(Some("explicit".to_string()), false, || {
|
||||
panic!("desktop loader must not run for explicit credentials")
|
||||
})
|
||||
.unwrap();
|
||||
assert_eq!(key.as_str(), "explicit");
|
||||
assert_eq!(origin, PrivateKeyOrigin::Explicit);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn desktop_private_key_is_loaded_only_when_requested() {
|
||||
let (key, origin) =
|
||||
resolve_private_key(None, true, || Ok(Some("desktop-secret".to_string()))).unwrap();
|
||||
assert_eq!(key.as_str(), "desktop-secret");
|
||||
assert_eq!(origin, PrivateKeyOrigin::Desktop);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn desktop_identity_and_environment_credentials_are_mutually_exclusive() {
|
||||
let error = resolve_private_key(Some("environment-secret".to_string()), true, || {
|
||||
panic!("ambiguous auth must fail before keychain access")
|
||||
})
|
||||
.unwrap_err();
|
||||
assert!(matches!(error, CliError::Usage(_)));
|
||||
assert!(!error.to_string().contains("environment-secret"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_desktop_identity_is_a_redacted_auth_error() {
|
||||
let error = resolve_private_key(None, true, || Ok(None)).unwrap_err();
|
||||
assert!(matches!(error, CliError::Auth(_)));
|
||||
assert!(error.to_string().contains("identity is missing"));
|
||||
assert_eq!(error::exit_code(&error), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn desktop_storage_failures_are_clear_redacted_auth_errors() {
|
||||
use buzz_secret_store::ReadonlySecretError;
|
||||
|
||||
for (storage_error, expected) in [
|
||||
(ReadonlySecretError::LockedOrUnavailable, "locked"),
|
||||
(ReadonlySecretError::AccessDenied, "denied"),
|
||||
(ReadonlySecretError::Corrupt, "corrupt"),
|
||||
(ReadonlySecretError::Unavailable, "unavailable"),
|
||||
] {
|
||||
let error = resolve_private_key(None, true, || Err(storage_error)).unwrap_err();
|
||||
assert!(matches!(error, CliError::Auth(_)));
|
||||
assert!(error.to_string().contains(expected), "{error}");
|
||||
assert_eq!(error::exit_code(&error), 3);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_all_auth_keeps_a_safe_failure() {
|
||||
let error = resolve_private_key(None, false, || {
|
||||
panic!("desktop loader must not run without explicit opt-in")
|
||||
})
|
||||
.unwrap_err();
|
||||
assert!(matches!(error, CliError::Auth(_)));
|
||||
assert_eq!(error::exit_code(&error), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_desktop_credential_is_a_redacted_key_error() {
|
||||
let invalid_secret = "not-a-valid-secret";
|
||||
let error = parse_private_key(invalid_secret, PrivateKeyOrigin::Desktop).unwrap_err();
|
||||
assert!(matches!(error, CliError::Key(_)));
|
||||
assert!(error.to_string().contains("invalid Buzz Desktop identity"));
|
||||
assert!(!error.to_string().contains(invalid_secret));
|
||||
assert_eq!(error::exit_code(&error), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_status_clear_rejects_text_and_emoji() {
|
||||
for extra in [["--text", "busy"], ["--emoji", "🎶"]] {
|
||||
|
||||
31
crates/buzz-cli/tests/desktop_identity_args.rs
Normal file
31
crates/buzz-cli/tests/desktop_identity_args.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
use std::process::Command;
|
||||
|
||||
#[test]
|
||||
fn desktop_identity_conflicts_with_environment_private_key() {
|
||||
let secret = "environment-secret-must-stay-redacted";
|
||||
let output = Command::new(env!("CARGO_BIN_EXE_buzz"))
|
||||
.env("BUZZ_PRIVATE_KEY", secret)
|
||||
.arg("--use-desktop-identity")
|
||||
.args(["channels", "list"])
|
||||
.output()
|
||||
.expect("run buzz CLI");
|
||||
|
||||
assert_eq!(output.status.code(), Some(1));
|
||||
let stderr = String::from_utf8(output.stderr).expect("stderr is UTF-8");
|
||||
assert!(stderr.contains("cannot be used with"), "{stderr}");
|
||||
assert!(!stderr.contains(secret));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_explicit_auth_does_not_discover_desktop_identity() {
|
||||
let output = Command::new(env!("CARGO_BIN_EXE_buzz"))
|
||||
.env_remove("BUZZ_PRIVATE_KEY")
|
||||
.args(["channels", "list"])
|
||||
.output()
|
||||
.expect("run buzz CLI");
|
||||
|
||||
assert_eq!(output.status.code(), Some(3));
|
||||
let stderr = String::from_utf8(output.stderr).expect("stderr is UTF-8");
|
||||
assert!(stderr.contains("BUZZ_PRIVATE_KEY is required"), "{stderr}");
|
||||
assert!(!stderr.contains("Desktop identity is missing"));
|
||||
}
|
||||
31
crates/buzz-secret-store/Cargo.toml
Normal file
31
crates/buzz-secret-store/Cargo.toml
Normal file
@@ -0,0 +1,31 @@
|
||||
[package]
|
||||
name = "buzz-secret-store"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
description = "Platform secure storage shared by Buzz clients"
|
||||
|
||||
[features]
|
||||
default = ["system-keyring"]
|
||||
system-keyring = ["dep:keyring", "dep:security-framework"]
|
||||
|
||||
[dependencies]
|
||||
serde_json = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
zeroize = { workspace = true }
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
libc = "0.2"
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
keyring = { version = "3.6.3", default-features = false, features = ["sync-secret-service", "vendored"], optional = true }
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
keyring = { version = "3.6.3", default-features = false, features = ["apple-native", "vendored"], optional = true }
|
||||
security-framework = { version = "3.7.0", features = ["OSX_10_15"], optional = true }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
keyring = { version = "3.6.3", default-features = false, features = ["windows-native", "vendored"], optional = true }
|
||||
windows-sys = { version = "0.61", features = ["Win32_Foundation", "Win32_Security", "Win32_System_Threading"] }
|
||||
1481
crates/buzz-secret-store/src/lib.rs
Normal file
1481
crates/buzz-secret-store/src/lib.rs
Normal file
File diff suppressed because it is too large
Load Diff
16
desktop/src-tauri/Cargo.lock
generated
16
desktop/src-tauri/Cargo.lock
generated
@@ -1095,6 +1095,7 @@ dependencies = [
|
||||
"buzz-media",
|
||||
"buzz-persona",
|
||||
"buzz-sdk",
|
||||
"buzz-secret-store",
|
||||
"buzz-terminal",
|
||||
"buzz-voice",
|
||||
"bytes",
|
||||
@@ -1111,7 +1112,6 @@ dependencies = [
|
||||
"image",
|
||||
"infer",
|
||||
"iroh",
|
||||
"keyring",
|
||||
"libc",
|
||||
"mesh-llm-client",
|
||||
"mesh-llm-events",
|
||||
@@ -1137,7 +1137,6 @@ dependencies = [
|
||||
"rubato",
|
||||
"rusqlite",
|
||||
"rustls",
|
||||
"security-framework 3.7.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
@@ -1225,6 +1224,19 @@ dependencies = [
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "buzz-secret-store"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"keyring",
|
||||
"libc",
|
||||
"security-framework 3.7.0",
|
||||
"serde_json",
|
||||
"thiserror 2.0.18",
|
||||
"windows-sys 0.61.2",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "buzz-terminal"
|
||||
version = "0.1.0"
|
||||
|
||||
@@ -26,7 +26,7 @@ default = ["system-keyring"]
|
||||
mesh-llm = ["dep:iroh", "dep:mesh-llm-sdk", "dep:mesh-llm-host-runtime", "dep:mesh-llm-client", "dep:mesh-llm-node", "dep:mesh-llm-system", "dep:mesh-llm-events"]
|
||||
# OS keyring backing for desktop secret storage (nsec private keys). When
|
||||
# disabled, secrets fall back to 0o600 files. On by default for real builds.
|
||||
system-keyring = ["dep:keyring"]
|
||||
system-keyring = ["buzz-secret-store/system-keyring"]
|
||||
|
||||
[build-dependencies]
|
||||
base64 = "0.22"
|
||||
@@ -39,7 +39,6 @@ libc = "0.2"
|
||||
ctrlc = { version = "3", features = ["termination"] }
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
keyring = { version = "3.6.3", default-features = false, features = ["sync-secret-service", "vendored"], optional = true }
|
||||
# Used directly (alongside tauri-plugin-notification) so we can hold the posting
|
||||
# D-Bus connection open. GNOME 46+ dismisses a notification the moment that
|
||||
# connection is dropped, which the plugin does immediately. Default features
|
||||
@@ -56,15 +55,12 @@ objc2 = { version = "0.6.4", default-features = false }
|
||||
objc2-app-kit = { version = "0.3.2", default-features = false, features = ["NSEvent", "NSHapticFeedback", "NSMenu", "NSMenuItem", "NSStatusItem", "block2"] }
|
||||
objc2-foundation = { version = "0.3.2", default-features = false, features = ["NSDictionary", "NSError", "NSBundle", "NSObject", "NSProcessInfo", "NSString"] }
|
||||
objc2-user-notifications = { version = "0.3.2", default-features = false, features = ["block2", "UNNotification", "UNNotificationContent", "UNNotificationRequest", "UNNotificationResponse", "UNNotificationSettings", "UNNotificationTrigger", "UNUserNotificationCenter"] }
|
||||
keyring = { version = "3.6.3", default-features = false, features = ["apple-native", "vendored"], optional = true }
|
||||
security-framework = { version = "3.7.0", features = ["OSX_10_15"] }
|
||||
window-vibrancy = "0.6"
|
||||
user-idle = { version = "0.6", default-features = false }
|
||||
plist = "1"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows-sys = { version = "0.61", features = ["Win32_Security", "Win32_Storage_FileSystem", "Win32_System_JobObjects", "Win32_System_Registry", "Win32_System_Threading", "Win32_Foundation"] }
|
||||
keyring = { version = "3.6.3", default-features = false, features = ["windows-native", "vendored"], optional = true }
|
||||
user-idle = { version = "0.6", default-features = false }
|
||||
|
||||
[dependencies]
|
||||
@@ -105,6 +101,7 @@ url = "2"
|
||||
buzz_core_pkg = { package = "buzz-core", path = "../../crates/buzz-core" }
|
||||
buzz_persona_pkg = { package = "buzz-persona", path = "../../crates/buzz-persona" }
|
||||
buzz_sdk_pkg = { package = "buzz-sdk", path = "../../crates/buzz-sdk" }
|
||||
buzz-secret-store = { path = "../../crates/buzz-secret-store", default-features = false }
|
||||
buzz_agent_pkg = { package = "buzz-agent", path = "../../crates/buzz-agent" }
|
||||
buzz_voice_pkg = { package = "buzz-voice", path = "../../crates/buzz-voice" }
|
||||
buzz_terminal = { package = "buzz-terminal", path = "crates/buzz-terminal" }
|
||||
|
||||
@@ -13,12 +13,12 @@ pub(crate) fn keyring_service() -> &'static str {
|
||||
.get_or_init(|| dev_keyring_service(std::env::var("BUZZ_DEV_KEYRING_SERVICE").ok()))
|
||||
.as_str()
|
||||
} else {
|
||||
"buzz-desktop"
|
||||
buzz_secret_store::DESKTOP_RELEASE_SERVICE
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn migration_marker_name(service: &str, default_name: &str) -> String {
|
||||
if service == "buzz-desktop" || service == "buzz-desktop-dev" {
|
||||
if service == buzz_secret_store::DESKTOP_RELEASE_SERVICE || service == "buzz-desktop-dev" {
|
||||
default_name.to_string()
|
||||
} else {
|
||||
format!("identity.{service}.migrated")
|
||||
|
||||
@@ -481,7 +481,8 @@ pub fn migrate_agent_keys_to_dev_service(app: &tauri::AppHandle) {
|
||||
// A fresh non-singleton store for the prod service — its own empty
|
||||
// cache so reads go to the OS keyring without polluting the dev
|
||||
// singleton's cache.
|
||||
let prod_store = crate::secret_store::SecretStore::keyring("buzz-desktop");
|
||||
let prod_store =
|
||||
crate::secret_store::SecretStore::keyring(buzz_secret_store::DESKTOP_RELEASE_SERVICE);
|
||||
let dev_store = crate::secret_store::SecretStore::shared(keyring_service());
|
||||
copy_agent_keys_between_stores(&pubkeys, &prod_store, dev_store);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user