mirror of
https://github.com/ModernRelay/omnigraph.git
synced 2026-06-12 01:45:14 +02:00
fix(cli): honor server graph for policy tooling
This commit is contained in:
parent
4bf3f3fd14
commit
b1cbb96197
4 changed files with 86 additions and 19 deletions
|
|
@ -800,21 +800,17 @@ struct ResolvedPolicyContext {
|
|||
}
|
||||
|
||||
fn resolve_policy_context(config: &OmnigraphConfig) -> Result<ResolvedPolicyContext> {
|
||||
let selected = config.cli_graph_name().map(str::to_string);
|
||||
config.resolve_graph_selection(selected.as_deref())?;
|
||||
let selected = config.resolve_policy_tooling_graph_selection()?;
|
||||
let policy_file = config
|
||||
.resolve_policy_file_for(selected.as_deref())
|
||||
.resolve_policy_file_for(selected)
|
||||
.ok_or_else(|| {
|
||||
color_eyre::eyre::eyre!(
|
||||
"policy.file or graphs.<name>.policy.file must be set in omnigraph.yaml"
|
||||
)
|
||||
})?;
|
||||
let graph_id = match selected.as_deref() {
|
||||
let graph_id = match selected {
|
||||
Some(name) => graph_resource_id_for_selection(Some(name), ""),
|
||||
None => {
|
||||
let anonymous_graph_id = anonymous_policy_graph_id(config)?;
|
||||
graph_resource_id_for_selection(None, &anonymous_graph_id)
|
||||
}
|
||||
None => graph_resource_id_for_selection(None, "default"),
|
||||
};
|
||||
Ok(ResolvedPolicyContext {
|
||||
policy_file,
|
||||
|
|
@ -871,16 +867,6 @@ fn normalize_policy_graph_uri(uri: &str) -> Result<String> {
|
|||
}
|
||||
}
|
||||
|
||||
fn anonymous_policy_graph_id(config: &OmnigraphConfig) -> Result<String> {
|
||||
let raw_uri = config
|
||||
.resolve_target_uri(None, None, config.server_graph_name())
|
||||
.or_else(|_| config.resolve_target_uri(None, None, config.cli_graph_name()));
|
||||
match raw_uri {
|
||||
Ok(uri) => normalize_policy_graph_uri(&uri),
|
||||
Err(_) => Ok("default".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_remote_bearer_token(
|
||||
config: &OmnigraphConfig,
|
||||
explicit_uri: Option<&str>,
|
||||
|
|
@ -3483,6 +3469,30 @@ server:
|
|||
assert!(context.policy_file.ends_with("server-policy.yaml"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn graph_identity_resolve_policy_context_anonymous_uses_top_level_default_identity() {
|
||||
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: ./top-policy.yaml
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let config = load_config(Some(&config_path)).unwrap();
|
||||
let context = resolve_policy_context(&config).unwrap();
|
||||
assert_eq!(context.graph_id, "default");
|
||||
assert!(context.policy_file.ends_with("top-policy.yaml"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn graph_identity_resolve_cli_graph_named_target_uses_graph_key_not_project_name_or_uri() {
|
||||
let temp = tempdir().unwrap();
|
||||
|
|
|
|||
|
|
@ -364,6 +364,10 @@ impl OmnigraphConfig {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn resolve_policy_tooling_graph_selection(&self) -> Result<Option<&str>> {
|
||||
self.resolve_graph_selection(self.cli_graph_name().or_else(|| self.server_graph_name()))
|
||||
}
|
||||
|
||||
/// The policy file that applies for a graph selection — the policy
|
||||
/// sibling of [`OmnigraphConfig::query_entries_for`], so policy and
|
||||
/// queries resolve by the same identity rule. A named graph in
|
||||
|
|
@ -692,6 +696,55 @@ policy: {}
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn policy_tooling_graph_selection_prefers_cli_then_server_and_validates() {
|
||||
let temp = tempdir().unwrap();
|
||||
fs::write(
|
||||
temp.path().join("omnigraph.yaml"),
|
||||
"graphs:\n local:\n uri: ./local.omni\n prod:\n uri: ./prod.omni\n\
|
||||
server:\n graph: local\ncli:\n graph: prod\n",
|
||||
)
|
||||
.unwrap();
|
||||
let config = load_config_in(temp.path(), None).unwrap();
|
||||
assert_eq!(
|
||||
config.resolve_policy_tooling_graph_selection().unwrap(),
|
||||
Some("prod")
|
||||
);
|
||||
|
||||
let temp = tempdir().unwrap();
|
||||
fs::write(
|
||||
temp.path().join("omnigraph.yaml"),
|
||||
"graphs:\n local:\n uri: ./local.omni\nserver:\n graph: local\n",
|
||||
)
|
||||
.unwrap();
|
||||
let config = load_config_in(temp.path(), None).unwrap();
|
||||
assert_eq!(
|
||||
config.resolve_policy_tooling_graph_selection().unwrap(),
|
||||
Some("local")
|
||||
);
|
||||
|
||||
let temp = tempdir().unwrap();
|
||||
fs::write(temp.path().join("omnigraph.yaml"), "policy: {}\n").unwrap();
|
||||
let config = load_config_in(temp.path(), None).unwrap();
|
||||
assert_eq!(config.resolve_policy_tooling_graph_selection().unwrap(), None);
|
||||
|
||||
let temp = tempdir().unwrap();
|
||||
fs::write(
|
||||
temp.path().join("omnigraph.yaml"),
|
||||
"graphs:\n local:\n uri: ./local.omni\nserver:\n graph: ghost\n",
|
||||
)
|
||||
.unwrap();
|
||||
let config = load_config_in(temp.path(), None).unwrap();
|
||||
let err = config
|
||||
.resolve_policy_tooling_graph_selection()
|
||||
.unwrap_err()
|
||||
.to_string();
|
||||
assert!(
|
||||
err.contains("ghost") && err.contains("not found"),
|
||||
"unknown server.graph must use graph-selection validation: {err}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolve_query_path_searches_config_roots() {
|
||||
let temp = tempdir().unwrap();
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ A reference for the `omnigraph` binary's command surface and `omnigraph.yaml` sc
|
|||
| `optimize` | non-destructive Lance compaction |
|
||||
| `cleanup --keep N --older-than 7d --confirm` | destructive version GC |
|
||||
| `embed` | offline JSONL embedding pipeline |
|
||||
| `policy validate \| test \| explain` | Cedar tooling |
|
||||
| `policy validate \| test \| explain` | Cedar tooling. Selects `cli.graph`, else `server.graph`, else top-level `policy.file` |
|
||||
| `version` / `-v` | print `omnigraph 0.3.x` |
|
||||
|
||||
## `omnigraph.yaml` schema
|
||||
|
|
|
|||
|
|
@ -98,6 +98,10 @@ bearer token.
|
|||
|
||||
## CLI
|
||||
|
||||
Policy tooling resolves its graph like server single-mode policy: `cli.graph`
|
||||
wins, otherwise `server.graph` is used, otherwise the top-level `policy.file`
|
||||
is validated/tested/explained as the anonymous policy.
|
||||
|
||||
- `omnigraph policy validate` — parse + count actors, exit 1 on parse error.
|
||||
- `omnigraph policy test` — run cases in `policy.tests.yaml`, exit 1 on any expectation mismatch.
|
||||
- `omnigraph policy explain --actor … --action … [--branch …] [--target-branch …]` — show decision and matched rule.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue