use super::*;
use crate::services::lifecycle::templates::TemplateSources;
const POLICY_WORDS: &str = "templates: roots and the record-template policy need \
[open.construction] on an open exchange or [auth.lys.construction] \
on a gated one";
fn policy(root: &std::path::Path) -> Result<TemplateSources, Box<dyn std::error::Error>> {
#[derive(serde::Deserialize)]
struct Wrap {
templates: TemplateSources,
}
let wrapped: Wrap = toml::from_str(&format!(
"[templates]\nroots = [\"{}\"]\ncommand_bytes = 1048576\nrecords = 8\narguments = 8\n\
environment_names = 8\ntext_bytes = 1024\nstop_timeout_ms = 2000\n",
root.display()
))?;
Ok(wrapped.templates)
}
fn open_construction() -> Result<crate::config::types::OpenConfig, Box<dyn std::error::Error>> {
Ok(toml::from_str(
"[construction]\nsites = 8\nsubjects = 8\nschema_bytes = 16384\ntext_bytes = 1024\n\
steps = 32\ntransitions = 128\ndrafts = 128\napprovers = 2\nsnapshot_bytes = 1048576\n\
request_bytes = 65536\n",
)?)
}
fn open_exchange() -> Result<ServerConfig, Box<dyn std::error::Error>> {
let mut config = sample_config()?;
config.auth = None;
config.cluster = None;
config.persistence_path = Some(PathBuf::from(env!("CARGO_MANIFEST_DIR")));
config.agents = Some(crate::agents::config::AgentsConfig::default());
config.limits.max_channels = Some(64);
Ok(config)
}
#[test]
fn access015_an_open_exchange_with_construction_and_a_root_policy_validates()
-> Result<(), Box<dyn std::error::Error>> {
let root = tempfile::tempdir()?;
let mut config = open_exchange()?;
config.open = Some(open_construction()?);
config.templates = policy(root.path())?;
let message = config_validation_message(validate(&mut config, None));
assert_eq!(message, "", "an open exchange with construction validates");
assert!(config.open_construction().is_some());
Ok(())
}
#[test]
fn access015_a_root_policy_without_construction_is_refused_by_the_exact_words()
-> Result<(), Box<dyn std::error::Error>> {
let root = tempfile::tempdir()?;
let mut config = open_exchange()?;
config.templates = policy(root.path())?;
let message = config_validation_message(validate(&mut config, None));
assert!(
message.lines().any(|line| line == POLICY_WORDS),
"missing {POLICY_WORDS:?} in {message:?}"
);
config.open = Some(open_construction()?);
config.templates = policy(&root.path().join("absent"))?;
let message = config_validation_message(validate(&mut config, None));
assert!(
message
.lines()
.any(|line| line == "[templates] roots must name existing absolute directories"),
"{message}"
);
Ok(())
}
#[test]
fn access015_construction_without_agents_or_a_store_is_refused_by_name()
-> Result<(), Box<dyn std::error::Error>> {
let mut config = open_exchange()?;
config.open = Some(open_construction()?);
config.agents = None;
config.persistence_path = None;
let message = config_validation_message(validate(&mut config, None));
for words in [
"[open.construction] requires top-level [agents]",
"[open.construction] requires persistence_path",
] {
assert!(
message.lines().any(|line| line == words),
"{words}: {message}"
);
}
Ok(())
}