Skip to main content

wist_api/enrollment/
mod.rs

1//! `agent/enroll` 与 `agent/credentials:renew` 两条 edge seam 的报文。
2//!
3//! 这是**跨进程 seam 报文**的唯一一份定义:网关(接收端)与 agentd(发送端)都 `use` 这里,
4//! 不再各自复制。报文引用的**领域类型**(`HostProfile` / `AgentIdentity` / `CredentialBundle`
5//! / `InitialConfig` / `PolicyBinding`)是两侧共同底座,仍留在 `wist-contracts`;这里 re-export,
6//! 调用方可以从 `wist_api::enrollment` 一处取齐整条 seam。
7//!
8//! ## 版本并存约定(v1 / v2 …)
9//!
10//! 一条 seam 的**每一版**是独立一组 `{route, req, resp}`:各自一个版本子模块(`v1`、`v2`…)
11//! 与各自的 handler。**不**用一个结构体 + `api_version` 分支硬扛两版。
12//!
13//! - **非加性(breaking)变更** → 新开一版 + 新路由(`/api/v2/…`);老版本子模块**冻结、只增不删**。
14//! - **纯加字段** → 才在同版本内演进,并按 `upgrade-order.md` §4 **接收端先升**
15//!   (其余情况接收端多为 `deny_unknown_fields`,非加性一律走新版本)。
16//! - `CURRENT` 指出新代码该用的版本;**路由并存 / 版本协商**留待真正出现 v2 时再接。
17//!
18//! 约定详见 `wist-design/doc/design/foundation/api-seam-inventory.md` §7。
19
20/// 版本无关的**领域类型**(被多条 seam 复用),来自 `wist-contracts`。
21pub use wist_contracts::enrollment::{
22    AgentIdentity, AgentIdentityStatus, CredentialBundle, HostProfile, InitialConfig, PolicyBinding,
23};
24
25pub mod v1;
26pub use v1::*;
27
28/// 当前线上版本。新代码从这里取版本口径;并存期由路由/协商决定。
29pub const CURRENT: &str = v1::API_VERSION;
30
31#[cfg(test)]
32mod tests {
33    use super::*;
34
35    /// `CURRENT` 必须与 v1 报文里填的 `api_version` 一致(不至两处各说各话)。
36    #[test]
37    fn current_matches_the_live_wire_version() {
38        let request = v1::EnrollmentRequest::new(
39            "t".to_string(),
40            "cr".to_string(),
41            "csr".to_string(),
42            HostProfile {
43                node_id: "n".to_string(),
44                hostname: "h".to_string(),
45                os: "linux".to_string(),
46                arch: "x86_64".to_string(),
47                machine_id: "m".to_string(),
48                cloud_instance_id: None,
49                k8s_node_uid: None,
50                ip_addresses: vec![],
51            },
52            "caps".to_string(),
53            "2026-09-28T00:00:00Z".to_string(),
54        );
55        assert_eq!(request.api_version, CURRENT);
56    }
57
58    /// 编译期身份断言:本模块 re-export 的领域类型**就是** `wist-contracts` 的那几个
59    /// (若有人另抄一份,下面的函数体将类型不匹配而编译失败)。
60    #[test]
61    fn domain_types_are_the_contracts_ones() {
62        #[allow(dead_code)]
63        fn assert_identity() {
64            fn host(v: wist_contracts::enrollment::HostProfile) -> HostProfile {
65                v
66            }
67            fn agent(v: wist_contracts::enrollment::AgentIdentity) -> AgentIdentity {
68                v
69            }
70            fn agent_status(
71                v: wist_contracts::enrollment::AgentIdentityStatus,
72            ) -> AgentIdentityStatus {
73                v
74            }
75            fn cred(v: wist_contracts::enrollment::CredentialBundle) -> CredentialBundle {
76                v
77            }
78            fn init(v: wist_contracts::enrollment::InitialConfig) -> InitialConfig {
79                v
80            }
81            fn policy(v: wist_contracts::enrollment::PolicyBinding) -> PolicyBinding {
82                v
83            }
84            let _ = (host, agent, agent_status, cred, init, policy);
85        }
86        assert_identity();
87    }
88}