Skip to main content

datasynth_core/models/
coso.rs

1//! COSO 2013 Internal Control-Integrated Framework definitions.
2//!
3//! Provides structures for modeling the COSO framework's 5 components
4//! and 17 principles, along with control scope and maturity levels.
5
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9use super::graph_properties::{GraphPropertyValue, ToNodeProperties};
10
11/// COSO 2013 Framework - 5 Components of Internal Control.
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
13#[serde(rename_all = "snake_case")]
14pub enum CosoComponent {
15    /// The set of standards, processes, and structures that provide the basis
16    /// for carrying out internal control across the organization.
17    ControlEnvironment,
18    /// A dynamic and iterative process for identifying and assessing risks
19    /// to achievement of objectives.
20    RiskAssessment,
21    /// Actions established through policies and procedures that help ensure
22    /// that management's directives are carried out.
23    ControlActivities,
24    /// Information is necessary for the entity to carry out internal control
25    /// responsibilities. Communication is the ongoing process of providing,
26    /// sharing, and obtaining necessary information.
27    InformationCommunication,
28    /// Ongoing evaluations, separate evaluations, or some combination of
29    /// the two are used to ascertain whether each of the five components
30    /// of internal control is present and functioning.
31    MonitoringActivities,
32}
33
34impl std::fmt::Display for CosoComponent {
35    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36        match self {
37            Self::ControlEnvironment => write!(f, "Control Environment"),
38            Self::RiskAssessment => write!(f, "Risk Assessment"),
39            Self::ControlActivities => write!(f, "Control Activities"),
40            Self::InformationCommunication => write!(f, "Information & Communication"),
41            Self::MonitoringActivities => write!(f, "Monitoring Activities"),
42        }
43    }
44}
45
46/// COSO 2013 Framework - 17 Principles of Internal Control.
47///
48/// Each principle maps to one of the 5 COSO components:
49/// - Control Environment: Principles 1-5
50/// - Risk Assessment: Principles 6-9
51/// - Control Activities: Principles 10-12
52/// - Information & Communication: Principles 13-15
53/// - Monitoring Activities: Principles 16-17
54#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
55#[serde(rename_all = "snake_case")]
56pub enum CosoPrinciple {
57    // Control Environment (Principles 1-5)
58    /// Principle 1: The organization demonstrates a commitment to integrity
59    /// and ethical values.
60    IntegrityAndEthics,
61    /// Principle 2: The board of directors demonstrates independence from
62    /// management and exercises oversight of internal control.
63    BoardOversight,
64    /// Principle 3: Management establishes structures, reporting lines, and
65    /// appropriate authorities and responsibilities.
66    OrganizationalStructure,
67    /// Principle 4: The organization demonstrates a commitment to attract,
68    /// develop, and retain competent individuals.
69    CommitmentToCompetence,
70    /// Principle 5: The organization holds individuals accountable for their
71    /// internal control responsibilities.
72    Accountability,
73
74    // Risk Assessment (Principles 6-9)
75    /// Principle 6: The organization specifies objectives with sufficient
76    /// clarity to enable the identification and assessment of risks.
77    ClearObjectives,
78    /// Principle 7: The organization identifies risks to the achievement
79    /// of its objectives and analyzes risks as a basis for determining
80    /// how the risks should be managed.
81    IdentifyRisks,
82    /// Principle 8: The organization considers the potential for fraud
83    /// in assessing risks to the achievement of objectives.
84    FraudRisk,
85    /// Principle 9: The organization identifies and assesses changes that
86    /// could significantly impact the system of internal control.
87    ChangeIdentification,
88
89    // Control Activities (Principles 10-12)
90    /// Principle 10: The organization selects and develops control activities
91    /// that contribute to the mitigation of risks.
92    ControlActions,
93    /// Principle 11: The organization selects and develops general control
94    /// activities over technology to support the achievement of objectives.
95    TechnologyControls,
96    /// Principle 12: The organization deploys control activities through
97    /// policies that establish what is expected and procedures that put
98    /// policies into action.
99    PoliciesAndProcedures,
100
101    // Information & Communication (Principles 13-15)
102    /// Principle 13: The organization obtains or generates and uses relevant,
103    /// quality information to support the functioning of internal control.
104    QualityInformation,
105    /// Principle 14: The organization internally communicates information,
106    /// including objectives and responsibilities for internal control.
107    InternalCommunication,
108    /// Principle 15: The organization communicates with external parties
109    /// regarding matters affecting the functioning of internal control.
110    ExternalCommunication,
111
112    // Monitoring Activities (Principles 16-17)
113    /// Principle 16: The organization selects, develops, and performs ongoing
114    /// and/or separate evaluations to ascertain whether the components of
115    /// internal control are present and functioning.
116    OngoingMonitoring,
117    /// Principle 17: The organization evaluates and communicates internal
118    /// control deficiencies in a timely manner to those parties responsible
119    /// for taking corrective action.
120    DeficiencyEvaluation,
121}
122
123impl CosoPrinciple {
124    /// Returns the COSO component that this principle belongs to.
125    pub fn component(&self) -> CosoComponent {
126        match self {
127            // Control Environment (Principles 1-5)
128            Self::IntegrityAndEthics
129            | Self::BoardOversight
130            | Self::OrganizationalStructure
131            | Self::CommitmentToCompetence
132            | Self::Accountability => CosoComponent::ControlEnvironment,
133
134            // Risk Assessment (Principles 6-9)
135            Self::ClearObjectives
136            | Self::IdentifyRisks
137            | Self::FraudRisk
138            | Self::ChangeIdentification => CosoComponent::RiskAssessment,
139
140            // Control Activities (Principles 10-12)
141            Self::ControlActions | Self::TechnologyControls | Self::PoliciesAndProcedures => {
142                CosoComponent::ControlActivities
143            }
144
145            // Information & Communication (Principles 13-15)
146            Self::QualityInformation
147            | Self::InternalCommunication
148            | Self::ExternalCommunication => CosoComponent::InformationCommunication,
149
150            // Monitoring Activities (Principles 16-17)
151            Self::OngoingMonitoring | Self::DeficiencyEvaluation => {
152                CosoComponent::MonitoringActivities
153            }
154        }
155    }
156
157    /// Returns the principle number (1-17) in the COSO framework.
158    pub fn principle_number(&self) -> u8 {
159        match self {
160            Self::IntegrityAndEthics => 1,
161            Self::BoardOversight => 2,
162            Self::OrganizationalStructure => 3,
163            Self::CommitmentToCompetence => 4,
164            Self::Accountability => 5,
165            Self::ClearObjectives => 6,
166            Self::IdentifyRisks => 7,
167            Self::FraudRisk => 8,
168            Self::ChangeIdentification => 9,
169            Self::ControlActions => 10,
170            Self::TechnologyControls => 11,
171            Self::PoliciesAndProcedures => 12,
172            Self::QualityInformation => 13,
173            Self::InternalCommunication => 14,
174            Self::ExternalCommunication => 15,
175            Self::OngoingMonitoring => 16,
176            Self::DeficiencyEvaluation => 17,
177        }
178    }
179}
180
181impl std::fmt::Display for CosoPrinciple {
182    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
183        match self {
184            Self::IntegrityAndEthics => write!(f, "Integrity and Ethics"),
185            Self::BoardOversight => write!(f, "Board Oversight"),
186            Self::OrganizationalStructure => write!(f, "Organizational Structure"),
187            Self::CommitmentToCompetence => write!(f, "Commitment to Competence"),
188            Self::Accountability => write!(f, "Accountability"),
189            Self::ClearObjectives => write!(f, "Clear Objectives"),
190            Self::IdentifyRisks => write!(f, "Identify Risks"),
191            Self::FraudRisk => write!(f, "Fraud Risk"),
192            Self::ChangeIdentification => write!(f, "Change Identification"),
193            Self::ControlActions => write!(f, "Control Actions"),
194            Self::TechnologyControls => write!(f, "Technology Controls"),
195            Self::PoliciesAndProcedures => write!(f, "Policies and Procedures"),
196            Self::QualityInformation => write!(f, "Quality Information"),
197            Self::InternalCommunication => write!(f, "Internal Communication"),
198            Self::ExternalCommunication => write!(f, "External Communication"),
199            Self::OngoingMonitoring => write!(f, "Ongoing Monitoring"),
200            Self::DeficiencyEvaluation => write!(f, "Deficiency Evaluation"),
201        }
202    }
203}
204
205impl ToNodeProperties for CosoComponent {
206    fn node_type_name(&self) -> &'static str {
207        "coso_component"
208    }
209    fn node_type_code(&self) -> u16 {
210        500
211    }
212    fn to_node_properties(&self) -> HashMap<String, GraphPropertyValue> {
213        let mut p = HashMap::new();
214        p.insert("name".into(), GraphPropertyValue::String(self.to_string()));
215        p.insert(
216            "code".into(),
217            GraphPropertyValue::String(format!("{:?}", self)),
218        );
219        // Number of principles in this component
220        let principle_count = match self {
221            CosoComponent::ControlEnvironment => 5,
222            CosoComponent::RiskAssessment => 4,
223            CosoComponent::ControlActivities => 3,
224            CosoComponent::InformationCommunication => 3,
225            CosoComponent::MonitoringActivities => 2,
226        };
227        p.insert(
228            "principleCount".into(),
229            GraphPropertyValue::Int(principle_count),
230        );
231        p
232    }
233}
234
235impl ToNodeProperties for CosoPrinciple {
236    fn node_type_name(&self) -> &'static str {
237        "coso_principle"
238    }
239    fn node_type_code(&self) -> u16 {
240        501
241    }
242    fn to_node_properties(&self) -> HashMap<String, GraphPropertyValue> {
243        let mut p = HashMap::new();
244        p.insert("name".into(), GraphPropertyValue::String(self.to_string()));
245        p.insert(
246            "code".into(),
247            GraphPropertyValue::String(format!("{:?}", self)),
248        );
249        p.insert(
250            "number".into(),
251            GraphPropertyValue::Int(self.principle_number() as i64),
252        );
253        p.insert(
254            "componentId".into(),
255            GraphPropertyValue::String(format!("{:?}", self.component())),
256        );
257        p.insert(
258            "componentName".into(),
259            GraphPropertyValue::String(self.component().to_string()),
260        );
261        p
262    }
263}
264
265/// Control scope distinguishing entity-level from transaction-level controls.
266#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
267#[serde(rename_all = "snake_case")]
268pub enum ControlScope {
269    /// Entity-level controls operate across the organization and are typically
270    /// more pervasive in nature (e.g., tone at the top, code of conduct).
271    EntityLevel,
272    /// Transaction-level controls operate at the process or transaction level
273    /// and are typically more specific (e.g., three-way match, approvals).
274    TransactionLevel,
275    /// IT General Controls (ITGCs) are controls over the IT environment that
276    /// support the effective functioning of application controls.
277    ItGeneralControl,
278    /// IT Application Controls are automated controls embedded within
279    /// applications to ensure data integrity and proper authorization.
280    ItApplicationControl,
281}
282
283impl std::fmt::Display for ControlScope {
284    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
285        match self {
286            Self::EntityLevel => write!(f, "Entity Level"),
287            Self::TransactionLevel => write!(f, "Transaction Level"),
288            Self::ItGeneralControl => write!(f, "IT General Control"),
289            Self::ItApplicationControl => write!(f, "IT Application Control"),
290        }
291    }
292}
293
294/// Control maturity level based on capability maturity models.
295#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
296#[serde(rename_all = "snake_case")]
297pub enum CosoMaturityLevel {
298    /// Level 0: Control processes do not exist or are not recognized.
299    NonExistent,
300    /// Level 1: Processes are ad hoc and chaotic; success depends on
301    /// individual effort.
302    AdHoc,
303    /// Level 2: Basic processes exist and are repeated; discipline exists
304    /// to maintain basic consistency.
305    Repeatable,
306    /// Level 3: Processes are documented, standardized, and integrated
307    /// into the organization.
308    Defined,
309    /// Level 4: Processes are measured and controlled using metrics;
310    /// performance is predictable.
311    Managed,
312    /// Level 5: Continuous improvement is enabled through feedback and
313    /// innovative ideas.
314    Optimized,
315}
316
317impl std::fmt::Display for CosoMaturityLevel {
318    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
319        match self {
320            Self::NonExistent => write!(f, "Non-Existent"),
321            Self::AdHoc => write!(f, "Ad Hoc"),
322            Self::Repeatable => write!(f, "Repeatable"),
323            Self::Defined => write!(f, "Defined"),
324            Self::Managed => write!(f, "Managed"),
325            Self::Optimized => write!(f, "Optimized"),
326        }
327    }
328}
329
330impl CosoMaturityLevel {
331    /// Returns the numeric level (0-5).
332    pub fn level(&self) -> u8 {
333        match self {
334            Self::NonExistent => 0,
335            Self::AdHoc => 1,
336            Self::Repeatable => 2,
337            Self::Defined => 3,
338            Self::Managed => 4,
339            Self::Optimized => 5,
340        }
341    }
342}
343
344#[cfg(test)]
345#[allow(clippy::unwrap_used)]
346mod tests {
347    use super::*;
348
349    #[test]
350    fn test_principle_component_mapping() {
351        // Control Environment principles
352        assert_eq!(
353            CosoPrinciple::IntegrityAndEthics.component(),
354            CosoComponent::ControlEnvironment
355        );
356        assert_eq!(
357            CosoPrinciple::Accountability.component(),
358            CosoComponent::ControlEnvironment
359        );
360
361        // Risk Assessment principles
362        assert_eq!(
363            CosoPrinciple::FraudRisk.component(),
364            CosoComponent::RiskAssessment
365        );
366
367        // Control Activities principles
368        assert_eq!(
369            CosoPrinciple::ControlActions.component(),
370            CosoComponent::ControlActivities
371        );
372        assert_eq!(
373            CosoPrinciple::TechnologyControls.component(),
374            CosoComponent::ControlActivities
375        );
376
377        // Information & Communication principles
378        assert_eq!(
379            CosoPrinciple::QualityInformation.component(),
380            CosoComponent::InformationCommunication
381        );
382
383        // Monitoring Activities principles
384        assert_eq!(
385            CosoPrinciple::OngoingMonitoring.component(),
386            CosoComponent::MonitoringActivities
387        );
388        assert_eq!(
389            CosoPrinciple::DeficiencyEvaluation.component(),
390            CosoComponent::MonitoringActivities
391        );
392    }
393
394    #[test]
395    fn test_principle_numbers() {
396        assert_eq!(CosoPrinciple::IntegrityAndEthics.principle_number(), 1);
397        assert_eq!(CosoPrinciple::Accountability.principle_number(), 5);
398        assert_eq!(CosoPrinciple::ClearObjectives.principle_number(), 6);
399        assert_eq!(CosoPrinciple::ControlActions.principle_number(), 10);
400        assert_eq!(CosoPrinciple::QualityInformation.principle_number(), 13);
401        assert_eq!(CosoPrinciple::DeficiencyEvaluation.principle_number(), 17);
402    }
403
404    #[test]
405    fn test_maturity_level_ordering() {
406        assert!(CosoMaturityLevel::NonExistent < CosoMaturityLevel::AdHoc);
407        assert!(CosoMaturityLevel::AdHoc < CosoMaturityLevel::Repeatable);
408        assert!(CosoMaturityLevel::Repeatable < CosoMaturityLevel::Defined);
409        assert!(CosoMaturityLevel::Defined < CosoMaturityLevel::Managed);
410        assert!(CosoMaturityLevel::Managed < CosoMaturityLevel::Optimized);
411    }
412
413    #[test]
414    fn test_maturity_level_numeric() {
415        assert_eq!(CosoMaturityLevel::NonExistent.level(), 0);
416        assert_eq!(CosoMaturityLevel::Optimized.level(), 5);
417    }
418
419    #[test]
420    fn test_display_implementations() {
421        assert_eq!(
422            CosoComponent::ControlEnvironment.to_string(),
423            "Control Environment"
424        );
425        assert_eq!(
426            CosoPrinciple::IntegrityAndEthics.to_string(),
427            "Integrity and Ethics"
428        );
429        assert_eq!(ControlScope::EntityLevel.to_string(), "Entity Level");
430        assert_eq!(CosoMaturityLevel::Defined.to_string(), "Defined");
431    }
432
433    #[test]
434    fn test_serde_roundtrip() {
435        let component = CosoComponent::ControlActivities;
436        let json = serde_json::to_string(&component).unwrap();
437        let deserialized: CosoComponent = serde_json::from_str(&json).unwrap();
438        assert_eq!(component, deserialized);
439
440        let principle = CosoPrinciple::FraudRisk;
441        let json = serde_json::to_string(&principle).unwrap();
442        let deserialized: CosoPrinciple = serde_json::from_str(&json).unwrap();
443        assert_eq!(principle, deserialized);
444    }
445}