use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct AuthMetadata {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub account_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub workspace_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub organization_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub user_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub plan: Option<String>,
#[serde(default)]
pub route_hints: AuthRouteHints,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub provider_metadata: Option<ProviderAuthMetadata>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct AuthMetadataDefaults {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub organization_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub workspace_id: Option<String>,
#[serde(default)]
pub route_hints: AuthRouteHints,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub provider_metadata: Option<ProviderAuthMetadata>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(tag = "provider", rename_all = "snake_case")]
pub enum AuthRouteHints {
#[default]
None,
OpenAi(Box<OpenAiRouteHints>),
Anthropic(Box<AnthropicRouteHints>),
Google(Box<GoogleRouteHints>),
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(tag = "provider", rename_all = "snake_case")]
pub enum ProviderAuthMetadata {
OpenAi(OpenAiAuthMetadata),
Anthropic(AnthropicAuthMetadata),
Google(GoogleAuthMetadata),
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[non_exhaustive]
pub struct OpenAiRouteHints {}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[non_exhaustive]
pub struct AnthropicRouteHints {}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[non_exhaustive]
pub struct GoogleRouteHints {}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct OpenAiAuthMetadata {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub plan_type: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub user_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub account_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub is_fedramp: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub email: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct AnthropicAuthMetadata {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub subscription_tier: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub aws_region: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub vertex_project_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub vertex_region: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub foundry_deployment: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct GoogleAuthMetadata {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub account_email: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub project_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub region: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub code_assist_tier: Option<String>,
}
#[cfg(test)]
#[allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
mod tests {
use super::*;
#[test]
fn auth_metadata_default_is_empty() {
let m = AuthMetadata::default();
assert!(m.account_id.is_none());
assert_eq!(m.route_hints, AuthRouteHints::None);
assert!(m.provider_metadata.is_none());
}
#[test]
fn route_hints_serde_roundtrip() {
for hints in [
AuthRouteHints::None,
AuthRouteHints::OpenAi(Box::default()),
AuthRouteHints::Anthropic(Box::default()),
AuthRouteHints::Google(Box::default()),
] {
let s = serde_json::to_string(&hints).unwrap();
let back: AuthRouteHints = serde_json::from_str(&s).unwrap();
assert_eq!(back, hints);
}
}
#[test]
fn provider_auth_metadata_roundtrip() {
let m = ProviderAuthMetadata::OpenAi(OpenAiAuthMetadata::default());
let s = serde_json::to_string(&m).unwrap();
let back: ProviderAuthMetadata = serde_json::from_str(&s).unwrap();
assert_eq!(back, m);
}
}