Skip to main content

alien_core/deployment/
domain.rs

1//! Domain, certificate, and DNS metadata for auto-managed public resources.
2
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6/// Certificate status in the certificate lifecycle
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
8#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
9#[serde(rename_all = "kebab-case")]
10pub enum CertificateStatus {
11    Pending,
12    Issued,
13    Renewing,
14    RenewalFailed,
15    Failed,
16    Deleting,
17}
18
19/// DNS record status in the DNS lifecycle
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
21#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
22#[serde(rename_all = "lowercase")]
23pub enum DnsRecordStatus {
24    Pending,
25    Active,
26    Updating,
27    Deleting,
28    Failed,
29}
30
31/// Certificate and DNS metadata for a managed hostname.
32///
33/// Includes decrypted certificate data for issued certificates.
34/// Private keys are deployment-scoped secrets (like environment variables).
35#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
36#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
37#[serde(rename_all = "camelCase")]
38pub struct ManagedDomainInfo {
39    /// Fully qualified domain name.
40    pub fqdn: String,
41    /// Certificate ID (for tracking/logging).
42    pub certificate_id: String,
43    /// Current certificate status
44    pub certificate_status: CertificateStatus,
45    /// Current DNS record status
46    pub dns_status: DnsRecordStatus,
47    /// Last DNS error message. Present when DNS previously failed, even if status
48    /// was reset to pending for retry. Used to surface actionable error context
49    /// in WaitingForDns failure messages.
50    #[serde(skip_serializing_if = "Option::is_none")]
51    pub dns_error: Option<String>,
52    /// Full PEM certificate chain (only present if status is "issued").
53    #[serde(skip_serializing_if = "Option::is_none")]
54    pub certificate_chain: Option<String>,
55    /// Decrypted private key (only present if status is "issued").
56    #[serde(skip_serializing_if = "Option::is_none")]
57    pub private_key: Option<String>,
58    /// ISO 8601 timestamp when certificate was issued (for renewal detection).
59    #[serde(skip_serializing_if = "Option::is_none")]
60    pub issued_at: Option<String>,
61}
62
63/// Certificate and DNS metadata for a public endpoint.
64pub type PublicEndpointDomainInfo = ManagedDomainInfo;
65
66/// Certificate and DNS metadata for a public resource.
67///
68/// The direct fields describe the primary endpoint hostname. `endpoints`
69/// contains endpoint-scoped metadata keyed by endpoint name. `aliases` contains
70/// additional managed hostnames that route directly to the primary endpoint.
71#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
72#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
73#[serde(rename_all = "camelCase")]
74pub struct ResourceDomainInfo {
75    /// Fully qualified domain name.
76    pub fqdn: String,
77    /// Certificate ID (for tracking/logging).
78    pub certificate_id: String,
79    /// Current certificate status
80    pub certificate_status: CertificateStatus,
81    /// Current DNS record status
82    pub dns_status: DnsRecordStatus,
83    /// Last DNS error message.
84    #[serde(skip_serializing_if = "Option::is_none")]
85    pub dns_error: Option<String>,
86    /// Full PEM certificate chain (only present if status is "issued").
87    #[serde(skip_serializing_if = "Option::is_none")]
88    pub certificate_chain: Option<String>,
89    /// Decrypted private key (only present if status is "issued").
90    #[serde(skip_serializing_if = "Option::is_none")]
91    pub private_key: Option<String>,
92    /// ISO 8601 timestamp when certificate was issued (for renewal detection).
93    #[serde(skip_serializing_if = "Option::is_none")]
94    pub issued_at: Option<String>,
95    /// Endpoint-scoped metadata keyed by endpoint name.
96    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
97    pub endpoints: HashMap<String, PublicEndpointDomainInfo>,
98    /// Additional managed hostnames for the resource.
99    #[serde(default, skip_serializing_if = "Vec::is_empty")]
100    pub aliases: Vec<ManagedDomainInfo>,
101}
102
103/// Domain metadata for auto-managed public resources (no private keys).
104#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
105#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
106#[serde(rename_all = "camelCase")]
107pub struct DomainMetadata {
108    /// Base domain for auto-generated domains (e.g., "vpc.direct").
109    pub base_domain: String,
110    /// Deployment public subdomain (e.g., "k8f2j3").
111    pub public_subdomain: String,
112    /// Hosted zone ID for DNS records.
113    pub hosted_zone_id: String,
114    /// Metadata per resource ID.
115    pub resources: HashMap<String, ResourceDomainInfo>,
116}