//! End-to-end integration test: spawn `jclaw-policyd` as a child //! process and drive it through PolicyClient. The binary is built by //! Cargo as a sibling of the test artefact under `target//`. use jouleclaw_policy::{ Action, AgentId, AgentScope, FsMode, Policy, PolicyEngine, Rule, }; use jouleclaw_policy_ipc::PolicyClient; use std::path::PathBuf; fn binary_path() -> PathBuf { // CARGO_BIN_EXE_ is set by Cargo when running integration // tests of a crate that declares a [[bin]] target. let p = env!("CARGO_BIN_EXE_jclaw-policyd"); PathBuf::from(p) } #[test] fn evaluate_round_trips_through_a_child_process() { let client = PolicyClient::spawn(binary_path()).expect("spawn jclaw-policyd"); // Server boots with the empty deny-by-default policy. let decision = client.evaluate( &AgentId::new("did:key:zA"), &Action::filesystem("/x", FsMode::Read), ); assert!(decision.is_deny(), "empty policy → deny-by-default"); } #[test] fn install_policy_over_ipc_then_evaluate_uses_new_rules() { let client = PolicyClient::spawn(binary_path()).expect("spawn jclaw-policyd"); let new = Policy::new_at_version( vec![Rule::allow("read-workspace", AgentScope::Any) .filesystem("/workspace/**", [FsMode::Read])], 2, ); let v = client.install_policy(new).expect("install"); assert_eq!(v, 2); assert_eq!(client.policy_version(), 2); let allowed = client.evaluate( &AgentId::new("did:key:zA"), &Action::filesystem("/workspace/notes.md", FsMode::Read), ); assert!(allowed.is_allow()); let denied = client.evaluate( &AgentId::new("did:key:zA"), &Action::filesystem("/etc/passwd", FsMode::Read), ); assert!(denied.is_deny()); } #[test] fn audit_log_is_visible_over_ipc() { let client = PolicyClient::spawn(binary_path()).expect("spawn jclaw-policyd"); let _ = client.evaluate( &AgentId::new("did:key:zA"), &Action::filesystem("/x", FsMode::Read), ); let _ = client.evaluate( &AgentId::new("did:key:zA"), &Action::filesystem("/y", FsMode::Read), ); let log = client.audit(); assert_eq!(log.len(), 2); assert_eq!(log[0].sequence, 1); assert_eq!(log[1].sequence, 2); let after = client.audit_since(1); assert_eq!(after.len(), 1); assert_eq!(after[0].sequence, 2); }