koi_common/integration.rs
1//! Integration traits for cross-crate abstractions.
2//!
3//! These traits define contracts that domain crates implement
4//! and the binary crate wires together, without domain crates
5//! importing each other.
6//!
7//! Domain crates depend only on `koi-common`, never on each other.
8//! The binary crate (or `koi-embedded`) provides bridge implementations
9//! that wrap concrete domain cores and implement these traits.
10
11use std::collections::HashMap;
12use std::net::IpAddr;
13
14use chrono::{DateTime, Utc};
15use serde::{Deserialize, Serialize};
16
17use crate::types::ServiceRecord;
18
19// ── Status reporter ────────────────────────────────────────────────
20
21/// Trait for types that can report a capability status summary.
22///
23/// Each domain core implements this so the binary crate can
24/// build a unified status view without coupling domains.
25pub trait StatusReporter: Send + Sync {
26 /// Machine-readable capability name (e.g. "mdns", "dns", "health").
27 fn capability_name(&self) -> &'static str;
28
29 /// Whether the capability is currently operational.
30 fn is_running(&self) -> bool;
31
32 /// Optional human-readable status detail.
33 fn status_detail(&self) -> Option<String> {
34 None
35 }
36}
37
38// ── Summary types ──────────────────────────────────────────────────
39
40/// Summary of a certmesh member, projected through the trait boundary.
41#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct MemberSummary {
43 pub hostname: String,
44 pub sans: Vec<String>,
45 pub cert_expires: Option<DateTime<Utc>>,
46 pub last_seen: Option<DateTime<Utc>>,
47 pub status: String,
48 pub proxy_entries: Vec<ProxyConfigSummary>,
49}
50
51/// Proxy configuration entry projected through the trait boundary.
52#[derive(Debug, Clone, Serialize, Deserialize)]
53pub struct ProxyConfigSummary {
54 pub name: String,
55 pub listen_port: u16,
56 pub backend: String,
57 pub allow_remote: bool,
58}
59
60/// Lightweight proxy entry used by health checks.
61#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct ProxyEntrySummary {
63 pub name: String,
64 pub listen_port: u16,
65 pub backend: String,
66}
67
68// ── Cross-domain traits ────────────────────────────────────────────
69
70/// Read-only snapshot of the certmesh roster.
71pub trait CertmeshSnapshot: Send + Sync {
72 /// Return summaries of all active members.
73 fn active_members(&self) -> Vec<MemberSummary>;
74}
75
76/// Read-only snapshot of mDNS network state.
77pub trait MdnsSnapshot: Send + Sync {
78 /// Map of hostname → IP derived from mDNS service records.
79 fn host_ips(&self) -> HashMap<String, IpAddr>;
80
81 /// All cached mDNS service records (for DNS alias building).
82 fn cached_records(&self) -> Vec<ServiceRecord>;
83}
84
85/// Resolve a local DNS name without importing the DNS crate.
86pub trait DnsProbe: Send + Sync {
87 /// Resolve a local name to IP addresses (A or AAAA).
88 fn resolve_local(&self, name: &str) -> Option<Vec<IpAddr>>;
89}
90
91/// Read-only snapshot of proxy entries.
92pub trait ProxySnapshot: Send + Sync {
93 /// Return all configured proxy entries.
94 fn entries(&self) -> Vec<ProxyEntrySummary>;
95}
96
97/// Write-back channel for DNS alias feedback to certmesh.
98///
99/// When the DNS resolver discovers mDNS aliases, it can push them
100/// to certmesh so that certificates include the correct SANs.
101pub trait AliasFeedback: Send + Sync {
102 /// Record that `hostname` should have `alias` as a SAN.
103 fn record_alias(&self, hostname: &str, alias: &str);
104}