Skip to main content

verifyos_cli/rules/
export_compliance.rs

1use crate::rules::core::{
2    AppStoreRule, ArtifactContext, RuleCategory, RuleError, RuleReport, RuleStatus, Severity,
3};
4
5pub struct ExportComplianceRule;
6
7impl AppStoreRule for ExportComplianceRule {
8    fn id(&self) -> &'static str {
9        "RULE_EXPORT_COMPLIANCE"
10    }
11
12    fn name(&self) -> &'static str {
13        "Export Compliance Declaration"
14    }
15
16    fn category(&self) -> RuleCategory {
17        RuleCategory::Metadata
18    }
19
20    fn severity(&self) -> Severity {
21        Severity::Warning
22    }
23
24    fn recommendation(&self) -> &'static str {
25        "Set ITSAppUsesNonExemptEncryption to avoid App Store Connect prompts."
26    }
27
28    fn evaluate(&self, artifact: &ArtifactContext) -> Result<RuleReport, RuleError> {
29        let Some(plist) = artifact.info_plist else {
30            return Ok(RuleReport {
31                status: RuleStatus::Skip,
32                message: Some("Info.plist not found".to_string()),
33                evidence: None,
34            });
35        };
36
37        let uses_encryption = plist.get_bool("ITSAppUsesNonExemptEncryption");
38
39        match uses_encryption {
40            Some(false) => Ok(RuleReport {
41                status: RuleStatus::Pass,
42                message: None,
43                evidence: None,
44            }),
45            Some(true) => Ok(RuleReport {
46                status: RuleStatus::Fail,
47                message: Some("App uses non-exempt encryption".to_string()),
48                evidence: Some("ITSAppUsesNonExemptEncryption=true".to_string()),
49            }),
50            None => Ok(RuleReport {
51                status: RuleStatus::Fail,
52                message: Some("Missing export compliance declaration".to_string()),
53                evidence: Some("ITSAppUsesNonExemptEncryption not set".to_string()),
54            }),
55        }
56    }
57}