//! Golden Path Loop Tests (Bless → Export → Import → Scan with Policy Source). use crate::*; #[tokio::test] async fn test_golden_path_bless_export_import_scan() { // This tests the full "Golden Path" loop: // 1. Project A: Bless a pattern as the authoritative standard // 2. Export as Trust Pack // 3. Project B: Import the Trust Pack // 4. Scan shows policy source attribution let temp_dir_a = tempfile::Builder::new().prefix("aphoria_golden_a").tempdir().expect("create temp dir A"); let temp_dir_b = tempfile::Builder::new().prefix("aphoria_golden_b").tempdir().expect("create temp dir B"); // ========== Project A: Bless a pattern ========== let mut config_a = AphoriaConfig::default(); config_a.episteme.data_dir = temp_dir_a.path().join(".aphoria").join("db"); // Create .aphoria directory for the agent key let aphoria_dir_a = temp_dir_a.path().join(".aphoria"); std::fs::create_dir_all(&aphoria_dir_a).expect("create .aphoria dir A"); // Open LocalEpisteme and bless a pattern { let mut episteme = crate::episteme::LocalEpisteme::open(&config_a, temp_dir_a.path()) .await .expect("open A"); // Create blessed assertion (not "acknowledged", but the actual predicate "enabled") let claim = ExtractedClaim { concept_path: "code://rust/acme/grpc/tls".to_string(), predicate: "enabled".to_string(), value: stemedb_core::types::ObjectValue::Boolean(true), file: "aphoria_bless".to_string(), line: 0, matched_text: "Blessed: enabled = true".to_string(), confidence: 1.0, description: "All services MUST use mTLS".to_string(), }; episteme.ingest_claims(&[claim]).await.expect("ingest blessed claim"); episteme.shutdown().await; } // ========== Export as Trust Pack ========== let pack_path = temp_dir_a.path().join("acme-standard.pack"); // We need to directly create a pack since export_policy uses current_dir() let signing_key = crate::bridge::load_or_generate_key(temp_dir_a.path()).expect("load key A"); // Create a blessed assertion for the pack using the bridge helper let blessed_claim = ExtractedClaim { concept_path: "code://rust/acme/grpc/tls".to_string(), predicate: "enabled".to_string(), value: stemedb_core::types::ObjectValue::Boolean(true), file: "aphoria_bless".to_string(), line: 0, matched_text: "Blessed: enabled = true".to_string(), confidence: 1.0, description: "All services MUST use mTLS".to_string(), }; let timestamp = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .map(|d| d.as_secs()) .unwrap_or(0); let blessed_assertion = crate::bridge::claim_to_assertion(&blessed_claim, &signing_key, timestamp); let pack = crate::policy::TrustPack::new( "Acme Security Standard".to_string(), "1.0.0".to_string(), vec![blessed_assertion], vec![], // No aliases &signing_key, ) .expect("create pack"); pack.save(&pack_path).expect("save pack"); // ========== Project B: Import and scan ========== let mut config_b = AphoriaConfig::default(); config_b.episteme.data_dir = temp_dir_b.path().join(".aphoria").join("db"); // Add the policy to config for scanning config_b.policies = vec![pack_path.to_string_lossy().to_string()]; // Create project B with code that DISABLES TLS (conflicts with blessed pattern) let src_dir_b = temp_dir_b.path().join("src"); std::fs::create_dir_all(&src_dir_b).expect("create src dir B"); std::fs::write( src_dir_b.join("server.rs"), r#" fn create_server() -> Result { // Disabling TLS - should conflict with blessed pattern let server = tonic::transport::Server::builder() .tls_config(None) // TLS disabled .build()?; Ok(server) } "#, ) .expect("write file B"); std::fs::write( temp_dir_b.path().join("Cargo.toml"), r#"[package] name = "projectb" version = "0.1.0" "#, ) .expect("write cargo.toml B"); // Create .aphoria directory for project B let aphoria_dir_b = temp_dir_b.path().join(".aphoria"); std::fs::create_dir_all(&aphoria_dir_b).expect("create .aphoria dir B"); // Run ephemeral scan with the imported policy let args = ScanArgs { path: temp_dir_b.path().to_path_buf(), format: "table".to_string(), exit_code_enabled: false, mode: ScanMode::Ephemeral, debug: false, sync: false, file_source: FileSource::All, benchmark: false, show_claims: false, }; let result = run_scan(args, &config_b).await.expect("scan should succeed"); // Verify the pack was loaded and policy source is tracked // The scan should show conflicts where policy_source is populated // Note: The current extractors may not extract the exact pattern we blessed, // so we mainly verify the policy ingestion worked // The key assertion: policies are loaded and can be queried // Let's verify the policy manager loaded the pack correctly let policy_manager = crate::policy::PolicyManager::new(&config_b.corpus.cache_dir); let policies = policy_manager.load_policies(&config_b.policies).expect("load policies"); assert_eq!(policies.len(), 1, "Should have loaded 1 policy pack"); assert_eq!(policies[0].header.name, "Acme Security Standard"); assert_eq!(policies[0].header.version, "1.0.0"); assert_eq!(policies[0].assertions.len(), 1); assert_eq!(policies[0].assertions[0].subject, "code://rust/acme/grpc/tls"); assert_eq!(policies[0].assertions[0].predicate, "enabled"); // Verify the scan completed (even if no specific conflicts match our blessed pattern) assert!(result.files_scanned > 0, "Should have scanned files"); } #[tokio::test] async fn test_bless_args_value_parsing() { // Test the parse_value function for different value types use crate::policy_ops::parse_value; // Boolean values assert_eq!(parse_value("true"), stemedb_core::types::ObjectValue::Boolean(true)); assert_eq!(parse_value("false"), stemedb_core::types::ObjectValue::Boolean(false)); assert_eq!(parse_value("TRUE"), stemedb_core::types::ObjectValue::Boolean(true)); assert_eq!(parse_value("False"), stemedb_core::types::ObjectValue::Boolean(false)); // Numeric values assert_eq!(parse_value("42"), stemedb_core::types::ObjectValue::Number(42.0)); assert_eq!(parse_value("2.71"), stemedb_core::types::ObjectValue::Number(2.71)); assert_eq!(parse_value("-1.5"), stemedb_core::types::ObjectValue::Number(-1.5)); // Text values (anything that doesn't parse as bool or number) assert_eq!(parse_value("TLS1.3"), stemedb_core::types::ObjectValue::Text("TLS1.3".to_string())); assert_eq!( parse_value("enabled"), stemedb_core::types::ObjectValue::Text("enabled".to_string()) ); // Scientific notation should work assert_eq!(parse_value("1e10"), stemedb_core::types::ObjectValue::Number(1e10)); // NaN and Infinity should be treated as text (defensive behavior) assert_eq!(parse_value("nan"), stemedb_core::types::ObjectValue::Text("nan".to_string())); assert_eq!( parse_value("infinity"), stemedb_core::types::ObjectValue::Text("infinity".to_string()) ); assert_eq!(parse_value("inf"), stemedb_core::types::ObjectValue::Text("inf".to_string())); }