nixfleet_proto/
revocations.rs1use chrono::{DateTime, Utc};
5use serde::{Deserialize, Serialize};
6
7use crate::fleet_resolved::Meta;
8
9#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
10#[serde(rename_all = "camelCase")]
11pub struct Revocations {
12 pub schema_version: u32,
13 pub revocations: Vec<RevocationEntry>,
15 pub meta: Meta,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
19#[serde(rename_all = "camelCase")]
20pub struct RevocationEntry {
21 pub hostname: String,
22 pub not_before: DateTime<Utc>,
25 #[serde(default)]
26 pub reason: Option<String>,
27 #[serde(default)]
28 pub revoked_by: Option<String>,
29}
30
31#[cfg(test)]
32mod tests {
33 use super::*;
34
35 fn meta_v1() -> Meta {
36 Meta {
37 schema_version: 1,
38 signed_at: Some("2026-04-28T10:00:00Z".parse().unwrap()),
39 ci_commit: Some("abc12345".into()),
40 signature_algorithm: Some("ed25519".into()),
41 }
42 }
43
44 #[test]
45 fn empty_revocations_round_trip() {
46 let r = Revocations {
47 schema_version: 1,
48 revocations: vec![],
49 meta: meta_v1(),
50 };
51 let s = serde_json::to_string(&r).unwrap();
52 let parsed: Revocations = serde_json::from_str(&s).unwrap();
53 assert_eq!(parsed, r);
54 }
55
56 #[test]
57 fn revocation_entry_round_trip() {
58 let r = Revocations {
59 schema_version: 1,
60 revocations: vec![RevocationEntry {
61 hostname: "old-laptop".into(),
62 not_before: "2026-04-26T00:00:00Z".parse().unwrap(),
63 reason: Some("decommissioned".into()),
64 revoked_by: Some("operator".into()),
65 }],
66 meta: meta_v1(),
67 };
68 let s = serde_json::to_string(&r).unwrap();
69 let parsed: Revocations = serde_json::from_str(&s).unwrap();
70 assert_eq!(parsed, r);
71 }
72
73 #[test]
74 fn revocation_entry_optional_fields_default_to_none() {
75 let json = r#"{
76 "hostname": "old-laptop",
77 "notBefore": "2026-04-26T00:00:00Z"
78 }"#;
79 let entry: RevocationEntry = serde_json::from_str(json).unwrap();
80 assert_eq!(entry.hostname, "old-laptop");
81 assert!(entry.reason.is_none());
82 assert!(entry.revoked_by.is_none());
83 }
84}