Menu
Public repository / 11cb359c85449c1aa6d5e0f3eb805b47d18c063d
AkurAI-DNS / src/models.rs
Latest change 1f985ee57c4d7762e35f4e0bd2fbbfe716bf42ee - feat(domains): audited domain lifecycle - certificate-ready state, transitions, events, customer-safe status (AKURAI-DNS-4) by agent
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum DomainState {
Requested,
Verifying,
Provisioned,
CertificateReady,
Renewing,
Failed,
Retired,
}
impl DomainState {
pub fn as_str(&self) -> &'static str {
match self {
DomainState::Requested => "requested",
DomainState::Verifying => "verifying",
DomainState::Provisioned => "provisioned",
DomainState::CertificateReady => "certificate_ready",
DomainState::Renewing => "renewing",
DomainState::Failed => "failed",
DomainState::Retired => "retired",
}
}
pub fn from_str(s: &str) -> Option<Self> {
match s {
"requested" => Some(DomainState::Requested),
"verifying" => Some(DomainState::Verifying),
"provisioned" => Some(DomainState::Provisioned),
"certificate_ready" => Some(DomainState::CertificateReady),
"renewing" => Some(DomainState::Renewing),
"failed" => Some(DomainState::Failed),
"retired" => Some(DomainState::Retired),
_ => None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DomainOwnership {
pub id: i64,
pub org_id: String,
pub workspace_id: String,
pub domain: String,
pub state: DomainState,
pub verification_token: Option<String>,
pub verified_at: Option<String>,
pub provisioned_at: Option<String>,
pub cert_ready_at: Option<String>,
pub expires_at: Option<String>,
pub last_error: Option<String>,
pub created_at: String,
pub updated_at: String,
}
/// JSON shape for POST /api/domains — only the domain is caller-supplied.
#[derive(Debug, Deserialize)]
pub struct CreateDomainRequest {
pub domain: String,
}
/// JSON shape for POST /api/domains/{id}/verify.
#[derive(Debug, Deserialize)]
pub struct VerifyDomainRequest {
pub token: String,
}
/// JSON shape for POST /api/domains/{id}/fail.
#[derive(Debug, Deserialize)]
pub struct FailDomainRequest {
pub reason: String,
}
/// JSON shape for returning a created or listed domain — the caller's own
/// full tenant-scoped view. Includes the verification token (needed by the
/// caller to prove ownership) but never any other tenant's data.
#[derive(Debug, Serialize)]
pub struct DomainResponse {
pub id: i64,
pub org_id: String,
pub workspace_id: String,
pub domain: String,
pub state: String,
pub verification_token: Option<String>,
pub verified_at: Option<String>,
pub provisioned_at: Option<String>,
pub cert_ready_at: Option<String>,
pub expires_at: Option<String>,
pub last_error: Option<String>,
pub created_at: String,
pub updated_at: String,
}
impl From<DomainOwnership> for DomainResponse {
fn from(d: DomainOwnership) -> Self {
DomainResponse {
id: d.id,
org_id: d.org_id,
workspace_id: d.workspace_id,
domain: d.domain,
state: d.state.as_str().to_string(),
verification_token: d.verification_token,
verified_at: d.verified_at,
provisioned_at: d.provisioned_at,
cert_ready_at: d.cert_ready_at,
expires_at: d.expires_at,
last_error: d.last_error,
created_at: d.created_at,
updated_at: d.updated_at,
}
}
}
/// Customer-safe status view for Platform — never carries the verification
/// token, timestamps beyond `updated_at`, or any zone/DNS-internal detail.
#[derive(Debug, Serialize)]
pub struct DomainStatusResponse {
pub id: i64,
pub domain: String,
pub state: String,
pub updated_at: String,
pub last_error: Option<String>,
}
impl From<DomainOwnership> for DomainStatusResponse {
fn from(d: DomainOwnership) -> Self {
DomainStatusResponse {
id: d.id,
domain: d.domain,
state: d.state.as_str().to_string(),
updated_at: d.updated_at,
last_error: d.last_error,
}
}
}