1use chrono::NaiveDate;
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9
10use super::coso::{ControlScope, CosoComponent, CosoMaturityLevel, CosoPrinciple};
11use super::graph_properties::{GraphPropertyValue, ToNodeProperties};
12use super::user::UserPersona;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
16#[serde(rename_all = "snake_case")]
17pub enum ControlType {
18 Preventive,
20 Detective,
22 Monitoring,
24}
25
26impl std::fmt::Display for ControlType {
27 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 match self {
29 Self::Preventive => write!(f, "Preventive"),
30 Self::Detective => write!(f, "Detective"),
31 Self::Monitoring => write!(f, "Monitoring"),
32 }
33 }
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
38#[serde(rename_all = "snake_case")]
39pub enum ControlFrequency {
40 Transactional,
42 Daily,
44 Weekly,
46 Monthly,
48 Quarterly,
50 Annual,
52}
53
54impl std::fmt::Display for ControlFrequency {
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 match self {
57 Self::Transactional => write!(f, "Transactional"),
58 Self::Daily => write!(f, "Daily"),
59 Self::Weekly => write!(f, "Weekly"),
60 Self::Monthly => write!(f, "Monthly"),
61 Self::Quarterly => write!(f, "Quarterly"),
62 Self::Annual => write!(f, "Annual"),
63 }
64 }
65}
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
69#[serde(rename_all = "snake_case")]
70pub enum RiskLevel {
71 Low,
73 Medium,
75 High,
77 Critical,
79}
80
81impl std::fmt::Display for RiskLevel {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 match self {
84 Self::Low => write!(f, "Low"),
85 Self::Medium => write!(f, "Medium"),
86 Self::High => write!(f, "High"),
87 Self::Critical => write!(f, "Critical"),
88 }
89 }
90}
91
92#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
94#[serde(rename_all = "snake_case")]
95pub enum SoxAssertion {
96 Existence,
98 Completeness,
100 Valuation,
102 RightsAndObligations,
104 PresentationAndDisclosure,
106}
107
108impl ToNodeProperties for SoxAssertion {
109 fn node_type_name(&self) -> &'static str {
110 "sox_assertion"
111 }
112 fn node_type_code(&self) -> u16 {
113 502
114 }
115 fn to_node_properties(&self) -> HashMap<String, GraphPropertyValue> {
116 let mut p = HashMap::new();
117 p.insert("name".into(), GraphPropertyValue::String(self.to_string()));
118 p.insert(
119 "code".into(),
120 GraphPropertyValue::String(format!("{self:?}")),
121 );
122 p
123 }
124}
125
126impl std::fmt::Display for SoxAssertion {
127 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128 match self {
129 Self::Existence => write!(f, "Existence"),
130 Self::Completeness => write!(f, "Completeness"),
131 Self::Valuation => write!(f, "Valuation"),
132 Self::RightsAndObligations => write!(f, "RightsAndObligations"),
133 Self::PresentationAndDisclosure => write!(f, "PresentationAndDisclosure"),
134 }
135 }
136}
137
138#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
140#[serde(rename_all = "snake_case")]
141pub enum TestResult {
142 Pass,
144 Partial,
146 Fail,
148 #[default]
150 NotTested,
151}
152
153impl std::fmt::Display for TestResult {
154 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
155 match self {
156 Self::Pass => write!(f, "Pass"),
157 Self::Partial => write!(f, "Partial"),
158 Self::Fail => write!(f, "Fail"),
159 Self::NotTested => write!(f, "NotTested"),
160 }
161 }
162}
163
164#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
166#[serde(rename_all = "snake_case")]
167pub enum ControlEffectiveness {
168 Effective,
170 PartiallyEffective,
172 #[default]
174 NotTested,
175 Ineffective,
177}
178
179impl std::fmt::Display for ControlEffectiveness {
180 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
181 match self {
182 Self::Effective => write!(f, "Effective"),
183 Self::PartiallyEffective => write!(f, "PartiallyEffective"),
184 Self::NotTested => write!(f, "NotTested"),
185 Self::Ineffective => write!(f, "Ineffective"),
186 }
187 }
188}
189
190#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
192#[serde(rename_all = "snake_case")]
193pub enum ControlStatus {
194 #[default]
196 Effective,
197 Exception,
199 NotTested,
201 Remediated,
203}
204
205impl std::fmt::Display for ControlStatus {
206 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
207 match self {
208 Self::Effective => write!(f, "Effective"),
209 Self::Exception => write!(f, "Exception"),
210 Self::NotTested => write!(f, "NotTested"),
211 Self::Remediated => write!(f, "Remediated"),
212 }
213 }
214}
215
216#[derive(Debug, Clone, Serialize, Deserialize)]
218pub struct InternalControl {
219 pub control_id: String,
221 pub control_name: String,
223 pub control_type: ControlType,
225 pub objective: String,
227 pub frequency: ControlFrequency,
229 pub owner_role: UserPersona,
231 pub risk_level: RiskLevel,
233 pub description: String,
235 pub is_key_control: bool,
237 pub sox_assertion: SoxAssertion,
239 pub coso_component: CosoComponent,
241 pub coso_principles: Vec<CosoPrinciple>,
243 pub control_scope: ControlScope,
245 pub maturity_level: CosoMaturityLevel,
247
248 pub owner_employee_id: Option<String>,
251 pub owner_name: String,
253
254 pub test_count: u32,
256 pub last_tested_date: Option<NaiveDate>,
258 pub test_result: TestResult,
260
261 pub effectiveness: ControlEffectiveness,
263
264 pub mitigates_risk_ids: Vec<String>,
266 pub covers_account_classes: Vec<String>,
268}
269
270impl InternalControl {
271 pub fn new(
273 control_id: impl Into<String>,
274 control_name: impl Into<String>,
275 control_type: ControlType,
276 objective: impl Into<String>,
277 ) -> Self {
278 Self {
279 control_id: control_id.into(),
280 control_name: control_name.into(),
281 control_type,
282 objective: objective.into(),
283 frequency: ControlFrequency::Transactional,
284 owner_role: UserPersona::Controller,
285 risk_level: RiskLevel::Medium,
286 description: String::new(),
287 is_key_control: false,
288 sox_assertion: SoxAssertion::Existence,
289 coso_component: CosoComponent::ControlActivities,
290 coso_principles: vec![CosoPrinciple::ControlActions],
291 control_scope: ControlScope::TransactionLevel,
292 maturity_level: CosoMaturityLevel::Defined,
293 owner_employee_id: None,
294 owner_name: String::new(),
295 test_count: 0,
296 last_tested_date: None,
297 test_result: TestResult::NotTested,
298 effectiveness: ControlEffectiveness::NotTested,
299 mitigates_risk_ids: Vec::new(),
300 covers_account_classes: Vec::new(),
301 }
302 }
303
304 pub fn with_frequency(mut self, frequency: ControlFrequency) -> Self {
306 self.frequency = frequency;
307 self
308 }
309
310 pub fn with_owner(mut self, owner: UserPersona) -> Self {
312 self.owner_role = owner;
313 self
314 }
315
316 pub fn with_risk_level(mut self, level: RiskLevel) -> Self {
318 self.risk_level = level;
319 self
320 }
321
322 pub fn with_description(mut self, description: impl Into<String>) -> Self {
324 self.description = description.into();
325 self
326 }
327
328 pub fn as_key_control(mut self) -> Self {
330 self.is_key_control = true;
331 self
332 }
333
334 pub fn with_assertion(mut self, assertion: SoxAssertion) -> Self {
336 self.sox_assertion = assertion;
337 self
338 }
339
340 pub fn with_coso_component(mut self, component: CosoComponent) -> Self {
342 self.coso_component = component;
343 self
344 }
345
346 pub fn with_coso_principles(mut self, principles: Vec<CosoPrinciple>) -> Self {
348 self.coso_principles = principles;
349 self
350 }
351
352 pub fn with_control_scope(mut self, scope: ControlScope) -> Self {
354 self.control_scope = scope;
355 self
356 }
357
358 pub fn with_maturity_level(mut self, level: CosoMaturityLevel) -> Self {
360 self.maturity_level = level;
361 self
362 }
363
364 pub fn with_owner_employee(
366 mut self,
367 employee_id: impl Into<String>,
368 name: impl Into<String>,
369 ) -> Self {
370 self.owner_employee_id = Some(employee_id.into());
371 self.owner_name = name.into();
372 self
373 }
374
375 pub fn with_test_history(
377 mut self,
378 test_count: u32,
379 last_tested_date: Option<NaiveDate>,
380 test_result: TestResult,
381 ) -> Self {
382 self.test_count = test_count;
383 self.last_tested_date = last_tested_date;
384 self.test_result = test_result;
385 self
386 }
387
388 pub fn with_effectiveness(mut self, effectiveness: ControlEffectiveness) -> Self {
390 self.effectiveness = effectiveness;
391 self
392 }
393
394 pub fn with_mitigates_risk_ids(mut self, risk_ids: Vec<String>) -> Self {
396 self.mitigates_risk_ids = risk_ids;
397 self
398 }
399
400 pub fn with_covers_account_classes(mut self, classes: Vec<String>) -> Self {
402 self.covers_account_classes = classes;
403 self
404 }
405
406 pub fn derive_from_maturity(&mut self, assessed_date: NaiveDate) {
418 let level = self.maturity_level.level();
419
420 if level >= 4 {
421 self.test_count = (level as u32).saturating_sub(2); let days_back = 30_i64 * (5 - level as i64);
424 self.last_tested_date =
425 assessed_date.checked_sub_signed(chrono::Duration::days(days_back));
426 self.test_result = TestResult::Pass;
427 self.effectiveness = ControlEffectiveness::Effective;
428 } else if level == 3 {
429 self.test_count = 1;
431 let days_back = 30_i64 * (5 - 3);
432 self.last_tested_date =
433 assessed_date.checked_sub_signed(chrono::Duration::days(days_back));
434 self.test_result = TestResult::Partial;
435 self.effectiveness = ControlEffectiveness::PartiallyEffective;
436 } else {
437 self.test_count = 0;
439 self.last_tested_date = None;
440 self.test_result = TestResult::NotTested;
441 self.effectiveness = ControlEffectiveness::NotTested;
442 }
443 }
444
445 pub fn derive_account_classes(&mut self) {
454 self.covers_account_classes = match self.sox_assertion {
455 SoxAssertion::Existence => vec!["Assets".into()],
456 SoxAssertion::Completeness => vec!["Revenue".into(), "Liabilities".into()],
457 SoxAssertion::Valuation => vec![
458 "Assets".into(),
459 "Liabilities".into(),
460 "Equity".into(),
461 "Revenue".into(),
462 "Expenses".into(),
463 ],
464 SoxAssertion::RightsAndObligations => vec!["Assets".into(), "Liabilities".into()],
465 SoxAssertion::PresentationAndDisclosure => vec!["Revenue".into(), "Equity".into()],
466 };
467 }
468
469 pub fn standard_controls() -> Vec<Self> {
474 vec![
475 Self::new(
481 "C001",
482 "Cash Account Daily Review",
483 ControlType::Detective,
484 "Review all cash transactions daily for unauthorized activity",
485 )
486 .with_frequency(ControlFrequency::Daily)
487 .with_owner(UserPersona::Controller)
488 .with_risk_level(RiskLevel::High)
489 .as_key_control()
490 .with_assertion(SoxAssertion::Existence)
491 .with_description(
492 "Daily reconciliation of cash accounts with bank statements and review of unusual transactions",
493 )
494 .with_coso_component(CosoComponent::ControlActivities)
495 .with_coso_principles(vec![
496 CosoPrinciple::ControlActions,
497 CosoPrinciple::OngoingMonitoring,
498 ])
499 .with_control_scope(ControlScope::TransactionLevel)
500 .with_maturity_level(CosoMaturityLevel::Managed),
501
502 Self::new(
504 "C002",
505 "Large Transaction Multi-Level Approval",
506 ControlType::Preventive,
507 "Transactions over $10,000 require additional approval levels",
508 )
509 .with_frequency(ControlFrequency::Transactional)
510 .with_owner(UserPersona::Manager)
511 .with_risk_level(RiskLevel::High)
512 .as_key_control()
513 .with_assertion(SoxAssertion::Valuation)
514 .with_description(
515 "Multi-level approval workflow for transactions exceeding defined thresholds",
516 )
517 .with_coso_component(CosoComponent::ControlActivities)
518 .with_coso_principles(vec![
519 CosoPrinciple::ControlActions,
520 CosoPrinciple::PoliciesAndProcedures,
521 ])
522 .with_control_scope(ControlScope::TransactionLevel)
523 .with_maturity_level(CosoMaturityLevel::Defined),
524
525 Self::new(
527 "C010",
528 "Three-Way Match",
529 ControlType::Preventive,
530 "Match purchase order, receipt, and invoice before payment",
531 )
532 .with_frequency(ControlFrequency::Transactional)
533 .with_owner(UserPersona::SeniorAccountant)
534 .with_risk_level(RiskLevel::Medium)
535 .as_key_control()
536 .with_assertion(SoxAssertion::Completeness)
537 .with_description(
538 "Automated matching of PO, goods receipt, and vendor invoice prior to payment release",
539 )
540 .with_coso_component(CosoComponent::ControlActivities)
541 .with_coso_principles(vec![
542 CosoPrinciple::ControlActions,
543 CosoPrinciple::TechnologyControls,
544 ])
545 .with_control_scope(ControlScope::ItApplicationControl)
546 .with_maturity_level(CosoMaturityLevel::Managed),
547
548 Self::new(
550 "C011",
551 "Vendor Master Data Maintenance",
552 ControlType::Preventive,
553 "Segregated access for vendor master data changes",
554 )
555 .with_frequency(ControlFrequency::Transactional)
556 .with_owner(UserPersona::SeniorAccountant)
557 .with_risk_level(RiskLevel::High)
558 .as_key_control()
559 .with_assertion(SoxAssertion::Existence)
560 .with_description(
561 "Restricted access to vendor master data with dual-approval for bank account changes",
562 )
563 .with_coso_component(CosoComponent::ControlActivities)
564 .with_coso_principles(vec![
565 CosoPrinciple::ControlActions,
566 CosoPrinciple::FraudRisk,
567 ])
568 .with_control_scope(ControlScope::TransactionLevel)
569 .with_maturity_level(CosoMaturityLevel::Defined),
570
571 Self::new(
573 "C020",
574 "Revenue Recognition Review",
575 ControlType::Detective,
576 "Review revenue entries for proper timing and classification",
577 )
578 .with_frequency(ControlFrequency::Monthly)
579 .with_owner(UserPersona::Controller)
580 .with_risk_level(RiskLevel::Critical)
581 .as_key_control()
582 .with_assertion(SoxAssertion::Valuation)
583 .with_description(
584 "Monthly review of revenue recognition to ensure compliance with ASC 606",
585 )
586 .with_coso_component(CosoComponent::ControlActivities)
587 .with_coso_principles(vec![
588 CosoPrinciple::ControlActions,
589 CosoPrinciple::ClearObjectives,
590 ])
591 .with_control_scope(ControlScope::TransactionLevel)
592 .with_maturity_level(CosoMaturityLevel::Managed),
593
594 Self::new(
596 "C021",
597 "Customer Credit Limit Check",
598 ControlType::Preventive,
599 "Automatic credit limit check before order acceptance",
600 )
601 .with_frequency(ControlFrequency::Transactional)
602 .with_owner(UserPersona::AutomatedSystem)
603 .with_risk_level(RiskLevel::Medium)
604 .with_assertion(SoxAssertion::Valuation)
605 .with_description(
606 "System-enforced credit limit validation at order entry",
607 )
608 .with_coso_component(CosoComponent::ControlActivities)
609 .with_coso_principles(vec![
610 CosoPrinciple::TechnologyControls,
611 CosoPrinciple::ControlActions,
612 ])
613 .with_control_scope(ControlScope::ItApplicationControl)
614 .with_maturity_level(CosoMaturityLevel::Optimized),
615
616 Self::new(
618 "C030",
619 "GL Account Reconciliation",
620 ControlType::Detective,
621 "Monthly reconciliation of all balance sheet accounts",
622 )
623 .with_frequency(ControlFrequency::Monthly)
624 .with_owner(UserPersona::SeniorAccountant)
625 .with_risk_level(RiskLevel::High)
626 .as_key_control()
627 .with_assertion(SoxAssertion::Completeness)
628 .with_description(
629 "Complete reconciliation of all balance sheet accounts with supporting documentation",
630 )
631 .with_coso_component(CosoComponent::MonitoringActivities)
632 .with_coso_principles(vec![CosoPrinciple::OngoingMonitoring])
633 .with_control_scope(ControlScope::TransactionLevel)
634 .with_maturity_level(CosoMaturityLevel::Managed),
635
636 Self::new(
638 "C031",
639 "Manual Journal Entry Review",
640 ControlType::Detective,
641 "Review of all manual journal entries over threshold",
642 )
643 .with_frequency(ControlFrequency::Daily)
644 .with_owner(UserPersona::Controller)
645 .with_risk_level(RiskLevel::High)
646 .as_key_control()
647 .with_assertion(SoxAssertion::Existence)
648 .with_description(
649 "Daily review of manual journal entries with supporting documentation",
650 )
651 .with_coso_component(CosoComponent::ControlActivities)
652 .with_coso_principles(vec![
653 CosoPrinciple::ControlActions,
654 CosoPrinciple::FraudRisk,
655 ])
656 .with_control_scope(ControlScope::TransactionLevel)
657 .with_maturity_level(CosoMaturityLevel::Managed),
658
659 Self::new(
661 "C032",
662 "Period Close Checklist",
663 ControlType::Detective,
664 "Comprehensive checklist for period-end close procedures",
665 )
666 .with_frequency(ControlFrequency::Monthly)
667 .with_owner(UserPersona::Controller)
668 .with_risk_level(RiskLevel::Medium)
669 .with_assertion(SoxAssertion::Completeness)
670 .with_description(
671 "Standardized period-end close checklist ensuring all procedures completed",
672 )
673 .with_coso_component(CosoComponent::ControlActivities)
674 .with_coso_principles(vec![
675 CosoPrinciple::PoliciesAndProcedures,
676 CosoPrinciple::ControlActions,
677 ])
678 .with_control_scope(ControlScope::TransactionLevel)
679 .with_maturity_level(CosoMaturityLevel::Defined),
680
681 Self::new(
683 "C040",
684 "Payroll Processing Review",
685 ControlType::Detective,
686 "Review of payroll processing for accuracy",
687 )
688 .with_frequency(ControlFrequency::Monthly)
689 .with_owner(UserPersona::Controller)
690 .with_risk_level(RiskLevel::High)
691 .as_key_control()
692 .with_assertion(SoxAssertion::Valuation)
693 .with_description(
694 "Monthly review of payroll journals and reconciliation to HR records",
695 )
696 .with_coso_component(CosoComponent::ControlActivities)
697 .with_coso_principles(vec![
698 CosoPrinciple::ControlActions,
699 CosoPrinciple::FraudRisk,
700 ])
701 .with_control_scope(ControlScope::TransactionLevel)
702 .with_maturity_level(CosoMaturityLevel::Managed),
703
704 Self::new(
706 "C050",
707 "Fixed Asset Addition Approval",
708 ControlType::Preventive,
709 "Multi-level approval for capital expenditures",
710 )
711 .with_frequency(ControlFrequency::Transactional)
712 .with_owner(UserPersona::Manager)
713 .with_risk_level(RiskLevel::Medium)
714 .with_assertion(SoxAssertion::Existence)
715 .with_description(
716 "Approval workflow for capital asset additions based on dollar thresholds",
717 )
718 .with_coso_component(CosoComponent::ControlActivities)
719 .with_coso_principles(vec![
720 CosoPrinciple::ControlActions,
721 CosoPrinciple::PoliciesAndProcedures,
722 ])
723 .with_control_scope(ControlScope::TransactionLevel)
724 .with_maturity_level(CosoMaturityLevel::Defined),
725
726 Self::new(
728 "C060",
729 "Intercompany Balance Reconciliation",
730 ControlType::Detective,
731 "Monthly reconciliation of intercompany balances",
732 )
733 .with_frequency(ControlFrequency::Monthly)
734 .with_owner(UserPersona::SeniorAccountant)
735 .with_risk_level(RiskLevel::High)
736 .as_key_control()
737 .with_assertion(SoxAssertion::Completeness)
738 .with_description(
739 "Full reconciliation of intercompany accounts between all entities",
740 )
741 .with_coso_component(CosoComponent::MonitoringActivities)
742 .with_coso_principles(vec![
743 CosoPrinciple::OngoingMonitoring,
744 CosoPrinciple::DeficiencyEvaluation,
745 ])
746 .with_control_scope(ControlScope::TransactionLevel)
747 .with_maturity_level(CosoMaturityLevel::Managed),
748
749 Self::new(
755 "C070",
756 "Code of Conduct and Ethics",
757 ControlType::Preventive,
758 "Establish and communicate ethical values and standards of conduct",
759 )
760 .with_frequency(ControlFrequency::Annual)
761 .with_owner(UserPersona::Controller)
762 .with_risk_level(RiskLevel::High)
763 .as_key_control()
764 .with_assertion(SoxAssertion::PresentationAndDisclosure)
765 .with_description(
766 "Annual review and acknowledgment of code of conduct by all employees; \
767 includes ethics hotline and whistleblower protections",
768 )
769 .with_coso_component(CosoComponent::ControlEnvironment)
770 .with_coso_principles(vec![
771 CosoPrinciple::IntegrityAndEthics,
772 CosoPrinciple::Accountability,
773 ])
774 .with_control_scope(ControlScope::EntityLevel)
775 .with_maturity_level(CosoMaturityLevel::Managed),
776
777 Self::new(
779 "C071",
780 "Audit Committee Oversight",
781 ControlType::Monitoring,
782 "Board and audit committee exercise independent oversight of internal control",
783 )
784 .with_frequency(ControlFrequency::Quarterly)
785 .with_owner(UserPersona::Controller)
786 .with_risk_level(RiskLevel::Critical)
787 .as_key_control()
788 .with_assertion(SoxAssertion::PresentationAndDisclosure)
789 .with_description(
790 "Quarterly audit committee meetings with review of internal control effectiveness, \
791 external auditor findings, and management representations",
792 )
793 .with_coso_component(CosoComponent::ControlEnvironment)
794 .with_coso_principles(vec![
795 CosoPrinciple::BoardOversight,
796 CosoPrinciple::OrganizationalStructure,
797 ])
798 .with_control_scope(ControlScope::EntityLevel)
799 .with_maturity_level(CosoMaturityLevel::Managed),
800
801 Self::new(
803 "C075",
804 "Enterprise Risk Assessment",
805 ControlType::Detective,
806 "Identify and assess risks to achievement of organizational objectives",
807 )
808 .with_frequency(ControlFrequency::Annual)
809 .with_owner(UserPersona::Controller)
810 .with_risk_level(RiskLevel::High)
811 .as_key_control()
812 .with_assertion(SoxAssertion::Completeness)
813 .with_description(
814 "Annual enterprise risk assessment process including fraud risk evaluation; \
815 risk register maintained and updated quarterly",
816 )
817 .with_coso_component(CosoComponent::RiskAssessment)
818 .with_coso_principles(vec![
819 CosoPrinciple::IdentifyRisks,
820 CosoPrinciple::FraudRisk,
821 CosoPrinciple::ChangeIdentification,
822 ])
823 .with_control_scope(ControlScope::EntityLevel)
824 .with_maturity_level(CosoMaturityLevel::Defined),
825
826 Self::new(
828 "C077",
829 "IT General Controls Program",
830 ControlType::Preventive,
831 "General controls over IT environment supporting financial reporting systems",
832 )
833 .with_frequency(ControlFrequency::Transactional)
834 .with_owner(UserPersona::AutomatedSystem)
835 .with_risk_level(RiskLevel::High)
836 .as_key_control()
837 .with_assertion(SoxAssertion::Existence)
838 .with_description(
839 "IT general controls including access management, change management, \
840 computer operations, and program development for systems supporting \
841 financial reporting",
842 )
843 .with_coso_component(CosoComponent::ControlActivities)
844 .with_coso_principles(vec![
845 CosoPrinciple::TechnologyControls,
846 CosoPrinciple::PoliciesAndProcedures,
847 ])
848 .with_control_scope(ControlScope::ItGeneralControl)
849 .with_maturity_level(CosoMaturityLevel::Managed),
850
851 Self::new(
853 "C078",
854 "Financial Information Quality",
855 ControlType::Detective,
856 "Obtain and use quality information for internal control",
857 )
858 .with_frequency(ControlFrequency::Monthly)
859 .with_owner(UserPersona::Controller)
860 .with_risk_level(RiskLevel::Medium)
861 .with_assertion(SoxAssertion::Valuation)
862 .with_description(
863 "Monthly data quality reviews for key financial reports; validation of \
864 data inputs, processing, and outputs supporting management decisions",
865 )
866 .with_coso_component(CosoComponent::InformationCommunication)
867 .with_coso_principles(vec![
868 CosoPrinciple::QualityInformation,
869 CosoPrinciple::InternalCommunication,
870 ])
871 .with_control_scope(ControlScope::EntityLevel)
872 .with_maturity_level(CosoMaturityLevel::Defined),
873
874 Self::new(
876 "C081",
877 "Internal Control Monitoring Program",
878 ControlType::Monitoring,
879 "Ongoing and periodic evaluations of internal control effectiveness",
880 )
881 .with_frequency(ControlFrequency::Quarterly)
882 .with_owner(UserPersona::Controller)
883 .with_risk_level(RiskLevel::High)
884 .as_key_control()
885 .with_assertion(SoxAssertion::Completeness)
886 .with_description(
887 "Continuous monitoring program with quarterly control testing, \
888 deficiency tracking, and remediation management; annual SOX 404 \
889 assessment and certification",
890 )
891 .with_coso_component(CosoComponent::MonitoringActivities)
892 .with_coso_principles(vec![
893 CosoPrinciple::OngoingMonitoring,
894 CosoPrinciple::DeficiencyEvaluation,
895 ])
896 .with_control_scope(ControlScope::EntityLevel)
897 .with_maturity_level(CosoMaturityLevel::Managed),
898 ]
899 }
900}
901
902#[cfg(test)]
903#[allow(clippy::unwrap_used)]
904mod tests {
905 use super::*;
906
907 #[test]
908 fn test_control_creation() {
909 let control = InternalControl::new(
910 "TEST001",
911 "Test Control",
912 ControlType::Preventive,
913 "Test objective",
914 )
915 .with_frequency(ControlFrequency::Daily)
916 .with_risk_level(RiskLevel::High)
917 .as_key_control();
918
919 assert_eq!(control.control_id, "TEST001");
920 assert_eq!(control.control_type, ControlType::Preventive);
921 assert_eq!(control.frequency, ControlFrequency::Daily);
922 assert_eq!(control.risk_level, RiskLevel::High);
923 assert!(control.is_key_control);
924 }
925
926 #[test]
927 fn test_standard_controls() {
928 let controls = InternalControl::standard_controls();
929 assert!(!controls.is_empty());
930
931 let key_controls: Vec<_> = controls.iter().filter(|c| c.is_key_control).collect();
933 assert!(key_controls.len() >= 5);
934
935 let preventive: Vec<_> = controls
937 .iter()
938 .filter(|c| c.control_type == ControlType::Preventive)
939 .collect();
940 let detective: Vec<_> = controls
941 .iter()
942 .filter(|c| c.control_type == ControlType::Detective)
943 .collect();
944
945 assert!(!preventive.is_empty());
946 assert!(!detective.is_empty());
947 }
948
949 #[test]
950 fn test_control_status_display() {
951 assert_eq!(ControlStatus::Effective.to_string(), "Effective");
952 assert_eq!(ControlStatus::Exception.to_string(), "Exception");
953 }
954}