diff --git a/crates/omnigraph-cli/src/main.rs b/crates/omnigraph-cli/src/main.rs index 91becc6..cc73f3f 100644 --- a/crates/omnigraph-cli/src/main.rs +++ b/crates/omnigraph-cli/src/main.rs @@ -3457,6 +3457,32 @@ cli: assert_eq!(context.graph_id, "local"); } + #[test] + fn graph_identity_resolve_policy_context_server_graph_uses_graph_key_when_cli_graph_absent() { + let temp = tempdir().unwrap(); + let config_path = temp.path().join("omnigraph.yaml"); + fs::write( + &config_path, + r#" +project: + name: misleading-project +graphs: + local: + uri: /tmp/local-policy-graph.omni + policy: + file: ./server-policy.yaml +server: + graph: local +"#, + ) + .unwrap(); + + let config = load_config(Some(&config_path)).unwrap(); + let context = resolve_policy_context(&config).unwrap(); + assert_eq!(context.graph_id, "local"); + assert!(context.policy_file.ends_with("server-policy.yaml")); + } + #[test] fn graph_identity_resolve_cli_graph_named_target_uses_graph_key_not_project_name_or_uri() { let temp = tempdir().unwrap(); diff --git a/crates/omnigraph-cli/tests/system_local.rs b/crates/omnigraph-cli/tests/system_local.rs index f735e07..4fc3e9a 100644 --- a/crates/omnigraph-cli/tests/system_local.rs +++ b/crates/omnigraph-cli/tests/system_local.rs @@ -87,6 +87,28 @@ query: ) } +fn local_policy_server_graph_config(graph: &SystemGraph) -> String { + format!( + "\ +project: + name: policy-e2e-local +graphs: + local: + uri: {} + policy: + file: ./policy.yaml +server: + graph: local +cli: + branch: main +query: + roots: + - . +", + yaml_string(&graph.path().to_string_lossy()) + ) +} + fn insert_person_query(graph: &SystemGraph, name: &str) -> std::path::PathBuf { graph.write_query( name, @@ -1001,40 +1023,46 @@ query vector_search($q: String) { fn local_cli_policy_tooling_is_end_to_end() { // Sanity check for the read-only policy CLI surfaces. These don't // mutate the graph; they parse and evaluate the effective policy for - // the `cli.graph` selection, including per-graph policy files. + // named graph selections, including per-graph policy files. let graph = SystemGraph::loaded(); let config = graph.write_config("omnigraph-policy.yaml", &local_policy_config(&graph)); + let server_graph_config = graph.write_config( + "omnigraph-policy-server.yaml", + &local_policy_server_graph_config(&graph), + ); graph.write_config("policy.yaml", POLICY_E2E_YAML); graph.write_config("policy.tests.yaml", POLICY_E2E_TESTS_YAML); - let validate = output_success( - cli() - .arg("policy") - .arg("validate") - .arg("--config") - .arg(&config), - ); - assert!(stdout_string(&validate).contains("policy valid:")); + for config in [&config, &server_graph_config] { + let validate = output_success( + cli() + .arg("policy") + .arg("validate") + .arg("--config") + .arg(config), + ); + assert!(stdout_string(&validate).contains("policy valid:")); - let tests = output_success(cli().arg("policy").arg("test").arg("--config").arg(&config)); - assert!(stdout_string(&tests).contains("policy tests passed: 2 cases")); + let tests = output_success(cli().arg("policy").arg("test").arg("--config").arg(config)); + assert!(stdout_string(&tests).contains("policy tests passed: 2 cases")); - let explain = output_success( - cli() - .arg("policy") - .arg("explain") - .arg("--config") - .arg(&config) - .arg("--actor") - .arg("act-bruno") - .arg("--action") - .arg("change") - .arg("--branch") - .arg("main"), - ); - let explain_stdout = stdout_string(&explain); - assert!(explain_stdout.contains("decision: deny")); - assert!(explain_stdout.contains("branch: main")); + let explain = output_success( + cli() + .arg("policy") + .arg("explain") + .arg("--config") + .arg(config) + .arg("--actor") + .arg("act-bruno") + .arg("--action") + .arg("change") + .arg("--branch") + .arg("main"), + ); + let explain_stdout = stdout_string(&explain); + assert!(explain_stdout.contains("decision: deny")); + assert!(explain_stdout.contains("branch: main")); + } } #[test]