openagent_auth_protocol/
types.rs1use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
11pub enum ConformanceLevel {
12 #[serde(rename = "L0")]
14 L0,
15 #[serde(rename = "L1")]
17 L1,
18 #[serde(rename = "L2")]
20 L2,
21}
22
23impl ConformanceLevel {
24 pub fn level(&self) -> u8 {
26 match self {
27 Self::L0 => 0,
28 Self::L1 => 1,
29 Self::L2 => 2,
30 }
31 }
32
33 pub fn satisfies(&self, required: &Self) -> bool {
35 self.level() >= required.level()
36 }
37}
38
39impl std::fmt::Display for ConformanceLevel {
40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 match self {
42 Self::L0 => write!(f, "L0"),
43 Self::L1 => write!(f, "L1"),
44 Self::L2 => write!(f, "L2"),
45 }
46 }
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct DidDocument {
52 pub id: String,
54 pub verification_key: String,
56 pub kind: String,
58 #[serde(skip_serializing_if = "Option::is_none")]
60 pub parent: Option<String>,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct LineageProof {
66 pub chain: Vec<LineageLink>,
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct LineageLink {
73 pub from: String,
75 pub to: String,
77 pub signature: String,
79 pub issued_at: String,
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct DiscoveryDocument {
86 pub auth_endpoint: String,
88 pub supported_versions: Vec<u32>,
90 pub server_did: String,
92 pub required_conformance_level: ConformanceLevel,
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn conformance_level_satisfies() {
102 assert!(ConformanceLevel::L2.satisfies(&ConformanceLevel::L0));
103 assert!(ConformanceLevel::L2.satisfies(&ConformanceLevel::L1));
104 assert!(ConformanceLevel::L2.satisfies(&ConformanceLevel::L2));
105 assert!(ConformanceLevel::L1.satisfies(&ConformanceLevel::L0));
106 assert!(!ConformanceLevel::L0.satisfies(&ConformanceLevel::L1));
107 }
108
109 #[test]
110 fn conformance_level_display() {
111 assert_eq!(ConformanceLevel::L0.to_string(), "L0");
112 assert_eq!(ConformanceLevel::L1.to_string(), "L1");
113 assert_eq!(ConformanceLevel::L2.to_string(), "L2");
114 }
115
116 #[test]
117 fn discovery_document_serializes() {
118 let doc = DiscoveryDocument {
119 auth_endpoint: "/.well-known/openagent/auth".into(),
120 supported_versions: vec![1],
121 server_did: "did:oas:l1fe:service:api".into(),
122 required_conformance_level: ConformanceLevel::L2,
123 };
124 let json = serde_json::to_string(&doc);
125 assert!(json.is_ok());
126 let parsed: Result<DiscoveryDocument, _> = serde_json::from_str(&json.unwrap_or_default());
127 assert!(parsed.is_ok());
128 }
129
130 #[test]
131 fn did_document_round_trip() {
132 let doc = DidDocument {
133 id: "did:oas:l1fe:agent:test".into(),
134 verification_key: "z6Mk...".into(),
135 kind: "agent".into(),
136 parent: Some("did:oas:l1fe:hmr:alice".into()),
137 };
138 let json = serde_json::to_string(&doc);
139 assert!(json.is_ok());
140 }
141}