mirror of
https://github.com/outbackdingo/optimclaw.git
synced 2026-08-25 14:53:34 +00:00
fix: wire secrets store into all WASM runtime activation paths (#479)
WASM tools and channels activated at runtime (via web UI or CLI) were missing secrets store wiring, causing credential injection to silently fail. Tools like web-search would get 401s from APIs even though the user had configured their API key. Four bugs fixed: - activate_wasm_tool(): WasmToolLoader created without .with_secrets_store() - register_wasm_from_storage(): hardcoded secrets_store: None - WasmChannelLoader: no secrets_store field at all (added field + builder) - activate_wasm_channel() and startup path: both missed wiring secrets The startup path in app.rs was correct; all runtime paths now match it. Co-authored-by: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
8530f44630
commit
6adf95b6d1
@@ -19,12 +19,14 @@ use crate::channels::wasm::schema::ChannelCapabilitiesFile;
|
||||
use crate::channels::wasm::wrapper::WasmChannel;
|
||||
use crate::db::SettingsStore;
|
||||
use crate::pairing::PairingStore;
|
||||
use crate::secrets::SecretsStore;
|
||||
|
||||
/// Loads WASM channels from the filesystem.
|
||||
pub struct WasmChannelLoader {
|
||||
runtime: Arc<WasmChannelRuntime>,
|
||||
pairing_store: Arc<PairingStore>,
|
||||
settings_store: Option<Arc<dyn SettingsStore>>,
|
||||
secrets_store: Option<Arc<dyn SecretsStore + Send + Sync>>,
|
||||
}
|
||||
|
||||
impl WasmChannelLoader {
|
||||
@@ -38,9 +40,16 @@ impl WasmChannelLoader {
|
||||
runtime,
|
||||
pairing_store,
|
||||
settings_store,
|
||||
secrets_store: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the secrets store for host-based credential injection in WASM channels.
|
||||
pub fn with_secrets_store(mut self, store: Arc<dyn SecretsStore + Send + Sync>) -> Self {
|
||||
self.secrets_store = Some(store);
|
||||
self
|
||||
}
|
||||
|
||||
/// Load a single WASM channel from a file pair.
|
||||
///
|
||||
/// Expects:
|
||||
@@ -127,7 +136,7 @@ impl WasmChannelLoader {
|
||||
.await?;
|
||||
|
||||
// Create the channel
|
||||
let channel = WasmChannel::new(
|
||||
let mut channel = WasmChannel::new(
|
||||
self.runtime.clone(),
|
||||
prepared,
|
||||
capabilities,
|
||||
@@ -135,6 +144,9 @@ impl WasmChannelLoader {
|
||||
self.pairing_store.clone(),
|
||||
self.settings_store.clone(),
|
||||
);
|
||||
if let Some(ref secrets) = self.secrets_store {
|
||||
channel = channel.with_secrets_store(Arc::clone(secrets));
|
||||
}
|
||||
|
||||
tracing::info!(
|
||||
name = name,
|
||||
|
||||
@@ -1804,7 +1804,8 @@ impl ExtensionManager {
|
||||
None
|
||||
};
|
||||
|
||||
let loader = WasmToolLoader::new(Arc::clone(runtime), Arc::clone(&self.tool_registry));
|
||||
let loader = WasmToolLoader::new(Arc::clone(runtime), Arc::clone(&self.tool_registry))
|
||||
.with_secrets_store(Arc::clone(&self.secrets));
|
||||
loader
|
||||
.load_from_files(name, &wasm_path, cap_path_option)
|
||||
.await
|
||||
@@ -1915,7 +1916,8 @@ impl ExtensionManager {
|
||||
Arc::clone(&channel_runtime),
|
||||
Arc::clone(&pairing_store),
|
||||
settings_store,
|
||||
);
|
||||
)
|
||||
.with_secrets_store(Arc::clone(&self.secrets));
|
||||
let loaded = loader
|
||||
.load_from_files(name, &wasm_path, cap_path_option)
|
||||
.await
|
||||
|
||||
+4
-1
@@ -911,11 +911,14 @@ async fn setup_wasm_channels(
|
||||
let pairing_store = Arc::new(PairingStore::new());
|
||||
let settings_store: Option<Arc<dyn ironclaw::db::SettingsStore>> =
|
||||
database.map(|db| Arc::clone(db) as Arc<dyn ironclaw::db::SettingsStore>);
|
||||
let loader = WasmChannelLoader::new(
|
||||
let mut loader = WasmChannelLoader::new(
|
||||
Arc::clone(&runtime),
|
||||
Arc::clone(&pairing_store),
|
||||
settings_store,
|
||||
);
|
||||
if let Some(secrets) = secrets_store {
|
||||
loader = loader.with_secrets_store(Arc::clone(secrets));
|
||||
}
|
||||
|
||||
let results = match loader
|
||||
.load_from_dir(&config.channels.wasm_channels_dir)
|
||||
|
||||
@@ -585,7 +585,7 @@ impl ToolRegistry {
|
||||
limits: None,
|
||||
description: Some(&tool_with_binary.tool.description),
|
||||
schema: Some(tool_with_binary.tool.parameters_schema.clone()),
|
||||
secrets_store: None,
|
||||
secrets_store: self.secrets_store.clone(),
|
||||
oauth_refresh: None,
|
||||
})
|
||||
.await
|
||||
|
||||
Reference in New Issue
Block a user