mirror of
https://github.com/ModernRelay/omnigraph.git
synced 2026-06-24 02:38:06 +02:00
mr-668: split PolicyEngine::load into kind-typed loaders
Pre-fix, every caller of `PolicyEngine::load(path, graph_id)` passed *some* `graph_id` argument — even when the policy was server-scoped and Cedar's resolution would never touch a Graph entity. The server-level loader at lib.rs passed the meaningless sentinel `"server"`. A graph policy file containing a `graph_list` rule compiled fine; a server policy file containing a `read` rule compiled fine. Both silently no-op'd at request time because the engine kind and the rule's resource kind disagreed. Correct-by-design fix: replace `load` with two kind-typed loaders. * `PolicyEngine::load_graph(path, graph_id)` — for per-graph policy files. Rejects any rule whose action `resource_kind()` is `Server`. * `PolicyEngine::load_server(path)` — for server-level policy files. Takes no `graph_id`: server-scoped actions resolve against the singleton `Omnigraph::Server::"root"` entity, never a Graph. Rejects any rule whose action `resource_kind()` is `Graph`. The old `load` is hard-deleted in the same commit because every in-tree consumer migrates here (no semver promise on the workspace crate, no external pinners). New `PolicyEngineKind` enum types the loader's intent; `validate_kind_alignment` is the load-time check that closes the "wrong action, wrong file, silent no-op" class — operators get a load-time error instead of confused-and- silent behavior at request time. Callsites migrated: * server lib.rs:374 (single-mode per-graph) → load_graph * server lib.rs:1065 (multi-mode server) → load_server * server lib.rs:1103 (multi-mode per-graph) → load_graph * CLI main.rs:732 (resolve_policy_engine) → load_graph * tests/server.rs ×5 (4 graph, 1 server) → load_graph/load_server * policy_engine_chassis.rs → load_graph Four new in-source tests pin the contract: both rejection paths and both positive paths. Closes the "operator puts an action in the wrong file and the rule silently never matches" class. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
67a46528ef
commit
4e2f18a95e
5 changed files with 228 additions and 13 deletions
|
|
@ -371,7 +371,7 @@ impl AppState {
|
|||
let uri = uri.into();
|
||||
let db = Omnigraph::open(&uri).await?;
|
||||
let policy_engine = match policy_file {
|
||||
Some(path) => Some(PolicyEngine::load(path, &uri)?),
|
||||
Some(path) => Some(PolicyEngine::load_graph(path, &uri)?),
|
||||
None => None,
|
||||
};
|
||||
if policy_engine.is_some() && bearer_tokens.is_empty() {
|
||||
|
|
@ -1062,7 +1062,7 @@ async fn open_multi_graph_state(
|
|||
// resource-model refactor maps to the singleton
|
||||
// `Omnigraph::Server::"root"` entity at evaluation time.
|
||||
let server_policy = match server_policy_file {
|
||||
Some(path) => Some(PolicyEngine::load(path, "server")?),
|
||||
Some(path) => Some(PolicyEngine::load_server(path)?),
|
||||
None => None,
|
||||
};
|
||||
|
||||
|
|
@ -1100,7 +1100,7 @@ async fn open_single_graph(cfg: GraphStartupConfig) -> Result<Arc<GraphHandle>>
|
|||
|
||||
let (policy_arc, db) = match &cfg.policy_file {
|
||||
Some(path) => {
|
||||
let policy = PolicyEngine::load(path, graph_id.as_str())?;
|
||||
let policy = PolicyEngine::load_graph(path, graph_id.as_str())?;
|
||||
let policy_arc: Arc<PolicyEngine> = Arc::new(policy);
|
||||
let checker = Arc::clone(&policy_arc) as Arc<dyn omnigraph_policy::PolicyChecker>;
|
||||
(Some(policy_arc), db.with_policy(checker))
|
||||
|
|
|
|||
|
|
@ -3592,7 +3592,7 @@ async fn ingest_per_actor_admission_cap_returns_429() {
|
|||
let policy_path = temp.path().join("policy.yaml");
|
||||
fs::write(&policy_path, permit_all_policy_yaml(&["act-flooder"])).unwrap();
|
||||
let policy_engine =
|
||||
omnigraph_server::PolicyEngine::load(&policy_path, graph.to_string_lossy().as_ref())
|
||||
omnigraph_server::PolicyEngine::load_graph(&policy_path, graph.to_string_lossy().as_ref())
|
||||
.unwrap();
|
||||
let state = AppState::new_single(
|
||||
graph.to_string_lossy().to_string(),
|
||||
|
|
@ -3716,7 +3716,7 @@ async fn engine_layer_policy_fires_via_direct_arc_omnigraph_from_new_single() {
|
|||
let policy_path = temp.path().join("policy.yaml");
|
||||
fs::write(&policy_path, permit_all_policy_yaml(&["act-allowed"])).unwrap();
|
||||
let policy_engine =
|
||||
omnigraph_server::PolicyEngine::load(&policy_path, graph.to_string_lossy().as_ref())
|
||||
omnigraph_server::PolicyEngine::load_graph(&policy_path, graph.to_string_lossy().as_ref())
|
||||
.unwrap();
|
||||
|
||||
let workload = omnigraph_server::workload::WorkloadController::new(100, 1_000_000_000);
|
||||
|
|
@ -3940,7 +3940,7 @@ async fn build_parity_graph() -> (tempfile::TempDir, PathBuf, PathBuf) {
|
|||
}
|
||||
|
||||
async fn sdk_change_decision(graph: &Path, policy_path: &Path, actor: &str) -> ParityDecision {
|
||||
let policy = PolicyEngine::load(policy_path, graph.to_string_lossy().as_ref()).unwrap();
|
||||
let policy = PolicyEngine::load_graph(policy_path, graph.to_string_lossy().as_ref()).unwrap();
|
||||
let db = Omnigraph::open(graph.to_str().unwrap())
|
||||
.await
|
||||
.unwrap()
|
||||
|
|
@ -4008,7 +4008,7 @@ async fn http_change_decision(
|
|||
}
|
||||
|
||||
async fn sdk_merge_decision(graph: &Path, policy_path: &Path, actor: &str) -> ParityDecision {
|
||||
let policy = PolicyEngine::load(policy_path, graph.to_string_lossy().as_ref()).unwrap();
|
||||
let policy = PolicyEngine::load_graph(policy_path, graph.to_string_lossy().as_ref()).unwrap();
|
||||
let db = Omnigraph::open(graph.to_str().unwrap())
|
||||
.await
|
||||
.unwrap()
|
||||
|
|
@ -4878,7 +4878,7 @@ rules:
|
|||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
let server_policy = PolicyEngine::load(&policy_path, "server").unwrap();
|
||||
let server_policy = PolicyEngine::load_server(&policy_path).unwrap();
|
||||
|
||||
let tokens = vec![
|
||||
("act-andrew".to_string(), "andrew-token".to_string()),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue