use std::path::Path;
use crate::error::{ForgeError, ForgeResult};
use crate::store::schema;
pub fn refuse_to_open_db(path: &Path) -> ForgeResult<()> {
let spec = forge_policy::DbIdentitySpec {
min_user_version: schema::FORGE_MIN_USER_VERSION,
max_user_version: schema::FORGE_MAX_USER_VERSION,
required_tables: schema::REQUIRED_TABLES,
schema_table: "forge_meta",
schema_key: "schema_hash",
expected_schema_hash: schema::forge_schema_hash(),
};
forge_policy::verify_sqlite_db_identity(path, &spec).map_err(|error| match error {
forge_policy::PolicyError::RefuseToOpenDb { reason } => {
ForgeError::RefuseToOpenDb { reason }
}
other => ForgeError::RefuseToOpenDb {
reason: other.to_string(),
},
})
}
pub fn validate_forbidden_paths(
paths: &[&str],
forbidden_patterns: &[String],
allow_test_modifications: bool,
) -> Vec<crate::error::Violation> {
let owned_paths: Vec<String> = paths.iter().map(|path| (*path).to_string()).collect();
forge_policy::validate_forbidden_paths(
&owned_paths,
forbidden_patterns,
allow_test_modifications,
)
}
pub fn validate_patch_caps(
files_changed: usize,
total_lines_changed: usize,
per_file_lines: &[usize],
max_files: usize,
max_total_lines: usize,
max_per_file: usize,
) -> Vec<crate::error::Violation> {
forge_policy::validate_patch_caps(
files_changed,
total_lines_changed,
per_file_lines,
max_files,
max_total_lines,
max_per_file,
)
}
pub fn validate_cea_no_raw_source(sig_json: &str) -> ForgeResult<()> {
let value: serde_json::Value =
serde_json::from_str(sig_json).map_err(|_| ForgeError::CeaRawSourceDetected)?;
check_value_no_raw_source(&value)
}
fn check_value_no_raw_source(value: &serde_json::Value) -> ForgeResult<()> {
match value {
serde_json::Value::Object(obj) => {
for key in &["context_before", "context_after", "raw_source", "raw_lines"] {
if obj.contains_key(*key) {
return Err(ForgeError::CeaRawSourceDetected);
}
}
if let Some(hash) = obj.get("context_hash") {
if let Some(s) = hash.as_str() {
if s.len() != 64 || !s.chars().all(|c| c.is_ascii_hexdigit()) {
return Err(ForgeError::CeaRawSourceDetected);
}
}
}
if let Some(ext) = obj.get("file_extension") {
if let Some(s) = ext.as_str() {
if s.contains('/') || s.contains('\\') || s.len() > 10 {
return Err(ForgeError::CeaRawSourceDetected);
}
}
}
for v in obj.values() {
check_value_no_raw_source(v)?;
}
}
serde_json::Value::Array(arr) => {
for v in arr {
check_value_no_raw_source(v)?;
}
}
_ => {}
}
Ok(())
}