1#[derive(
8 std::fmt::Debug,
9 std::clone::Clone,
10 std::marker::Copy,
11 std::cmp::PartialEq,
12 std::cmp::Eq,
13 std::hash::Hash,
14 serde::Serialize,
15 serde::Deserialize,
16)]
17#[serde(rename_all = "camelCase")]
18pub enum AphPartyRole {
19 HumanPrincipal,
21 AgentSender,
23 NotaryService,
25 ChannelAdapter,
27 RecipientEndpoint,
29}
30
31#[derive(
33 std::fmt::Debug,
34 std::clone::Clone,
35 std::marker::Copy,
36 std::cmp::PartialEq,
37 std::cmp::Eq,
38 std::hash::Hash,
39 serde::Serialize,
40 serde::Deserialize,
41)]
42#[serde(rename_all = "camelCase")]
43pub enum AphOperation {
44 IssueDelegationMandate,
46 IssueCommunicationMandate,
48 Notarize,
50 Transport,
52 Verify,
54 Reject,
56}
57
58impl AphPartyRole {
59 pub fn allowed_operations(&self) -> &'static [AphOperation] {
61 match self {
62 Self::HumanPrincipal => &[
63 AphOperation::IssueDelegationMandate,
64 AphOperation::IssueCommunicationMandate,
65 ],
66 Self::AgentSender => &[AphOperation::IssueCommunicationMandate],
67 Self::NotaryService => &[AphOperation::Notarize, AphOperation::Reject],
68 Self::ChannelAdapter => &[AphOperation::Transport],
69 Self::RecipientEndpoint => &[AphOperation::Verify],
70 }
71 }
72
73 pub fn can_perform(&self, op: AphOperation) -> bool {
75 self.allowed_operations().contains(&op)
76 }
77
78 pub fn all() -> &'static [AphPartyRole] {
80 &[
81 Self::HumanPrincipal,
82 Self::AgentSender,
83 Self::NotaryService,
84 Self::ChannelAdapter,
85 Self::RecipientEndpoint,
86 ]
87 }
88
89 pub fn label(&self) -> &'static str {
91 match self {
92 Self::HumanPrincipal => "Human Principal",
93 Self::AgentSender => "Agent Sender",
94 Self::NotaryService => "Notary Service",
95 Self::ChannelAdapter => "Channel Adapter",
96 Self::RecipientEndpoint => "Recipient Endpoint",
97 }
98 }
99}
100
101impl AphOperation {
102 pub fn all() -> &'static [AphOperation] {
104 &[
105 Self::IssueDelegationMandate,
106 Self::IssueCommunicationMandate,
107 Self::Notarize,
108 Self::Transport,
109 Self::Verify,
110 Self::Reject,
111 ]
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 #[test]
118 fn role_serde_roundtrip_all_variants() {
119 for role in super::AphPartyRole::all() {
123 let json = serde_json::to_string(role).unwrap();
124 let back: super::AphPartyRole = serde_json::from_str(&json).unwrap();
125 std::assert_eq!(*role, back);
126 }
127 }
128
129 #[test]
130 fn operation_serde_roundtrip_all_variants() {
131 for op in super::AphOperation::all() {
135 let json = serde_json::to_string(op).unwrap();
136 let back: super::AphOperation = serde_json::from_str(&json).unwrap();
137 std::assert_eq!(*op, back);
138 }
139 }
140
141 #[test]
142 fn role_serde_uses_camel_case() {
143 let json = serde_json::to_string(&super::AphPartyRole::HumanPrincipal).unwrap();
147 std::assert_eq!(json, "\"humanPrincipal\"");
148 let json = serde_json::to_string(&super::AphPartyRole::RecipientEndpoint).unwrap();
149 std::assert_eq!(json, "\"recipientEndpoint\"");
150 }
151
152 #[test]
153 fn operation_serde_uses_camel_case() {
154 let json = serde_json::to_string(&super::AphOperation::IssueDelegationMandate).unwrap();
157 std::assert_eq!(json, "\"issueDelegationMandate\"");
158 let json = serde_json::to_string(&super::AphOperation::Notarize).unwrap();
159 std::assert_eq!(json, "\"notarize\"");
160 }
161
162 #[test]
163 fn every_operation_assigned_to_at_least_one_role() {
164 for op in super::AphOperation::all() {
168 let assigned = super::AphPartyRole::all()
169 .iter()
170 .any(|r| r.can_perform(*op));
171 std::assert!(assigned, "{:?} is not assigned to any role", op);
172 }
173 }
174
175 #[test]
176 fn human_principal_can_issue_mandates() {
177 let role = super::AphPartyRole::HumanPrincipal;
181 std::assert!(role.can_perform(super::AphOperation::IssueDelegationMandate));
182 std::assert!(role.can_perform(super::AphOperation::IssueCommunicationMandate));
183 std::assert!(!role.can_perform(super::AphOperation::Notarize));
184 std::assert!(!role.can_perform(super::AphOperation::Transport));
185 }
186
187 #[test]
188 fn notary_service_can_notarize_and_reject_only() {
189 let role = super::AphPartyRole::NotaryService;
193 std::assert!(role.can_perform(super::AphOperation::Notarize));
194 std::assert!(role.can_perform(super::AphOperation::Reject));
195 std::assert!(!role.can_perform(super::AphOperation::IssueDelegationMandate));
196 std::assert!(!role.can_perform(super::AphOperation::Transport));
197 std::assert!(!role.can_perform(super::AphOperation::Verify));
198 }
199
200 #[test]
201 fn channel_adapter_can_only_transport() {
202 let role = super::AphPartyRole::ChannelAdapter;
206 std::assert!(role.can_perform(super::AphOperation::Transport));
207 std::assert!(!role.can_perform(super::AphOperation::Notarize));
208 std::assert!(!role.can_perform(super::AphOperation::Verify));
209 std::assert!(!role.can_perform(super::AphOperation::IssueCommunicationMandate));
210 }
211
212 #[test]
213 fn label_non_empty_for_all_roles() {
214 for role in super::AphPartyRole::all() {
218 std::assert!(!role.label().is_empty(), "{:?} has empty label", role);
219 }
220 }
221
222 #[test]
223 fn all_returns_expected_counts() {
224 std::assert_eq!(super::AphPartyRole::all().len(), 5);
228 std::assert_eq!(super::AphOperation::all().len(), 6);
229 }
230}