fix: resolve runtime panic in Linux keychain integration (#32)

* fix: resolve runtime panic in Linux keychain integration

- Convert Linux keychain functions from sync (rt.block_on) to async
- Remove nested runtime panic when called from async context
- Make keychain API consistent across platforms (macOS, Linux, fallback)
- Propagate async through config loading and CLI commands

Fixes panic on Linux during 'ironclaw onboard' at Step 2 (Security).

* fix: await async Config::from_env in test_heartbeat example
This commit is contained in:
bkutasi
2026-02-12 00:15:41 +00:00
committed by GitHub
parent 23de75d75b
commit 45f547c711
9 changed files with 158 additions and 173 deletions
+1 -1
View File
@@ -71,7 +71,7 @@ pub async fn run_config_command(cmd: ConfigCommand) -> anyhow::Result<()> {
/// Bootstrap a DB connection for config commands.
async fn connect_store() -> anyhow::Result<crate::history::Store> {
let config = crate::config::Config::from_env().map_err(|e| anyhow::anyhow!("{}", e))?;
let config = crate::config::Config::from_env().await.map_err(|e| anyhow::anyhow!("{}", e))?;
let store = crate::history::Store::new(&config.database).await?;
store.run_migrations().await?;
Ok(store)
+2 -2
View File
@@ -467,7 +467,7 @@ const DEFAULT_USER_ID: &str = "default";
/// Try to connect to the database store for DB-backed config.
async fn connect_store() -> Option<Store> {
let config = Config::from_env().ok()?;
let config = Config::from_env().await.ok()?;
let store = Store::new(&config.database).await.ok()?;
store.run_migrations().await.ok()?;
Some(store)
@@ -496,7 +496,7 @@ async fn save_servers(
/// Initialize and return the secrets store.
async fn get_secrets_store() -> anyhow::Result<Arc<dyn SecretsStore + Send + Sync>> {
let config = Config::from_env()?;
let config = Config::from_env().await?;
let master_key = config.secrets.master_key().ok_or_else(|| {
anyhow::anyhow!(
+1 -1
View File
@@ -47,7 +47,7 @@ pub async fn run_status_command() -> anyhow::Result<()> {
print!(" Secrets: ");
let secrets_configured = settings.secrets_master_key_source != crate::settings::KeySource::None
|| std::env::var("SECRETS_MASTER_KEY").is_ok()
|| crate::secrets::keychain::has_master_key();
|| crate::secrets::keychain::has_master_key().await;
if secrets_configured {
println!("configured ({:?})", settings.secrets_master_key_source);
} else {
+1 -1
View File
@@ -715,7 +715,7 @@ async fn auth_tool(name: String, dir: Option<PathBuf>, user_id: String) -> anyho
println!();
// Initialize secrets store
let config = Config::from_env()?;
let config = Config::from_env().await?;
let master_key = config.secrets.master_key().ok_or_else(|| {
anyhow::anyhow!(
"SECRETS_MASTER_KEY not set. Run 'ironclaw onboard' first or set it in .env"