use super::types::{CheckItem, Evidence, EvidenceType, Severity};
use std::path::Path;
use std::time::Instant;
pub fn evaluate_all(project_path: &Path) -> Vec<CheckItem> {
vec![
check_data_residency_boundary(project_path),
check_data_inventory_completeness(project_path),
check_privacy_preserving_computation(project_path),
check_federated_learning_isolation(project_path),
check_supply_chain_provenance(project_path),
check_vpc_isolation(project_path),
check_data_classification_enforcement(project_path),
check_consent_purpose_limitation(project_path),
check_rtbf_compliance(project_path),
check_cross_border_logging(project_path),
check_model_weight_sovereignty(project_path),
check_inference_classification(project_path),
check_audit_log_immutability(project_path),
check_third_party_isolation(project_path),
check_secure_computation(project_path),
]
}
pub fn check_data_residency_boundary(project_path: &Path) -> CheckItem {
let start = Instant::now();
let mut item = CheckItem::new(
"SDG-01",
"Data Residency Boundary Enforcement",
"Sovereign-critical data never crosses geographic boundaries",
)
.with_severity(Severity::Critical)
.with_tps("Jidoka — automatic boundary violation detection");
let config_files = [
project_path.join("config/residency.yaml"),
project_path.join("config/residency.toml"),
project_path.join(".sovereignty/residency.yaml"),
];
let has_residency_config = config_files.iter().any(|p| p.exists());
let infra_files = [
project_path.join("infrastructure/vpc.tf"),
project_path.join("terraform/vpc.tf"),
project_path.join("infra/network.yaml"),
];
let has_network_isolation = infra_files.iter().any(|p| p.exists());
let has_residency_checks = check_for_pattern(
project_path,
&["residency", "region_check", "boundary_enforce", "geo_fence"],
);
item = item.with_evidence(Evidence {
evidence_type: EvidenceType::StaticAnalysis,
description: format!(
"Residency: config={}, network_isolation={}, code_checks={}",
has_residency_config, has_network_isolation, has_residency_checks
),
data: None,
files: Vec::new(),
});
let is_cli_only = !has_network_code(project_path);
item = apply_check_outcome(
item,
&[
(has_residency_config && has_network_isolation, None),
(
has_residency_config || has_residency_checks,
Some("Partial residency enforcement (missing network isolation)"),
),
(is_cli_only, None),
(true, Some("No explicit residency configuration")),
],
);
item.finish_timed(start)
}
pub fn check_data_inventory_completeness(project_path: &Path) -> CheckItem {
let start = Instant::now();
let mut item = CheckItem::new(
"SDG-02",
"Data Inventory Completeness",
"All data has documented purpose, classification, and lifecycle",
)
.with_severity(Severity::Major)
.with_tps("Muda (Inventory waste) — prevent data hoarding");
let inventory_files = [
project_path.join("data/inventory.yaml"),
project_path.join("docs/data-catalog.md"),
project_path.join(".datasheets/"),
project_path.join("data/schema/"),
];
let has_inventory = inventory_files.iter().any(|p| p.exists());
let has_classification = check_for_pattern(
project_path,
&["DataClassification", "data_class", "classification_level"],
);
let has_lifecycle = check_for_pattern(
project_path,
&["lifecycle_policy", "retention_days", "data_ttl", "expiration"],
);
item = item.with_evidence(Evidence {
evidence_type: EvidenceType::StaticAnalysis,
description: format!(
"Data inventory: catalog={}, classification={}, lifecycle={}",
has_inventory, has_classification, has_lifecycle
),
data: None,
files: Vec::new(),
});
let handles_data = check_for_pattern(project_path, &["DataFrame", "Dataset", "DataLoader"]);
item = apply_check_outcome(
item,
&[
(has_inventory && has_classification && has_lifecycle, None),
(
has_inventory || has_classification,
Some("Partial data inventory (missing lifecycle or classification)"),
),
(!handles_data, None),
(true, Some("No data inventory documentation")),
],
);
item.finish_timed(start)
}
pub fn check_privacy_preserving_computation(project_path: &Path) -> CheckItem {
let start = Instant::now();
let mut item = CheckItem::new(
"SDG-03",
"Privacy-Preserving Computation",
"Differential privacy correctly implemented",
)
.with_severity(Severity::Major)
.with_tps("Poka-Yoke — privacy by design");
let has_dp = check_for_pattern(
project_path,
&[
"differential_privacy",
"epsilon",
"privacy_budget",
"laplace_noise",
"gaussian_mechanism",
],
);
let has_budget_tracking =
check_for_pattern(project_path, &["privacy_accountant", "budget_consumed", "composition"]);
let has_privacy_tests = check_for_test_pattern(project_path, &["privacy", "dp_test"]);
item = item.with_evidence(Evidence {
evidence_type: EvidenceType::StaticAnalysis,
description: format!(
"Privacy: dp_impl={}, budget_tracking={}, tests={}",
has_dp, has_budget_tracking, has_privacy_tests
),
data: None,
files: Vec::new(),
});
let needs_privacy = check_for_pattern(project_path, &["pii", "personal_data", "gdpr"]);
item = apply_check_outcome(
item,
&[
(has_dp && has_budget_tracking && has_privacy_tests, None),
(has_dp, Some("DP implemented but missing budget tracking or tests")),
(!needs_privacy, None),
(true, Some("PII handling without differential privacy")),
],
);
item.finish_timed(start)
}
pub fn check_federated_learning_isolation(project_path: &Path) -> CheckItem {
let start = Instant::now();
let mut item = CheckItem::new(
"SDG-04",
"Federated Learning Client Isolation",
"FL clients send only model updates, never raw data",
)
.with_severity(Severity::Critical)
.with_tps("Jidoka — client-side enforcement");
let has_fl = check_for_pattern(
project_path,
&["federated", "FederatedClient", "model_update", "gradient_only"],
);
let has_secure_agg = check_for_pattern(
project_path,
&["secure_aggregation", "SecureAggregator", "encrypted_gradient"],
);
let has_isolation_tests =
check_for_test_pattern(project_path, &["client_isolation", "no_raw_data"]);
item = item.with_evidence(Evidence {
evidence_type: EvidenceType::StaticAnalysis,
description: format!(
"FL isolation: fl_impl={}, secure_agg={}, tests={}",
has_fl, has_secure_agg, has_isolation_tests
),
data: None,
files: Vec::new(),
});
item = apply_check_outcome(
item,
&[
(!has_fl, None),
(has_fl && has_secure_agg && has_isolation_tests, None),
(
has_fl && has_secure_agg,
Some("FL with secure aggregation (missing isolation tests)"),
),
(true, Some("FL without secure aggregation")),
],
);
item.finish_timed(start)
}
pub fn check_supply_chain_provenance(project_path: &Path) -> CheckItem {
let start = Instant::now();
let mut item = CheckItem::new(
"SDG-05",
"Supply Chain Provenance (AI BOM)",
"All model weights and data have verified provenance",
)
.with_severity(Severity::Critical)
.with_tps("Jidoka — supply chain circuit breaker");
let bom_files = [
project_path.join("ai-bom.json"),
project_path.join("sbom.json"),
project_path.join("bom.xml"),
project_path.join(".sbom/"),
];
let has_bom = bom_files.iter().any(|p| p.exists());
let cargo_toml = project_path.join("Cargo.toml");
let has_audit = cargo_toml
.exists()
.then(|| std::fs::read_to_string(&cargo_toml).ok())
.flatten()
.map(|c| c.contains("cargo-deny") || c.contains("cargo-audit"))
.unwrap_or(false);
let deny_toml = project_path.join("deny.toml");
let has_deny_config = deny_toml.exists();
let has_signature_check = check_for_pattern(
project_path,
&["verify_signature", "Ed25519", "sign_model", "provenance"],
);
item = item.with_evidence(Evidence {
evidence_type: EvidenceType::StaticAnalysis,
description: format!(
"Supply chain: bom={}, audit={}, deny={}, signatures={}",
has_bom, has_audit, has_deny_config, has_signature_check
),
data: None,
files: Vec::new(),
});
item = apply_check_outcome(
item,
&[
(has_deny_config && (has_bom || has_signature_check), None),
(has_deny_config || has_audit, Some("Dependency audit configured (missing AI BOM)")),
(true, Some("No supply chain verification configured")),
],
);
item.finish_timed(start)
}
pub fn check_vpc_isolation(project_path: &Path) -> CheckItem {
let start = Instant::now();
let mut item = CheckItem::new(
"SDG-06",
"VPC Isolation Verification",
"Compute only in compliant sovereign regions",
)
.with_severity(Severity::Major)
.with_tps("Genchi Genbutsu — verify physical location");
let iac_files = [
project_path.join("terraform/"),
project_path.join("infrastructure/"),
project_path.join("pulumi/"),
project_path.join("cloudformation/"),
];
let has_iac = iac_files.iter().any(|p| p.exists());
let has_region_policy = check_for_pattern(
project_path,
&["allowed_regions", "region_whitelist", "sovereign_region"],
);
item = item.with_evidence(Evidence {
evidence_type: EvidenceType::StaticAnalysis,
description: format!("VPC: iac={}, region_policy={}", has_iac, has_region_policy),
data: None,
files: Vec::new(),
});
item = apply_check_outcome(
item,
&[
(!has_iac, None),
(has_iac && has_region_policy, None),
(true, Some("IaC without explicit region constraints")),
],
);
item.finish_timed(start)
}
pub fn check_data_classification_enforcement(project_path: &Path) -> CheckItem {
let start = Instant::now();
let mut item = CheckItem::new(
"SDG-07",
"Data Classification Enforcement",
"Code paths enforce data classification levels",
)
.with_severity(Severity::Major)
.with_tps("Poka-Yoke — classification-based routing");
let has_type_classification = check_for_pattern(
project_path,
&["Classification", "DataTier", "SecurityLevel", "Sovereign<", "Confidential<"],
);
let has_runtime_check = check_for_pattern(
project_path,
&["check_classification", "enforce_tier", "validate_access_level"],
);
item = item.with_evidence(Evidence {
evidence_type: EvidenceType::StaticAnalysis,
description: format!(
"Classification: type_level={}, runtime={}",
has_type_classification, has_runtime_check
),
data: None,
files: Vec::new(),
});
let handles_classified =
check_for_pattern(project_path, &["sovereign", "confidential", "restricted"]);
item = apply_check_outcome(
item,
&[
(has_type_classification && has_runtime_check, None),
(
has_type_classification || has_runtime_check,
Some("Partial classification enforcement"),
),
(!handles_classified, None),
(true, Some("Classified data without enforcement")),
],
);
item.finish_timed(start)
}
pub fn check_consent_purpose_limitation(project_path: &Path) -> CheckItem {
let start = Instant::now();
let mut item = CheckItem::new(
"SDG-08",
"Consent and Purpose Limitation",
"Data usage matches documented consent scope",
)
.with_severity(Severity::Major)
.with_tps("Legal controls pillar");
let has_consent =
check_for_pattern(project_path, &["consent", "purpose_limitation", "data_usage_agreement"]);
let has_purpose_binding =
check_for_pattern(project_path, &["purpose_id", "usage_scope", "consent_scope"]);
item = item.with_evidence(Evidence {
evidence_type: EvidenceType::StaticAnalysis,
description: format!(
"Consent: management={}, purpose_binding={}",
has_consent, has_purpose_binding
),
data: None,
files: Vec::new(),
});
let handles_user_data = check_for_pattern(project_path, &["user_data", "personal", "pii"]);
item = apply_check_outcome(
item,
&[
(!handles_user_data, None),
(has_consent && has_purpose_binding, None),
(has_consent, Some("Consent tracking without purpose binding")),
(true, Some("User data handling without consent management")),
],
);
item.finish_timed(start)
}
pub fn check_rtbf_compliance(project_path: &Path) -> CheckItem {
let start = Instant::now();
let mut item = CheckItem::new(
"SDG-09",
"Right to Erasure (RTBF) Compliance",
"Deletion requests propagate through all storage",
)
.with_severity(Severity::Major)
.with_tps("Muda — data inventory hygiene");
let has_deletion = check_for_pattern(
project_path,
&["delete_user", "erasure", "rtbf", "forget_user", "cascade_delete"],
);
let has_unlearning =
check_for_pattern(project_path, &["unlearn", "model_forget", "data_removal"]);
item = item.with_evidence(Evidence {
evidence_type: EvidenceType::StaticAnalysis,
description: format!(
"RTBF: deletion_cascade={}, model_unlearning={}",
has_deletion, has_unlearning
),
data: None,
files: Vec::new(),
});
let stores_user_data = check_for_pattern(project_path, &["user_store", "persist_user", "save"]);
item = apply_check_outcome(
item,
&[
(!stores_user_data, None),
(has_deletion && has_unlearning, None),
(has_deletion, Some("Deletion without model unlearning")),
(true, Some("Data persistence without erasure mechanism")),
],
);
item.finish_timed(start)
}
pub fn check_cross_border_logging(project_path: &Path) -> CheckItem {
let start = Instant::now();
let mut item = CheckItem::new(
"SDG-10",
"Cross-Border Transfer Logging",
"All cross-border transfers logged and justified",
)
.with_severity(Severity::Major)
.with_tps("Auditability requirement");
let has_transfer_log = check_for_pattern(
project_path,
&["transfer_log", "cross_border", "data_export", "international_transfer"],
);
let has_legal_basis = check_for_pattern(
project_path,
&["legal_basis", "transfer_agreement", "adequacy_decision"],
);
item = item.with_evidence(Evidence {
evidence_type: EvidenceType::StaticAnalysis,
description: format!(
"Cross-border: logging={}, legal_basis={}",
has_transfer_log, has_legal_basis
),
data: None,
files: Vec::new(),
});
let does_transfers = has_network_code(project_path);
item = apply_check_outcome(
item,
&[
(!does_transfers, None),
(has_transfer_log && has_legal_basis, None),
(has_transfer_log, Some("Transfer logging without legal basis")),
(true, Some("Network operations without transfer logging")),
],
);
item.finish_timed(start)
}
pub fn check_model_weight_sovereignty(project_path: &Path) -> CheckItem {
let start = Instant::now();
let mut item = CheckItem::new(
"SDG-11",
"Model Weight Sovereignty",
"Weights from sovereign data remain under sovereign control",
)
.with_severity(Severity::Critical)
.with_tps("Jidoka — weight exfiltration prevention");
let has_access_control = check_for_pattern(
project_path,
&["weight_access", "model_acl", "sovereign_model", "protected_weights"],
);
let has_encryption =
check_for_pattern(project_path, &["encrypt_weights", "sealed_model", "encrypted_model"]);
let has_key_mgmt = check_for_pattern(project_path, &["key_management", "kms", "key_rotation"]);
item = item.with_evidence(Evidence {
evidence_type: EvidenceType::StaticAnalysis,
description: format!(
"Weight sovereignty: access_control={}, encryption={}, key_mgmt={}",
has_access_control, has_encryption, has_key_mgmt
),
data: None,
files: Vec::new(),
});
let handles_weights =
check_for_pattern(project_path, &["model_weights", "load_model", "save_model"]);
item = apply_check_outcome(
item,
&[
(!handles_weights, None),
(has_access_control && has_encryption, None),
(has_access_control || has_encryption, Some("Partial weight protection")),
(true, Some("Model weights without sovereignty controls")),
],
);
item.finish_timed(start)
}
pub fn check_inference_classification(project_path: &Path) -> CheckItem {
let start = Instant::now();
let mut item = CheckItem::new(
"SDG-12",
"Inference Result Classification",
"Outputs inherit classification from inputs",
)
.with_severity(Severity::Major)
.with_tps("Poka-Yoke — automatic classification propagation");
let has_inheritance = check_for_pattern(
project_path,
&["inherit_classification", "propagate_tier", "output_classification"],
);
let has_output_tagging =
check_for_pattern(project_path, &["tag_output", "classify_result", "result_tier"]);
item = item.with_evidence(Evidence {
evidence_type: EvidenceType::StaticAnalysis,
description: format!(
"Inference classification: inheritance={}, tagging={}",
has_inheritance, has_output_tagging
),
data: None,
files: Vec::new(),
});
let does_inference = check_for_pattern(project_path, &["inference", "predict", "infer"]);
item = apply_check_outcome(
item,
&[
(!does_inference, None),
(has_inheritance && has_output_tagging, None),
(has_inheritance || has_output_tagging, Some("Partial classification propagation")),
(true, Some("Inference without classification propagation")),
],
);
item.finish_timed(start)
}
pub fn check_audit_log_immutability(project_path: &Path) -> CheckItem {
let start = Instant::now();
let mut item = CheckItem::new(
"SDG-13",
"Audit Log Immutability",
"Audit logs cannot be modified or deleted",
)
.with_severity(Severity::Critical)
.with_tps("Governance layer integrity");
let has_append_only =
check_for_pattern(project_path, &["append_only", "immutable_log", "write_once"]);
let has_chaining = check_for_pattern(
project_path,
&["merkle", "hash_chain", "log_signature", "tamper_evident"],
);
let has_audit_trail =
check_for_pattern(project_path, &["audit_trail", "audit_log", "AuditEntry"]);
item = item.with_evidence(Evidence {
evidence_type: EvidenceType::StaticAnalysis,
description: format!(
"Audit immutability: append_only={}, chaining={}, trail={}",
has_append_only, has_chaining, has_audit_trail
),
data: None,
files: Vec::new(),
});
item = apply_check_outcome(
item,
&[
(has_audit_trail && has_chaining, None),
(has_audit_trail, Some("Audit trail without cryptographic verification")),
(true, Some("No immutable audit logging")),
],
);
item.finish_timed(start)
}
pub fn check_third_party_isolation(project_path: &Path) -> CheckItem {
let start = Instant::now();
let mut item = CheckItem::new(
"SDG-14",
"Third-Party API Isolation",
"No third-party API calls during sovereign operations",
)
.with_severity(Severity::Critical)
.with_tps("Jidoka — network isolation");
let has_allowlist = check_for_pattern(
project_path,
&["allowlist", "whitelist", "approved_endpoints", "sovereign_endpoints"],
);
let has_offline_mode =
check_for_pattern(project_path, &["offline_mode", "airgap", "no_network", "local_only"]);
let has_network_guard =
check_for_pattern(project_path, &["network_guard", "egress_filter", "outbound_check"]);
item = item.with_evidence(Evidence {
evidence_type: EvidenceType::StaticAnalysis,
description: format!(
"Third-party isolation: allowlist={}, offline={}, guard={}",
has_allowlist, has_offline_mode, has_network_guard
),
data: None,
files: Vec::new(),
});
let does_network = has_network_code(project_path);
item = apply_check_outcome(
item,
&[
(!does_network || has_offline_mode, None),
(has_allowlist && has_network_guard, None),
(has_allowlist, Some("Allowlist without runtime guard")),
(true, Some("Network operations without isolation controls")),
],
);
item.finish_timed(start)
}
pub fn check_secure_computation(project_path: &Path) -> CheckItem {
let start = Instant::now();
let mut item = CheckItem::new(
"SDG-15",
"Secure Computation Verification",
"Cryptographic primitives correctly implemented",
)
.with_severity(Severity::Major)
.with_tps("Formal verification requirement");
let has_he = check_for_pattern(project_path, &["homomorphic", "fhe", "seal", "paillier"]);
let has_mpc = check_for_pattern(project_path, &["mpc", "secure_multiparty", "secret_sharing"]);
let has_tee = check_for_pattern(project_path, &["sgx", "enclave", "trusted_execution", "tee"]);
let has_crypto_tests =
check_for_test_pattern(project_path, &["crypto", "encryption", "secure_compute"]);
item = item.with_evidence(Evidence {
evidence_type: EvidenceType::StaticAnalysis,
description: format!(
"Secure compute: he={}, mpc={}, tee={}, tests={}",
has_he, has_mpc, has_tee, has_crypto_tests
),
data: None,
files: Vec::new(),
});
let needs_secure_compute = has_he || has_mpc || has_tee;
item = apply_check_outcome(
item,
&[
(!needs_secure_compute, None),
(needs_secure_compute && has_crypto_tests, None),
(true, Some("Secure computation without comprehensive tests")),
],
);
item.finish_timed(start)
}
fn apply_check_outcome(item: CheckItem, checks: &[(bool, Option<&str>)]) -> CheckItem {
for &(condition, msg) in checks {
if condition {
return match msg {
Some(m) => item.partial(m),
None => item.pass(),
};
}
}
item
}
fn check_for_pattern(project_path: &Path, patterns: &[&str]) -> bool {
super::helpers::source_or_config_contains_pattern(project_path, patterns)
}
fn check_for_test_pattern(project_path: &Path, patterns: &[&str]) -> bool {
super::helpers::test_contains_pattern(project_path, patterns)
}
fn has_network_code(project_path: &Path) -> bool {
check_for_pattern(
project_path,
&["reqwest", "hyper", "tonic", "TcpStream", "HttpClient", "fetch", "grpc"],
)
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;
#[test]
fn test_evaluate_all_returns_15_items() {
let path = PathBuf::from(".");
let items = evaluate_all(&path);
assert_eq!(items.len(), 15);
}
#[test]
fn test_all_items_have_tps_principle() {
let path = PathBuf::from(".");
let items = evaluate_all(&path);
for item in items {
assert!(!item.tps_principle.is_empty(), "Item {} missing TPS principle", item.id);
}
}
#[test]
fn test_all_items_have_evidence() {
let path = PathBuf::from(".");
let items = evaluate_all(&path);
for item in items {
assert!(!item.evidence.is_empty(), "Item {} missing evidence", item.id);
}
}
#[test]
fn test_sdg_01_data_residency() {
let path = PathBuf::from(".");
let item = check_data_residency_boundary(&path);
assert_eq!(item.id, "SDG-01");
assert_eq!(item.severity, Severity::Critical);
}
#[test]
fn test_sdg_05_supply_chain() {
let path = PathBuf::from(".");
let item = check_supply_chain_provenance(&path);
assert_eq!(item.id, "SDG-05");
assert_eq!(item.severity, Severity::Critical);
}
#[test]
fn test_sdg_13_audit_log() {
let path = PathBuf::from(".");
let item = check_audit_log_immutability(&path);
assert_eq!(item.id, "SDG-13");
assert_eq!(item.severity, Severity::Critical);
}
#[test]
fn test_sdg_02_data_inventory() {
let path = PathBuf::from(".");
let item = check_data_inventory_completeness(&path);
assert_eq!(item.id, "SDG-02");
}
#[test]
fn test_sdg_03_privacy_preserving() {
let path = PathBuf::from(".");
let item = check_privacy_preserving_computation(&path);
assert_eq!(item.id, "SDG-03");
}
#[test]
fn test_sdg_04_federated_learning() {
let path = PathBuf::from(".");
let item = check_federated_learning_isolation(&path);
assert_eq!(item.id, "SDG-04");
}
#[test]
fn test_sdg_06_vpc_isolation() {
let path = PathBuf::from(".");
let item = check_vpc_isolation(&path);
assert_eq!(item.id, "SDG-06");
}
#[test]
fn test_sdg_07_data_classification() {
let path = PathBuf::from(".");
let item = check_data_classification_enforcement(&path);
assert_eq!(item.id, "SDG-07");
}
#[test]
fn test_sdg_08_consent_purpose() {
let path = PathBuf::from(".");
let item = check_consent_purpose_limitation(&path);
assert_eq!(item.id, "SDG-08");
}
#[test]
fn test_sdg_09_rtbf_compliance() {
let path = PathBuf::from(".");
let item = check_rtbf_compliance(&path);
assert_eq!(item.id, "SDG-09");
}
#[test]
fn test_sdg_10_cross_border() {
let path = PathBuf::from(".");
let item = check_cross_border_logging(&path);
assert_eq!(item.id, "SDG-10");
}
#[test]
fn test_sdg_11_model_weight() {
let path = PathBuf::from(".");
let item = check_model_weight_sovereignty(&path);
assert_eq!(item.id, "SDG-11");
}
#[test]
fn test_sdg_12_inference_classification() {
let path = PathBuf::from(".");
let item = check_inference_classification(&path);
assert_eq!(item.id, "SDG-12");
}
#[test]
fn test_sdg_14_third_party() {
let path = PathBuf::from(".");
let item = check_third_party_isolation(&path);
assert_eq!(item.id, "SDG-14");
}
#[test]
fn test_sdg_15_secure_computation() {
let path = PathBuf::from(".");
let item = check_secure_computation(&path);
assert_eq!(item.id, "SDG-15");
}
#[test]
fn test_nonexistent_path() {
let path = PathBuf::from("/nonexistent/path");
let items = evaluate_all(&path);
assert_eq!(items.len(), 15);
}
#[test]
fn test_temp_dir_with_privacy_lib() {
let temp_dir = std::env::temp_dir().join("test_privacy_lib");
let _ = std::fs::remove_dir_all(&temp_dir);
std::fs::create_dir_all(&temp_dir).expect("mkdir failed");
std::fs::write(
temp_dir.join("Cargo.toml"),
r#"
[package]
name = "test"
version = "0.1.0"
[dependencies]
differential-privacy = "0.1"
"#,
)
.expect("unexpected failure");
let item = check_privacy_preserving_computation(&temp_dir);
assert_eq!(item.id, "SDG-03");
let _ = std::fs::remove_dir_all(&temp_dir);
}
#[test]
fn test_temp_dir_with_data_types() {
let temp_dir = std::env::temp_dir().join("test_data_types");
let _ = std::fs::remove_dir_all(&temp_dir);
std::fs::create_dir_all(temp_dir.join("src")).expect("mkdir failed");
std::fs::write(
temp_dir.join("src/lib.rs"),
r#"
pub struct DataInventory {
pub pii: bool,
pub classification: String,
}
"#,
)
.expect("unexpected failure");
let item = check_data_inventory_completeness(&temp_dir);
assert_eq!(item.id, "SDG-02");
let _ = std::fs::remove_dir_all(&temp_dir);
}
#[test]
fn test_temp_dir_with_audit_logging() {
let temp_dir = std::env::temp_dir().join("test_audit_log");
let _ = std::fs::remove_dir_all(&temp_dir);
std::fs::create_dir_all(temp_dir.join("src")).expect("mkdir failed");
std::fs::write(
temp_dir.join("src/lib.rs"),
r#"
pub struct AuditLog {
pub append_only: bool,
pub immutable: bool,
}
"#,
)
.expect("unexpected failure");
let item = check_audit_log_immutability(&temp_dir);
assert_eq!(item.id, "SDG-13");
let _ = std::fs::remove_dir_all(&temp_dir);
}
#[test]
fn test_all_have_severity() {
let path = PathBuf::from(".");
let items = evaluate_all(&path);
for item in items {
assert!(
item.severity == Severity::Critical
|| item.severity == Severity::Major
|| item.severity == Severity::Minor
);
}
}
}