Skip to main content

verifyos_cli/rules/
launch_screen.rs

1use crate::rules::core::{
2    AppStoreRule, ArtifactContext, RuleCategory, RuleError, RuleReport, RuleStatus, Severity,
3};
4
5pub struct LaunchScreenStoryboardRule;
6
7impl AppStoreRule for LaunchScreenStoryboardRule {
8    fn id(&self) -> &'static str {
9        "RULE_LAUNCH_SCREEN_STORYBOARD"
10    }
11
12    fn name(&self) -> &'static str {
13        "Launch Screen Storyboard Requirement"
14    }
15
16    fn category(&self) -> RuleCategory {
17        RuleCategory::Metadata
18    }
19
20    fn severity(&self) -> Severity {
21        Severity::Error
22    }
23
24    fn recommendation(&self) -> &'static str {
25        "Remove UILaunchImages from Info.plist and use UILaunchStoryboardName instead."
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("No Info.plist found".to_string()),
33                evidence: None,
34            });
35        };
36
37        // Skip for App Extensions, typical extensions have NSExtension in Info.plist
38        if plist.get_value("NSExtension").is_some() {
39            return Ok(RuleReport {
40                status: RuleStatus::Skip,
41                message: Some("Rule does not apply to app extensions".to_string()),
42                evidence: None,
43            });
44        }
45
46        let has_launch_images = plist.get_value("UILaunchImages").is_some();
47        let has_storyboard = plist.get_value("UILaunchStoryboardName").is_some();
48
49        if has_launch_images {
50            return Ok(RuleReport {
51                status: RuleStatus::Fail,
52                message: Some("App uses deprecated UILaunchImages.".to_string()),
53                evidence: Some("UILaunchImages key found in Info.plist".to_string()),
54            });
55        }
56
57        if !has_storyboard {
58            return Ok(RuleReport {
59                status: RuleStatus::Fail,
60                message: Some("App is missing UILaunchStoryboardName.".to_string()),
61                evidence: Some("UILaunchStoryboardName key missing from Info.plist".to_string()),
62            });
63        }
64
65        Ok(RuleReport {
66            status: RuleStatus::Pass,
67            message: None,
68            evidence: None,
69        })
70    }
71}