Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion crates/animus-mcp-oauth/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,16 @@ pub struct ServerResolution {
/// Build a keychain-backed [`SecretStore`] for `project_root`, mirroring the
/// `animus secret` surface so OAuth tokens share the project's keychain
/// scope.
///
/// Consults both the global `~/.animus/config.json` and the project-level
/// `.animus/config.json` for the `secrets` configuration block so that
/// per-project key-source overrides (e.g. `key_source = user-key`) are
/// honored by `mcp auth --complete` and every other OAuth code path.
pub fn build_secret_store(project_root: &Path) -> Result<Arc<dyn SecretStore>, ServerResolutionError> {
let scoped_root = scoped_state_root(project_root)
.ok_or_else(|| ServerResolutionError::NoScopedRoot(project_root.display().to_string()))?;
let scope = resolve_keychain_scope(project_root, &scoped_root);
Ok(Arc::from(orchestrator_core::build_secret_store(&scope, scoped_root)))
Ok(Arc::from(orchestrator_core::build_secret_store_for_project(&scope, scoped_root, project_root)))
}

/// Pick the keychain service-scope string from the adopted scoped state
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ fn keychain_store(project_root: &Path) -> Option<Box<dyn SecretStore>> {
.and_then(|s| s.to_str())
.map(|s| s.to_string())
.unwrap_or_else(|| repository_scope_for_path(project_root));
Some(orchestrator_core::build_secret_store(&scope, scoped_root))
Some(orchestrator_core::build_secret_store_for_project(&scope, scoped_root, project_root))
}

/// True when `name` resolves to a non-empty value in the project secret store.
Expand Down
12 changes: 7 additions & 5 deletions crates/orchestrator-cli/src/services/operations/ops_secret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ pub(crate) async fn handle_secret(
}

/// Copy every secret between backends (keyring <-> device store). Builds both
/// ends explicitly via `build_backend` (independent of the configured default),
/// verifies each copy, and only clears the source when `--remove-source` is set.
/// ends explicitly via `build_backend_for_project` (independent of the configured
/// default), verifies each copy, and only clears the source when `--remove-source`
/// is set. Using the project-aware builder ensures `key_source`/`key_file` from
/// `.animus/config.json` are honored when the device backend is the source or target.
fn handle_migrate(
args: SecretMigrateArgs,
project_root: &Path,
Expand All @@ -61,8 +63,8 @@ fn handle_migrate(
"keyring" => ("device", "keyring"),
other => return Err(anyhow!("unknown migrate target '{other}' (expected: device or keyring)")),
};
let source = orchestrator_core::build_backend(&scope, scoped_root.to_path_buf(), source_name);
let target = orchestrator_core::build_backend(&scope, scoped_root.to_path_buf(), target_name);
let source = orchestrator_core::build_backend_for_project(&scope, scoped_root.to_path_buf(), source_name, project_root);
let target = orchestrator_core::build_backend_for_project(&scope, scoped_root.to_path_buf(), target_name, project_root);

let MigrationOutcome { migrated, remove_failures } =
migrate_secrets(source.as_ref(), target.as_ref(), args.remove_source)?;
Expand Down Expand Up @@ -286,7 +288,7 @@ fn build_store(project_root: &Path) -> Result<Box<dyn SecretStore>> {
let scoped_root = scoped_state_root(project_root)
.ok_or_else(|| anyhow!("could not resolve scoped state root for project at {}", project_root.display()))?;
let scope = resolve_keychain_scope(project_root, &scoped_root);
Ok(orchestrator_core::build_secret_store(&scope, scoped_root))
Ok(orchestrator_core::build_secret_store_for_project(&scope, scoped_root, project_root))
}

/// Pick the keychain service-scope string from the adopted scoped state
Expand Down
2 changes: 1 addition & 1 deletion crates/orchestrator-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ pub use runtime_contract::{
cli_tool_executable, cli_tool_read_only_flag, cli_tool_response_schema_flag, CliCapabilities, CliSessionResumeMode,
CliSessionResumePlan,
};
pub use secret_device_store::{build_backend, build_secret_store, DeviceEncryptedSecretStore};
pub use secret_device_store::{build_backend, build_backend_for_project, build_secret_store, build_secret_store_for_project, DeviceEncryptedSecretStore};
pub use secret_keysource::{KeySource, KeySourceConfig, KeySourceKind};
pub use secret_store::{
enforce_injection_cap, index_path as secrets_index_path, keychain_service_name,
Expand Down
Loading
Loading