1use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
10#[serde(rename_all = "snake_case")]
11pub enum CosoComponent {
12 ControlEnvironment,
15 RiskAssessment,
18 ControlActivities,
21 InformationCommunication,
25 MonitoringActivities,
29}
30
31impl std::fmt::Display for CosoComponent {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 match self {
34 Self::ControlEnvironment => write!(f, "Control Environment"),
35 Self::RiskAssessment => write!(f, "Risk Assessment"),
36 Self::ControlActivities => write!(f, "Control Activities"),
37 Self::InformationCommunication => write!(f, "Information & Communication"),
38 Self::MonitoringActivities => write!(f, "Monitoring Activities"),
39 }
40 }
41}
42
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
52#[serde(rename_all = "snake_case")]
53pub enum CosoPrinciple {
54 IntegrityAndEthics,
58 BoardOversight,
61 OrganizationalStructure,
64 CommitmentToCompetence,
67 Accountability,
70
71 ClearObjectives,
75 IdentifyRisks,
79 FraudRisk,
82 ChangeIdentification,
85
86 ControlActions,
90 TechnologyControls,
93 PoliciesAndProcedures,
97
98 QualityInformation,
102 InternalCommunication,
105 ExternalCommunication,
108
109 OngoingMonitoring,
114 DeficiencyEvaluation,
118}
119
120impl CosoPrinciple {
121 pub fn component(&self) -> CosoComponent {
123 match self {
124 Self::IntegrityAndEthics
126 | Self::BoardOversight
127 | Self::OrganizationalStructure
128 | Self::CommitmentToCompetence
129 | Self::Accountability => CosoComponent::ControlEnvironment,
130
131 Self::ClearObjectives
133 | Self::IdentifyRisks
134 | Self::FraudRisk
135 | Self::ChangeIdentification => CosoComponent::RiskAssessment,
136
137 Self::ControlActions | Self::TechnologyControls | Self::PoliciesAndProcedures => {
139 CosoComponent::ControlActivities
140 }
141
142 Self::QualityInformation
144 | Self::InternalCommunication
145 | Self::ExternalCommunication => CosoComponent::InformationCommunication,
146
147 Self::OngoingMonitoring | Self::DeficiencyEvaluation => {
149 CosoComponent::MonitoringActivities
150 }
151 }
152 }
153
154 pub fn principle_number(&self) -> u8 {
156 match self {
157 Self::IntegrityAndEthics => 1,
158 Self::BoardOversight => 2,
159 Self::OrganizationalStructure => 3,
160 Self::CommitmentToCompetence => 4,
161 Self::Accountability => 5,
162 Self::ClearObjectives => 6,
163 Self::IdentifyRisks => 7,
164 Self::FraudRisk => 8,
165 Self::ChangeIdentification => 9,
166 Self::ControlActions => 10,
167 Self::TechnologyControls => 11,
168 Self::PoliciesAndProcedures => 12,
169 Self::QualityInformation => 13,
170 Self::InternalCommunication => 14,
171 Self::ExternalCommunication => 15,
172 Self::OngoingMonitoring => 16,
173 Self::DeficiencyEvaluation => 17,
174 }
175 }
176}
177
178impl std::fmt::Display for CosoPrinciple {
179 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
180 match self {
181 Self::IntegrityAndEthics => write!(f, "Integrity and Ethics"),
182 Self::BoardOversight => write!(f, "Board Oversight"),
183 Self::OrganizationalStructure => write!(f, "Organizational Structure"),
184 Self::CommitmentToCompetence => write!(f, "Commitment to Competence"),
185 Self::Accountability => write!(f, "Accountability"),
186 Self::ClearObjectives => write!(f, "Clear Objectives"),
187 Self::IdentifyRisks => write!(f, "Identify Risks"),
188 Self::FraudRisk => write!(f, "Fraud Risk"),
189 Self::ChangeIdentification => write!(f, "Change Identification"),
190 Self::ControlActions => write!(f, "Control Actions"),
191 Self::TechnologyControls => write!(f, "Technology Controls"),
192 Self::PoliciesAndProcedures => write!(f, "Policies and Procedures"),
193 Self::QualityInformation => write!(f, "Quality Information"),
194 Self::InternalCommunication => write!(f, "Internal Communication"),
195 Self::ExternalCommunication => write!(f, "External Communication"),
196 Self::OngoingMonitoring => write!(f, "Ongoing Monitoring"),
197 Self::DeficiencyEvaluation => write!(f, "Deficiency Evaluation"),
198 }
199 }
200}
201
202#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
204#[serde(rename_all = "snake_case")]
205pub enum ControlScope {
206 EntityLevel,
209 TransactionLevel,
212 ItGeneralControl,
215 ItApplicationControl,
218}
219
220impl std::fmt::Display for ControlScope {
221 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
222 match self {
223 Self::EntityLevel => write!(f, "Entity Level"),
224 Self::TransactionLevel => write!(f, "Transaction Level"),
225 Self::ItGeneralControl => write!(f, "IT General Control"),
226 Self::ItApplicationControl => write!(f, "IT Application Control"),
227 }
228 }
229}
230
231#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
233#[serde(rename_all = "snake_case")]
234pub enum CosoMaturityLevel {
235 NonExistent,
237 AdHoc,
240 Repeatable,
243 Defined,
246 Managed,
249 Optimized,
252}
253
254impl std::fmt::Display for CosoMaturityLevel {
255 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
256 match self {
257 Self::NonExistent => write!(f, "Non-Existent"),
258 Self::AdHoc => write!(f, "Ad Hoc"),
259 Self::Repeatable => write!(f, "Repeatable"),
260 Self::Defined => write!(f, "Defined"),
261 Self::Managed => write!(f, "Managed"),
262 Self::Optimized => write!(f, "Optimized"),
263 }
264 }
265}
266
267impl CosoMaturityLevel {
268 pub fn level(&self) -> u8 {
270 match self {
271 Self::NonExistent => 0,
272 Self::AdHoc => 1,
273 Self::Repeatable => 2,
274 Self::Defined => 3,
275 Self::Managed => 4,
276 Self::Optimized => 5,
277 }
278 }
279}
280
281#[cfg(test)]
282mod tests {
283 use super::*;
284
285 #[test]
286 fn test_principle_component_mapping() {
287 assert_eq!(
289 CosoPrinciple::IntegrityAndEthics.component(),
290 CosoComponent::ControlEnvironment
291 );
292 assert_eq!(
293 CosoPrinciple::Accountability.component(),
294 CosoComponent::ControlEnvironment
295 );
296
297 assert_eq!(
299 CosoPrinciple::FraudRisk.component(),
300 CosoComponent::RiskAssessment
301 );
302
303 assert_eq!(
305 CosoPrinciple::ControlActions.component(),
306 CosoComponent::ControlActivities
307 );
308 assert_eq!(
309 CosoPrinciple::TechnologyControls.component(),
310 CosoComponent::ControlActivities
311 );
312
313 assert_eq!(
315 CosoPrinciple::QualityInformation.component(),
316 CosoComponent::InformationCommunication
317 );
318
319 assert_eq!(
321 CosoPrinciple::OngoingMonitoring.component(),
322 CosoComponent::MonitoringActivities
323 );
324 assert_eq!(
325 CosoPrinciple::DeficiencyEvaluation.component(),
326 CosoComponent::MonitoringActivities
327 );
328 }
329
330 #[test]
331 fn test_principle_numbers() {
332 assert_eq!(CosoPrinciple::IntegrityAndEthics.principle_number(), 1);
333 assert_eq!(CosoPrinciple::Accountability.principle_number(), 5);
334 assert_eq!(CosoPrinciple::ClearObjectives.principle_number(), 6);
335 assert_eq!(CosoPrinciple::ControlActions.principle_number(), 10);
336 assert_eq!(CosoPrinciple::QualityInformation.principle_number(), 13);
337 assert_eq!(CosoPrinciple::DeficiencyEvaluation.principle_number(), 17);
338 }
339
340 #[test]
341 fn test_maturity_level_ordering() {
342 assert!(CosoMaturityLevel::NonExistent < CosoMaturityLevel::AdHoc);
343 assert!(CosoMaturityLevel::AdHoc < CosoMaturityLevel::Repeatable);
344 assert!(CosoMaturityLevel::Repeatable < CosoMaturityLevel::Defined);
345 assert!(CosoMaturityLevel::Defined < CosoMaturityLevel::Managed);
346 assert!(CosoMaturityLevel::Managed < CosoMaturityLevel::Optimized);
347 }
348
349 #[test]
350 fn test_maturity_level_numeric() {
351 assert_eq!(CosoMaturityLevel::NonExistent.level(), 0);
352 assert_eq!(CosoMaturityLevel::Optimized.level(), 5);
353 }
354
355 #[test]
356 fn test_display_implementations() {
357 assert_eq!(
358 CosoComponent::ControlEnvironment.to_string(),
359 "Control Environment"
360 );
361 assert_eq!(
362 CosoPrinciple::IntegrityAndEthics.to_string(),
363 "Integrity and Ethics"
364 );
365 assert_eq!(ControlScope::EntityLevel.to_string(), "Entity Level");
366 assert_eq!(CosoMaturityLevel::Defined.to_string(), "Defined");
367 }
368
369 #[test]
370 fn test_serde_roundtrip() {
371 let component = CosoComponent::ControlActivities;
372 let json = serde_json::to_string(&component).unwrap();
373 let deserialized: CosoComponent = serde_json::from_str(&json).unwrap();
374 assert_eq!(component, deserialized);
375
376 let principle = CosoPrinciple::FraudRisk;
377 let json = serde_json::to_string(&principle).unwrap();
378 let deserialized: CosoPrinciple = serde_json::from_str(&json).unwrap();
379 assert_eq!(principle, deserialized);
380 }
381}