Resolve the identity to authenticate as for a given server profile. Resolution order: 1. `server.identity` — a per-server identity override (set when `atomic identity register --identity ` is used). 2. Global default identity from the identity store. Shared by [`build_client_with_org`] and [`build_apex_client`] so the org-scoped and apex-scoped code paths pick the same identity. # Errors
(
server: &atomic_config::ServerConfig,
)
| 245 | /// - Per-server identity name not found in the store. |
| 246 | /// - No default identity set. |
| 247 | pub fn resolve_identity_for_server( |
| 248 | server: &atomic_config::ServerConfig, |
| 249 | ) -> CliResult<atomic_identity::Identity> { |
| 250 | let store = IdentityStore::open_default() |
| 251 | .map_err(|e| CliError::Internal(anyhow::anyhow!("Failed to open identity store: {}", e)))?; |
| 252 | |
| 253 | if let Some(ref identity_name) = server.identity { |
| 254 | // Server profile specifies an identity — use it. |
| 255 | log::debug!( |
| 256 | "Authenticating as '{}' (bound to server profile {})", |
| 257 | identity_name, |
| 258 | server.url.as_deref().unwrap_or("<no url>") |
| 259 | ); |
| 260 | store.load_by_name(identity_name).map_err(|e| { |
| 261 | CliError::Internal(anyhow::anyhow!( |
| 262 | "Identity '{}' specified by server profile not found: {}", |
| 263 | identity_name, |
| 264 | e |
| 265 | )) |
| 266 | }) |
| 267 | } else { |
| 268 | // Fall back to global default identity. |
| 269 | // |
| 270 | // Worth logging loudly: the fallback is silent on the wire, so when |
| 271 | // the default identity is not the one registered with this server the |
| 272 | // only symptom is a 401 from the far end that names no identity at |
| 273 | // all. Saying which identity was chosen, and that it was a fallback, |
| 274 | // is the difference between a one-line fix and a blind hunt. |
| 275 | let identity = store |
| 276 | .get_default() |
| 277 | .map_err(|e| { |
| 278 | CliError::Internal(anyhow::anyhow!("Failed to load default identity: {}", e)) |
| 279 | })? |
| 280 | .ok_or_else(|| { |
| 281 | CliError::Internal(anyhow::anyhow!( |
| 282 | "No default identity set. Create one first:\n \ |
| 283 | atomic identity new <name> --email <email> --set-default" |
| 284 | )) |
| 285 | })?; |
| 286 | log::debug!( |
| 287 | "Server profile {} declares no identity; falling back to the default identity '{}'. \ |
| 288 | Bind one with 'atomic server set-identity <profile> <identity>'.", |
| 289 | server.url.as_deref().unwrap_or("<no url>"), |
| 290 | identity.name |
| 291 | ); |
| 292 | Ok(identity) |
| 293 | } |
| 294 | } |
| 295 | |
| 296 | /// Convenience: map a [`atomic_remote::RemoteError`] to a [`CliError`]. |
| 297 | pub fn remote_err(e: atomic_remote::RemoteError) -> CliError { |
no test coverage detected