Skip to main content

ralph/config/validation/
trust.rs

1//! Project execution trust validation.
2//!
3//! Responsibilities:
4//! - Reject execution-sensitive project config when the repository is untrusted.
5//! - Detect trust-relevant settings across the base agent, plugins, and profiles.
6//!
7//! Not handled here:
8//! - Queue thresholds or git-ref validation.
9//! - Repo trust-file loading.
10//!
11//! Invariants/assumptions:
12//! - Missing trust means the repo is untrusted.
13//! - Execution-sensitive settings are intentionally broader than runner binaries alone.
14
15use super::agent::agent_has_execution_settings;
16use crate::config::{ConfigLayer, RepoTrust};
17use anyhow::{Result, bail};
18
19pub const ERR_PROJECT_EXECUTION_TRUST: &str = "Project config defines execution-sensitive settings (runner binaries, plugin runners, agent.ci_gate, and/or plugins), but this repo is not trusted. Run `ralph config trust init`, use `ralph init --trust-project-commands` when bootstrapping, create `.ralph/trust.jsonc` with {\"allow_project_commands\": true, \"trusted_at\": \"<RFC3339>\"}, or move those settings to trusted global config.";
20
21pub fn validate_project_execution_trust(
22    project_cfg: Option<&ConfigLayer>,
23    repo_trust: &RepoTrust,
24) -> Result<()> {
25    let project_needs_trust = project_cfg.is_some_and(layer_has_execution_settings);
26    if project_needs_trust && !repo_trust.is_trusted() {
27        bail!(ERR_PROJECT_EXECUTION_TRUST);
28    }
29    Ok(())
30}
31
32fn layer_has_execution_settings(layer: &ConfigLayer) -> bool {
33    if agent_has_execution_settings(&layer.agent) {
34        return true;
35    }
36    if !layer.plugins.plugins.is_empty() {
37        return true;
38    }
39    layer
40        .profiles
41        .as_ref()
42        .is_some_and(|profiles| profiles.values().any(agent_has_execution_settings))
43}