use aristo_core::canon::{
CanonClient, CanonError, HttpCanonClient, MockCanonClient, RequestVerifyBody,
};
use crate::{CliError, CliResult};
pub(crate) fn run(canon_id: &str, notes: Option<String>) -> CliResult<()> {
let client: Box<dyn CanonClient> = if let Some(mock) = MockCanonClient::from_env() {
Box::new(mock)
} else {
match aristo_core::auth::resolve_full() {
Ok(creds) => {
let base_url = std::env::var("ARETTA_API_URL")
.unwrap_or_else(|_| creds.server.as_str().to_string());
Box::new(HttpCanonClient::new(base_url, &creds.token))
}
Err(_) => {
return Err(CliError::Other {
message: "canon API requires authentication.\n \
Run `aristo auth login` to sign in.\n \
`aristo canon request-verify` is a paid-tier feature; \
see canon-strategy.md §CS1."
.into(),
exit_code: 1,
});
}
}
};
let body = RequestVerifyBody {
canon_id: canon_id.to_string(),
notes,
};
let response = client.request_verify(&body).map_err(canon_error_to_cli)?;
match response.status.as_str() {
"submitted" => {
println!(
"ok: verification demand signal recorded for `{}`.",
response.canon_id
);
}
"updated" => {
let prev = response.previously_submitted_at.as_deref().unwrap_or("?");
println!(
"ok: verification demand signal updated for `{}` \
(first submitted {prev}).",
response.canon_id
);
}
other => {
println!(
"ok: request-verify returned status `{other}` for `{}`.",
response.canon_id
);
}
}
if let Some(current_backing) = &response.current_backing {
println!(" note: this entry already has backing: {current_backing}");
} else {
println!(
" note: this canon entry has no verification backing yet for your \
scope. Demand signals like yours drive Aretta's verifier-investment \
roadmap."
);
}
Ok(())
}
fn canon_error_to_cli(e: CanonError) -> CliError {
CliError::Other {
message: format!("canon API error: {e}"),
exit_code: 1,
}
}