MCPcopy Create free account
hub / github.com/NVIDIA/OpenShell / add_rule

Function add_rule

crates/openshell-policy/src/merge.rs:381–442  ·  view source on GitHub ↗
(
    policy: &mut SandboxPolicy,
    rule_name: &str,
    incoming_rule: &NetworkPolicyRule,
    warnings: &mut Vec<PolicyMergeWarning>,
)

Source from the content-addressed store, hash-verified

379}
380
381fn add_rule(
382 policy: &mut SandboxPolicy,
383 rule_name: &str,
384 incoming_rule: &NetworkPolicyRule,
385 warnings: &mut Vec<PolicyMergeWarning>,
386) -> Result<(), PolicyMergeError> {
387 if rule_name.trim().is_empty() {
388 return Err(PolicyMergeError::MissingRuleNameForAddRule);
389 }
390
391 let mut incoming_rule = incoming_rule.clone();
392 normalize_rule(&mut incoming_rule);
393 if incoming_rule.name.is_empty() {
394 incoming_rule.name = rule_name.to_string();
395 }
396
397 // Endpoint-overlap fallback: when a chunk arrives with a new rule_name
398 // that doesn't already exist, fold it into a same-host/port rule if one
399 // is present. This is intentional for user-authored policies (incremental
400 // refinements live under one rule name).
401 //
402 // Provider-injected rules (`_provider_*` — see `compose.rs::provider_rule_name`)
403 // are deliberately EXCLUDED from this fallback. Provider profiles supply a
404 // baseline layer that should stay separate from agent/user contributions;
405 // merging an agent's narrow proposal into a provider's broad rule would
406 // (a) expand the provider rule's `access` shorthand into wildcard
407 // `path: "**"` rules at the prover's input, masking the agent's narrow
408 // scope behind the existing broad coverage, and (b) silently widen the
409 // provider rule's binary list. The agent's contribution is kept on its
410 // own rule key, the prover sees the actual narrow proposal, and the
411 // reviewer gets honest signal about what's being added.
412 let target_key = if policy.network_policies.contains_key(rule_name) {
413 Some(rule_name.to_string())
414 } else {
415 let mut keys: Vec<_> = policy.network_policies.keys().cloned().collect();
416 keys.sort();
417 keys.into_iter()
418 .filter(|k| !is_provider_rule_name(k))
419 .find(|key| {
420 policy
421 .network_policies
422 .get(key)
423 .is_some_and(|existing_rule| {
424 rules_share_endpoint(existing_rule, &incoming_rule)
425 })
426 })
427 };
428
429 if let Some(key) = target_key {
430 let existing_rule = policy
431 .network_policies
432 .get_mut(&key)
433 .expect("existing rule must be present");
434 merge_rules(existing_rule, &incoming_rule, warnings)?;
435 } else {
436 policy
437 .network_policies
438 .insert(rule_name.to_string(), incoming_rule);

Callers 1

apply_operationFunction · 0.85

Calls 7

normalize_ruleFunction · 0.85
is_provider_rule_nameFunction · 0.85
rules_share_endpointFunction · 0.85
merge_rulesFunction · 0.85
contains_keyMethod · 0.80
is_emptyMethod · 0.45
getMethod · 0.45

Tested by

no test coverage detected