use std::collections::HashMap;
use axum::{
Json,
extract::{Path, Query, State},
http::StatusCode,
http::header,
response::IntoResponse,
};
use chrono::{Duration, Utc};
use serde::Deserialize;
use serde_json::{Value, json};
use crate::config_runtime;
use ironclad_agent::policy::{PolicyContext, ToolCallRequest};
use ironclad_core::{
InputAuthority, IroncladConfig, IroncladError, PolicyDecision, SurvivalTier,
input_capability_scan,
};
use super::{
AppState, JsonError, bad_request, internal_err, not_found, sanitize_html, validate_field,
validate_short,
};
pub(crate) enum KeySource {
NotRequired,
OAuth,
Keystore(String),
EnvVar(String),
Missing,
}
impl KeySource {
pub fn status_pair(&self) -> (&'static str, &'static str) {
match self {
Self::NotRequired => ("not_required", "local"),
Self::OAuth => ("configured", "oauth"),
Self::Keystore(_) => ("configured", "keystore"),
Self::EnvVar(_) => ("configured", "env"),
Self::Missing => ("missing", "none"),
}
}
}
fn resolve_key_source(
provider_name: &str,
is_local: bool,
api_key_ref: Option<&str>,
api_key_env: Option<&str>,
auth_mode: Option<&str>,
keystore: &ironclad_core::keystore::Keystore,
) -> KeySource {
if is_local {
return KeySource::NotRequired;
}
if auth_mode.is_some_and(|m| m == "oauth") {
return KeySource::OAuth;
}
if let Some(ks_name) = api_key_ref.and_then(|r| r.strip_prefix("keystore:"))
&& let Some(val) = keystore.get(ks_name)
{
return KeySource::Keystore(val);
}
let conventional = format!("{provider_name}_api_key");
if let Some(val) = keystore.get(&conventional)
&& !val.is_empty()
{
return KeySource::Keystore(val);
}
if let Some(env_name) = api_key_env
&& let Ok(val) = std::env::var(env_name)
&& !val.is_empty()
{
return KeySource::EnvVar(val);
}
KeySource::Missing
}
pub(crate) async fn resolve_provider_key(
provider_name: &str,
is_local: bool,
auth_mode: &str,
api_key_ref: Option<&str>,
api_key_env: &str,
oauth: &ironclad_llm::OAuthManager,
keystore: &ironclad_core::keystore::Keystore,
) -> Option<String> {
let source = resolve_key_source(
provider_name,
is_local,
api_key_ref,
Some(api_key_env),
Some(auth_mode),
keystore,
);
match source {
KeySource::NotRequired | KeySource::Missing => None,
KeySource::OAuth => oauth.resolve_token(provider_name).await
.inspect_err(|e| tracing::warn!(error = %e, provider = provider_name, "OAuth token resolution failed"))
.ok(),
KeySource::Keystore(v) | KeySource::EnvVar(v) => Some(v),
}
}
pub(crate) fn check_key_status(
provider_name: &str,
is_local: bool,
api_key_ref: Option<&str>,
api_key_env: Option<&str>,
auth_mode: Option<&str>,
keystore: &ironclad_core::keystore::Keystore,
) -> (&'static str, &'static str) {
resolve_key_source(
provider_name,
is_local,
api_key_ref,
api_key_env,
auth_mode,
keystore,
)
.status_pair()
}
include!("admin/approvals.rs");
include!("admin/config_models.rs");
include!("admin/metrics.rs");
include!("admin/revenue.rs");
include!("admin/runtime_health.rs");
include!("admin/operator_tools.rs");
include!("admin/workspace_agents.rs");
include!("admin/advanced_ops.rs");
#[cfg(test)]
mod tests;