mod common; use std::path::PathBuf; use std::sync::Arc; use std::time::Duration; use common::MockTransport; use sgclaw::pipe::{ Action, AgentMessage, BrowserMessage, BrowserPipeTool, ExecutionSurfaceKind, Timing, }; use sgclaw::security::MacPolicy; fn test_policy() -> MacPolicy { MacPolicy::from_json_str( r#"{ "version": "1.0", "domains": { "allowed": ["oa.example.com", "erp.example.com"] }, "pipe_actions": { "allowed": ["click", "type", "navigate", "getText"], "blocked": ["eval", "executeJsInPage"] } }"#, ) .unwrap() } #[test] fn browser_tool_signs_and_sends_command_then_waits_for_response() { let transport = Arc::new(MockTransport::new(vec![BrowserMessage::Response { seq: 1, success: true, data: serde_json::json!({"text": "ok"}), aom_snapshot: vec![], timing: Timing { queue_ms: 1, exec_ms: 20, }, }])); let tool = BrowserPipeTool::new( transport.clone(), test_policy(), vec![1, 2, 3, 4, 5, 6, 7, 8], ) .with_response_timeout(Duration::from_secs(1)); let result = tool .invoke( Action::Click, serde_json::json!({ "selector": "#submit" }), "oa.example.com", ) .unwrap(); let sent = transport.sent_messages(); assert_eq!(result.seq, 1); assert_eq!(result.data, serde_json::json!({"text": "ok"})); assert_eq!(sent.len(), 1); assert!(matches!( &sent[0], AgentMessage::Command { seq, action, params, security } if *seq == 1 && action == &Action::Click && params == &serde_json::json!({"selector": "#submit"}) && security.expected_domain == "oa.example.com" && !security.hmac.is_empty() )); } #[test] fn browser_tool_rejects_action_when_mac_policy_blocks_it() { let transport = Arc::new(MockTransport::new(vec![])); let tool = BrowserPipeTool::new(transport, test_policy(), vec![1, 2, 3, 4]); let err = tool .invoke( Action::GetHtml, serde_json::json!({ "selector": "body" }), "oa.example.com", ) .unwrap_err(); assert!(err.to_string().contains("action is not allowed")); } #[test] fn browser_tool_exposes_privileged_surface_metadata_backed_by_mac_policy() { let transport = Arc::new(MockTransport::new(vec![])); let tool = BrowserPipeTool::new(transport, test_policy(), vec![1, 2, 3, 4]); let metadata = tool.surface_metadata(); assert_eq!(metadata.kind, ExecutionSurfaceKind::PrivilegedBrowserPipe); assert!(metadata.privileged); assert!(!metadata.defines_runtime_identity); assert_eq!(metadata.guard, "mac_policy"); assert_eq!( metadata.allowed_domains, vec!["oa.example.com", "erp.example.com"] ); assert_eq!( metadata.allowed_actions, vec!["click", "type", "navigate", "getText"] ); } #[test] fn default_rules_allow_zhihu_navigation() { let rules_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("resources") .join("rules.json"); let policy = MacPolicy::load_from_path(rules_path).unwrap(); policy.validate(&Action::Navigate, "www.zhihu.com").unwrap(); }