use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use time::OffsetDateTime;
use uuid::Uuid;
use crate::internal::domain::{ErrorCode, GatewayError};
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize, JsonSchema)]
pub struct SidecarId(String);
impl SidecarId {
#[must_use]
pub fn new() -> Self {
Self(format!("sidecar-{}", Uuid::now_v7()))
}
#[must_use]
pub fn from_string(value: impl Into<String>) -> Option<Self> {
let value = value.into();
if value.trim().is_empty() {
None
} else {
Some(Self(value))
}
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
}
impl Default for SidecarId {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum SidecarCapability {
BrokerRead,
PaperTrading,
Heartbeat,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct SidecarIdentity {
pub sidecar_id: SidecarId,
pub public_key: String,
#[schemars(with = "String")]
#[serde(with = "time::serde::rfc3339")]
pub created_at: OffsetDateTime,
pub display_name: Option<String>,
pub capabilities: Vec<SidecarCapability>,
}
impl SidecarIdentity {
pub fn new(
public_key: impl Into<String>,
display_name: Option<String>,
) -> Result<Self, GatewayError> {
let public_key = public_key.into();
if public_key.trim().is_empty() {
return Err(GatewayError::new(
ErrorCode::ConfigInvalid,
"Sidecar public key is required",
false,
Some("Provide --public-key with a public key or fingerprint".to_string()),
));
}
Ok(Self {
sidecar_id: SidecarId::new(),
public_key,
created_at: OffsetDateTime::now_utc(),
display_name,
capabilities: vec![SidecarCapability::BrokerRead, SidecarCapability::Heartbeat],
})
}
}