use crate::config::types::ServerConfig;
pub(super) fn validate_template_places(config: &ServerConfig, errors: &mut Vec<String>) {
let lys = config.auth.as_ref().and_then(|auth| auth.lys.as_ref());
if !config.templates.is_empty() && lys.is_some_and(|lys| !lys.templates.is_empty()) {
errors.push(
"templates are written once: at the top level or under [auth.lys], not both".to_owned(),
);
}
if config.templates.is_empty() {
return;
}
if config.auth.is_some() && lys.is_none() {
errors.push(
"templates: a gated exchange places services in Lys, write [auth.lys] or remove [auth]"
.to_owned(),
);
}
if config.auth.is_none()
&& let Some(policy) = &config.templates.policy
{
if config.open_construction().is_none() {
errors.push(
"templates: roots and the record-template policy need [open.construction] on an \
open exchange or [auth.lys.construction] on a gated one"
.to_owned(),
);
}
if policy.roots.is_empty()
|| policy
.roots
.iter()
.any(|root| !root.is_absolute() || !root.is_dir())
{
errors.push("[templates] roots must name existing absolute directories".to_owned());
}
}
}
pub(super) fn validate_open_construction(config: &ServerConfig, errors: &mut Vec<String>) {
let Some(limits) = config.open_construction() else {
return;
};
if config.agents.is_none() {
errors.push("[open.construction] requires top-level [agents]".to_owned());
}
if config.persistence_path.is_none() {
errors.push("[open.construction] requires persistence_path".to_owned());
}
if limits.snapshot_bytes.get() < limits.request_bytes.get() {
errors.push("open.construction.snapshot_bytes is below request_bytes".to_owned());
}
}