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,
)
| 173 | /// - Per-server identity name not found in the store. |
| 174 | /// - No default identity set. |
| 175 | pub fn resolve_identity_for_server( |
| 176 | server: &atomic_config::ServerConfig, |
| 177 | ) -> CliResult<atomic_identity::Identity> { |
| 178 | let store = IdentityStore::open_default() |
| 179 | .map_err(|e| CliError::Internal(anyhow::anyhow!("Failed to open identity store: {}", e)))?; |
| 180 | |
| 181 | if let Some(ref identity_name) = server.identity { |
| 182 | // Server profile specifies an identity — use it. |
| 183 | log::debug!( |
| 184 | "Authenticating as '{}' (bound to server profile {})", |
| 185 | identity_name, |
| 186 | server.url.as_deref().unwrap_or("<no url>") |
| 187 | ); |
| 188 | store.load_by_name(identity_name).map_err(|e| { |
| 189 | CliError::Internal(anyhow::anyhow!( |
| 190 | "Identity '{}' specified by server profile not found: {}", |
| 191 | identity_name, |
| 192 | e |
| 193 | )) |
| 194 | }) |
| 195 | } else { |
| 196 | // Fall back to global default identity. |
| 197 | // |
| 198 | // Worth logging loudly: the fallback is silent on the wire, so when |
| 199 | // the default identity is not the one registered with this server the |
| 200 | // only symptom is a 401 from the far end that names no identity at |
| 201 | // all. Saying which identity was chosen, and that it was a fallback, |
| 202 | // is the difference between a one-line fix and a blind hunt. |
| 203 | let identity = store |
| 204 | .get_default() |
| 205 | .map_err(|e| { |
| 206 | CliError::Internal(anyhow::anyhow!("Failed to load default identity: {}", e)) |
| 207 | })? |
| 208 | .ok_or_else(|| { |
| 209 | CliError::Internal(anyhow::anyhow!( |
| 210 | "No default identity set. Create one first:\n \ |
| 211 | atomic identity new <name> --email <email> --set-default" |
| 212 | )) |
| 213 | })?; |
| 214 | log::debug!( |
| 215 | "Server profile {} declares no identity; falling back to the default identity '{}'. \ |
| 216 | Bind one with 'atomic server set-identity <profile> <identity>'.", |
| 217 | server.url.as_deref().unwrap_or("<no url>"), |
| 218 | identity.name |
| 219 | ); |
| 220 | Ok(identity) |
| 221 | } |
| 222 | } |
| 223 | |
| 224 | /// Convenience: map a [`atomic_remote::RemoteError`] to a [`CliError`]. |
| 225 | pub fn remote_err(e: atomic_remote::RemoteError) -> CliError { |
no test coverage detected