use std::collections::BTreeMap;
use std::fmt;
use std::path::PathBuf;
use std::str::FromStr;
use regex_lite::Regex;
use toml_edit::{DocumentMut, Item, Table, TableLike, Value};
use crate::models::{
MAX_WORKSPACE_TASK_LENSES, RedactionLevel, TASK_LENS_VERSION, TaskLens, TaskLensInput,
TaskLensOverlay, TrustClass,
};
use super::path::{PathExpander, PathExpansionError};
fn normalized_config_enum_token(input: &str) -> String {
let mut normalized = String::with_capacity(input.len());
let mut previous_was_lowercase_or_digit = false;
for character in input.trim().chars() {
match character {
'-' | '_' => {
if !normalized.ends_with('_') {
normalized.push('_');
}
previous_was_lowercase_or_digit = false;
}
ch if ch.is_ascii_uppercase() => {
if previous_was_lowercase_or_digit && !normalized.ends_with('_') {
normalized.push('_');
}
normalized.push(ch.to_ascii_lowercase());
previous_was_lowercase_or_digit = false;
}
ch => {
normalized.push(ch.to_ascii_lowercase());
previous_was_lowercase_or_digit = ch.is_ascii_lowercase() || ch.is_ascii_digit();
}
}
}
normalized
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct ConfigFile {
pub storage: StorageConfig,
pub runtime: RuntimeConfig,
pub write: WriteConfig,
pub cass: CassConfig,
pub search: SearchConfig,
pub pack: PackConfig,
pub task_lens: TaskLensConfig,
pub handoff: HandoffConfig,
pub cache: CacheConfig,
pub mesh: MeshConfig,
pub swarm: SwarmConfig,
pub graph: GraphConfig,
pub curation: CurationConfig,
pub journal: JournalConfig,
pub primer: PrimerConfig,
pub decide: DecideConfig,
pub learn: LearnConfig,
pub feedback: FeedbackConfig,
pub redaction: RedactionConfig,
pub policy: PolicyConfig,
pub privacy: PrivacyConfig,
pub trust: TrustConfig,
pub memory: MemoryConfig,
}
impl ConfigFile {
pub fn parse(input: &str) -> Result<Self, ConfigParseError> {
Self::parse_inner(input, None)
}
pub fn parse_with_expander(
input: &str,
expander: &PathExpander,
) -> Result<Self, ConfigParseError> {
Self::parse_inner(input, Some(expander))
}
fn parse_inner(input: &str, expander: Option<&PathExpander>) -> Result<Self, ConfigParseError> {
let document = input
.parse::<DocumentMut>()
.map_err(|source| ConfigParseError::Toml {
message: source.to_string(),
})?;
let parsed = Self {
storage: StorageConfig::parse(&document, expander)?,
runtime: RuntimeConfig::parse(&document)?,
write: WriteConfig::parse(&document)?,
cass: CassConfig::parse(&document)?,
search: SearchConfig::parse(&document)?,
pack: PackConfig::parse(&document)?,
task_lens: TaskLensConfig::parse(&document)?,
handoff: HandoffConfig::parse(&document)?,
cache: CacheConfig::parse(&document, expander)?,
mesh: MeshConfig::parse(&document)?,
swarm: SwarmConfig::parse(&document)?,
graph: GraphConfig::parse(&document)?,
curation: CurationConfig::parse(&document)?,
journal: JournalConfig::parse(&document)?,
primer: PrimerConfig::parse(&document)?,
decide: DecideConfig::parse(&document)?,
learn: LearnConfig::parse(&document)?,
feedback: FeedbackConfig::parse(&document)?,
redaction: RedactionConfig::parse(&document)?,
policy: PolicyConfig::parse(&document)?,
privacy: PrivacyConfig::parse(&document)?,
trust: TrustConfig::parse(&document)?,
memory: MemoryConfig::parse(&document)?,
};
validate_config_keys(&document)?;
Ok(parsed)
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct StorageConfig {
pub database_path: Option<PathBuf>,
pub index_dir: Option<PathBuf>,
pub jsonl_export: Option<bool>,
pub read_pool: ReadPoolConfig,
}
impl StorageConfig {
fn parse(
document: &DocumentMut,
expander: Option<&PathExpander>,
) -> Result<Self, ConfigParseError> {
Ok(Self {
database_path: optional_path(document, "storage", "database_path", expander)?,
index_dir: optional_path(document, "storage", "index_dir", expander)?,
jsonl_export: optional_bool(document, "storage", "jsonl_export")?,
read_pool: ReadPoolConfig::parse(document)?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct ReadPoolConfig {
pub size: Option<u64>,
pub idle_timeout_seconds: Option<u64>,
pub max_pin_duration_seconds: Option<u64>,
pub acquire_timeout_ms: Option<u64>,
pub pin_snapshot: Option<bool>,
}
impl ReadPoolConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
const SECTIONS: &[&str] = &["storage", "read_pool"];
Ok(Self {
size: optional_u64_path(document, SECTIONS, "size")?,
idle_timeout_seconds: optional_u64_path(document, SECTIONS, "idle_timeout_seconds")?,
max_pin_duration_seconds: optional_u64_path(
document,
SECTIONS,
"max_pin_duration_seconds",
)?,
acquire_timeout_ms: optional_u64_path(document, SECTIONS, "acquire_timeout_ms")?,
pin_snapshot: optional_bool_path(document, SECTIONS, "pin_snapshot")?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct RuntimeConfig {
pub daemon: Option<bool>,
pub job_budget_ms: Option<u64>,
pub import_batch_size: Option<u64>,
}
impl RuntimeConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
daemon: optional_bool(document, "runtime", "daemon")?,
job_budget_ms: optional_u64(document, "runtime", "job_budget_ms")?,
import_batch_size: optional_u64(document, "runtime", "import_batch_size")?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct WriteConfig {
pub group_commit_enabled: Option<bool>,
pub batch_window_ms: Option<u64>,
pub max_batch_size: Option<u64>,
pub max_inflight_bytes: Option<u64>,
}
impl WriteConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
group_commit_enabled: optional_bool(document, "write", "group_commit_enabled")?,
batch_window_ms: optional_u64(document, "write", "batch_window_ms")?,
max_batch_size: optional_u64(document, "write", "max_batch_size")?,
max_inflight_bytes: optional_u64(document, "write", "max_inflight_bytes")?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct CassConfig {
pub enabled: Option<bool>,
pub binary: Option<String>,
pub since: Option<String>,
pub subprocess_timeout_secs: Option<u64>,
}
impl CassConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
enabled: optional_bool(document, "cass", "enabled")?,
binary: optional_string(document, "cass", "binary")?,
since: optional_string(document, "cass", "since")?,
subprocess_timeout_secs: optional_u64(document, "cass", "subprocess_timeout_secs")?,
})
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct SearchConfig {
pub default_speed: Option<SearchSpeed>,
pub lexical_weight: Option<f64>,
pub semantic_weight: Option<f64>,
pub graph_weight: Option<f64>,
pub rerank: Option<SearchRerankMode>,
pub rerank_top_k: Option<u64>,
pub query_miss_retention_days: Option<u64>,
pub lexical_ram_tier: SearchLexicalRamTierConfig,
}
impl SearchConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
default_speed: optional_search_speed(document, "search", "default_speed")?,
lexical_weight: optional_unit_float(document, "search", "lexical_weight")?,
semantic_weight: optional_unit_float(document, "search", "semantic_weight")?,
graph_weight: optional_unit_float(document, "search", "graph_weight")?,
rerank: optional_search_rerank_mode(document, "search", "rerank")?,
rerank_top_k: optional_u64(document, "search", "rerank_top_k")?,
query_miss_retention_days: optional_u64(
document,
"search",
"query_miss_retention_days",
)?,
lexical_ram_tier: SearchLexicalRamTierConfig::parse(document)?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct SearchLexicalRamTierConfig {
pub enabled: Option<bool>,
pub request_hugepages: Option<bool>,
pub populate_on_open: Option<bool>,
}
impl SearchLexicalRamTierConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
const SECTIONS: &[&str] = &["search", "lexical_ram_tier"];
Ok(Self {
enabled: optional_bool_path(document, SECTIONS, "enabled")?,
request_hugepages: optional_bool_path(document, SECTIONS, "request_hugepages")?,
populate_on_open: optional_bool_path(document, SECTIONS, "populate_on_open")?,
})
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SearchRerankMode {
Auto,
Off,
}
impl SearchRerankMode {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::Auto => "auto",
Self::Off => "off",
}
}
}
impl FromStr for SearchRerankMode {
type Err = ConfigParseError;
fn from_str(input: &str) -> Result<Self, Self::Err> {
match normalized_config_enum_token(input).as_str() {
"auto" => Ok(Self::Auto),
"off" => Ok(Self::Off),
_ => Err(ConfigParseError::InvalidValue {
key: "search.rerank".to_string(),
value: input.to_string(),
message: "expected one of `auto` or `off`".to_string(),
}),
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SearchSpeed {
Fast,
Balanced,
Thorough,
}
impl SearchSpeed {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::Fast => "fast",
Self::Balanced => "balanced",
Self::Thorough => "thorough",
}
}
}
impl FromStr for SearchSpeed {
type Err = ConfigParseError;
fn from_str(input: &str) -> Result<Self, Self::Err> {
match normalized_config_enum_token(input).as_str() {
"fast" => Ok(Self::Fast),
"balanced" => Ok(Self::Balanced),
"thorough" => Ok(Self::Thorough),
_ => Err(ConfigParseError::InvalidValue {
key: "search.default_speed".to_string(),
value: input.to_string(),
message: "expected one of `fast`, `balanced`, or `thorough`".to_string(),
}),
}
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct PackConfig {
pub default_profile: Option<String>,
pub default_format: Option<String>,
pub default_max_tokens: Option<u64>,
pub adaptive_budget: Option<bool>,
pub mmr_lambda: Option<f64>,
pub candidate_pool: Option<u64>,
pub memory_tier_admission: Option<bool>,
pub lod_full_basis_points: Option<u64>,
pub lod_truncated_preview_basis_points: Option<u64>,
pub lod_link_only_basis_points: Option<u64>,
pub baseline_ledger_max_rows: Option<u64>,
}
impl PackConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
default_profile: optional_string(document, "pack", "default_profile")?,
default_format: optional_string(document, "pack", "default_format")?,
default_max_tokens: optional_u64(document, "pack", "default_max_tokens")?,
adaptive_budget: optional_bool(document, "pack", "adaptive_budget")?,
mmr_lambda: optional_unit_float(document, "pack", "mmr_lambda")?,
candidate_pool: optional_u64(document, "pack", "candidate_pool")?,
memory_tier_admission: optional_bool(document, "pack", "memory_tier_admission")?,
lod_full_basis_points: optional_u64(document, "pack", "lod_full_basis_points")?,
lod_truncated_preview_basis_points: optional_u64(
document,
"pack",
"lod_truncated_preview_basis_points",
)?,
lod_link_only_basis_points: optional_u64(
document,
"pack",
"lod_link_only_basis_points",
)?,
baseline_ledger_max_rows: optional_u64(document, "pack", "baseline_ledger_max_rows")?,
})
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct TaskLensConfig {
pub overrides: Vec<TaskLens>,
}
impl TaskLensConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
overrides: optional_task_lens_overrides(document)?,
})
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct HandoffConfig {
pub stale_threshold: HandoffStaleThresholdConfig,
}
impl HandoffConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
stale_threshold: HandoffStaleThresholdConfig::parse(document)?,
})
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct HandoffStaleThresholdConfig {
pub memories_added: Option<u64>,
pub any_expired_in_pack: Option<bool>,
pub content_drift_score: Option<f64>,
pub memories_revised: Option<u64>,
}
impl HandoffStaleThresholdConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
const SECTIONS: &[&str] = &["handoff", "stale_threshold"];
Ok(Self {
memories_added: optional_u64_path(document, SECTIONS, "memories_added")?,
any_expired_in_pack: optional_bool_path(document, SECTIONS, "any_expired_in_pack")?,
content_drift_score: optional_unit_float_path(
document,
SECTIONS,
"content_drift_score",
)?,
memories_revised: optional_u64_path(document, SECTIONS, "memories_revised")?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct CacheConfig {
pub pack_l2: PackL2CacheConfig,
}
impl CacheConfig {
fn parse(
document: &DocumentMut,
expander: Option<&PathExpander>,
) -> Result<Self, ConfigParseError> {
Ok(Self {
pack_l2: PackL2CacheConfig::parse(document, expander)?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct PackL2CacheConfig {
pub enabled: Option<bool>,
pub directory: Option<PathBuf>,
pub max_bytes: Option<u64>,
pub max_age_days: Option<u64>,
}
impl PackL2CacheConfig {
fn parse(
document: &DocumentMut,
expander: Option<&PathExpander>,
) -> Result<Self, ConfigParseError> {
const SECTIONS: &[&str] = &["cache", "pack_l2"];
Ok(Self {
enabled: optional_bool_path(document, SECTIONS, "enabled")?,
directory: optional_path_path(document, SECTIONS, "directory", expander)?,
max_bytes: optional_u64_path(document, SECTIONS, "max_bytes")?,
max_age_days: optional_u64_path(document, SECTIONS, "max_age_days")?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct MeshConfig {
pub enabled: Option<bool>,
pub command_mode: Option<MeshCommandMode>,
pub peer_group_bindings: Option<Vec<MeshPeerGroupBinding>>,
pub peer_policies: Option<Vec<MeshPeerPolicyConfig>>,
}
impl MeshConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
enabled: optional_bool(document, "mesh", "enabled")?,
command_mode: optional_mesh_command_mode(document, "mesh", "command_mode")?,
peer_group_bindings: optional_peer_group_bindings(document)?,
peer_policies: optional_peer_policies(document)?,
})
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub enum MeshCommandMode {
#[default]
Off,
Cache,
Revisable,
Blocking,
}
impl MeshCommandMode {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::Off => "off",
Self::Cache => "cache",
Self::Revisable => "revisable",
Self::Blocking => "blocking",
}
}
}
impl FromStr for MeshCommandMode {
type Err = ConfigParseError;
fn from_str(input: &str) -> Result<Self, Self::Err> {
match normalized_config_enum_token(input).as_str() {
"off" => Ok(Self::Off),
"cache" => Ok(Self::Cache),
"revisable" => Ok(Self::Revisable),
"blocking" => Ok(Self::Blocking),
_ => Err(ConfigParseError::InvalidValue {
key: "mesh.command_mode".to_string(),
value: input.to_string(),
message: "expected one of `off`, `cache`, `revisable`, or `blocking`".to_string(),
}),
}
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct MeshPeerGroupBinding {
pub workspace_id: Option<String>,
pub workspace_alias: Option<String>,
pub peer_group_id: Option<String>,
pub peer_group_label: Option<String>,
pub peer_ids: Option<Vec<String>>,
pub origin_workspace_ids: Option<Vec<String>>,
pub lanes: MeshLaneGrants,
pub default_action: Option<MeshLaneDecision>,
}
impl MeshPeerGroupBinding {
#[must_use]
pub fn decision_for(
&self,
local_workspace_id: &str,
peer_id: &str,
origin_workspace_id: &str,
lane: MeshLane,
) -> MeshLaneDecision {
if self.workspace_id.as_deref() != Some(local_workspace_id) {
return MeshLaneDecision::Deny;
}
if !self
.peer_ids
.as_ref()
.is_some_and(|peers| peers.iter().any(|known| known == peer_id))
{
return MeshLaneDecision::Deny;
}
if !self
.origin_workspace_ids
.as_ref()
.is_some_and(|origins| origins.iter().any(|known| known == origin_workspace_id))
{
return MeshLaneDecision::Deny;
}
self.lanes.decision(lane)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum MeshTrustLane {
LocalHuman,
PeerHumanViaPeer,
PeerAgent,
PeerDerived,
Untrusted,
}
impl MeshTrustLane {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::LocalHuman => "localHuman",
Self::PeerHumanViaPeer => "peerHumanViaPeer",
Self::PeerAgent => "peerAgent",
Self::PeerDerived => "peerDerived",
Self::Untrusted => "untrusted",
}
}
fn parse_for_key(input: &str, key: String) -> Result<Self, ConfigParseError> {
match normalized_config_enum_token(input).as_str() {
"local_human" => Ok(Self::LocalHuman),
"peer_human_via_peer" => Ok(Self::PeerHumanViaPeer),
"peer_agent" => Ok(Self::PeerAgent),
"peer_derived" => Ok(Self::PeerDerived),
"untrusted" => Ok(Self::Untrusted),
_ => Err(ConfigParseError::InvalidValue {
key,
value: input.to_string(),
message: "expected one of `localHuman`, `peerHumanViaPeer`, `peerAgent`, `peerDerived`, or `untrusted`".to_string(),
}),
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum MeshRedactionDecision {
Share,
Redact,
Deny,
}
impl MeshRedactionDecision {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::Share => "share",
Self::Redact => "redact",
Self::Deny => "deny",
}
}
fn parse_for_key(input: &str, key: String) -> Result<Self, ConfigParseError> {
match normalized_config_enum_token(input).as_str() {
"share" => Ok(Self::Share),
"redact" => Ok(Self::Redact),
"deny" => Ok(Self::Deny),
_ => Err(ConfigParseError::InvalidValue {
key,
value: input.to_string(),
message: "expected one of `share`, `redact`, or `deny`".to_string(),
}),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MeshRedactionPolicyConfig {
pub metadata: MeshRedactionDecision,
pub preview: MeshRedactionDecision,
pub body: MeshRedactionDecision,
pub embedding: MeshRedactionDecision,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MeshBodyFetchPolicyConfig {
pub allowed: bool,
pub requires_consent: bool,
pub max_bytes: Option<usize>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MeshPeerPolicyConfig {
pub policy_id: String,
pub workspace_id: String,
pub workspace_alias: Option<String>,
pub peer_id: String,
pub peer_alias: Option<String>,
pub origin_workspace_ids: Vec<String>,
pub trust_lane: MeshTrustLane,
pub import_trust_class: TrustClass,
pub allowed_lanes: MeshLaneGrants,
pub redaction: MeshRedactionPolicyConfig,
pub body_fetch: MeshBodyFetchPolicyConfig,
pub default_action: MeshLaneDecision,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum MeshLane {
Metadata,
Body,
Embedding,
GraphLink,
RevisionNotice,
CurationSignal,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub enum MeshLaneDecision {
Allow,
Quarantine,
#[default]
Deny,
}
impl MeshLaneDecision {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::Allow => "allow",
Self::Quarantine => "quarantine",
Self::Deny => "deny",
}
}
fn parse_for_key(input: &str, key: String) -> Result<Self, ConfigParseError> {
match normalized_config_enum_token(input).as_str() {
"allow" => Ok(Self::Allow),
"quarantine" => Ok(Self::Quarantine),
"deny" => Ok(Self::Deny),
_ => Err(ConfigParseError::InvalidValue {
key,
value: input.to_string(),
message: "expected one of `allow`, `quarantine`, or `deny`".to_string(),
}),
}
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct MeshLaneGrants {
pub metadata: Option<MeshLaneDecision>,
pub body: Option<MeshLaneDecision>,
pub embedding: Option<MeshLaneDecision>,
pub graph_link: Option<MeshLaneDecision>,
pub revision_notice: Option<MeshLaneDecision>,
pub curation_signal: Option<MeshLaneDecision>,
}
impl MeshLaneGrants {
#[must_use]
pub fn decision(&self, lane: MeshLane) -> MeshLaneDecision {
match lane {
MeshLane::Metadata => self.metadata,
MeshLane::Body => self.body,
MeshLane::Embedding => self.embedding,
MeshLane::GraphLink => self.graph_link,
MeshLane::RevisionNotice => self.revision_notice,
MeshLane::CurationSignal => self.curation_signal,
}
.unwrap_or(MeshLaneDecision::Deny)
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct SwarmConfig {
pub adaptive: SwarmAdaptiveConfig,
}
impl SwarmConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
adaptive: SwarmAdaptiveConfig::parse(document)?,
})
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct SwarmAdaptiveConfig {
pub enabled: Option<bool>,
pub prefetch_top_k: Option<u64>,
pub prefetch_budget_ms: Option<u64>,
pub similarity_threshold: Option<f64>,
pub noisy_neighbor_p99_ms: Option<u64>,
pub noisy_neighbor_backoff_ms: Option<u64>,
}
impl SwarmAdaptiveConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
const SECTIONS: &[&str] = &["swarm", "adaptive"];
Ok(Self {
enabled: optional_bool_path(document, SECTIONS, "enabled")?,
prefetch_top_k: optional_u64_path(document, SECTIONS, "prefetch_top_k")?,
prefetch_budget_ms: optional_u64_path(document, SECTIONS, "prefetch_budget_ms")?,
similarity_threshold: optional_unit_float_path(
document,
SECTIONS,
"similarity_threshold",
)?,
noisy_neighbor_p99_ms: optional_u64_path(document, SECTIONS, "noisy_neighbor_p99_ms")?,
noisy_neighbor_backoff_ms: optional_u64_path(
document,
SECTIONS,
"noisy_neighbor_backoff_ms",
)?,
})
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct GraphConfig {
pub ppr: GraphPprConfig,
pub health: GraphHealthConfig,
pub curate: GraphCurateConfig,
pub hits: GraphHitsConfig,
pub causal: GraphCausalConfig,
pub pack_dna: GraphPackDnaConfig,
pub gomory_hu: GraphGomoryHuConfig,
pub memory: GraphMemoryConfig,
pub witnesses: GraphWitnessesConfig,
pub feature: GraphFeatureFlagsConfig,
}
impl GraphConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
ppr: GraphPprConfig::parse(document)?,
health: GraphHealthConfig::parse(document)?,
curate: GraphCurateConfig::parse(document)?,
hits: GraphHitsConfig::parse(document)?,
causal: GraphCausalConfig::parse(document)?,
pack_dna: GraphPackDnaConfig::parse(document)?,
gomory_hu: GraphGomoryHuConfig::parse(document)?,
memory: GraphMemoryConfig::parse(document)?,
witnesses: GraphWitnessesConfig::parse(document)?,
feature: GraphFeatureFlagsConfig::parse(document)?,
})
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct GraphPprConfig {
pub alpha: Option<f64>,
}
impl GraphPprConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
alpha: optional_unit_float_path(document, &["graph", "ppr"], "alpha")?,
})
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct GraphHealthConfig {
pub contradiction_threshold: Option<f64>,
}
impl GraphHealthConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
contradiction_threshold: optional_unit_float_path(
document,
&["graph", "health"],
"contradiction_threshold",
)?,
})
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct GraphCurateConfig {
pub onion_decay_max: Option<f64>,
pub articulation_protection_multiplier: Option<f64>,
}
impl GraphCurateConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
const SECTIONS: &[&str] = &["graph", "curate"];
Ok(Self {
onion_decay_max: optional_positive_float_path(document, SECTIONS, "onion_decay_max")?,
articulation_protection_multiplier: optional_unit_float_path(
document,
SECTIONS,
"articulation_protection_multiplier",
)?,
})
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct GraphHitsConfig {
pub profile_boost: Option<f64>,
}
impl GraphHitsConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
profile_boost: optional_nonnegative_float_path(
document,
&["graph", "hits"],
"profile_boost",
)?,
})
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct GraphCausalConfig {
pub min_cost_normalization: Option<f64>,
}
impl GraphCausalConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
min_cost_normalization: optional_positive_float_path(
document,
&["graph", "causal"],
"min_cost_normalization",
)?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct GraphPackDnaConfig {
pub max_items: Option<u64>,
pub max_edges: Option<u64>,
}
impl GraphPackDnaConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
const SECTIONS: &[&str] = &["graph", "pack_dna"];
Ok(Self {
max_items: optional_u64_path(document, SECTIONS, "max_items")?,
max_edges: optional_u64_path(document, SECTIONS, "max_edges")?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct GraphGomoryHuConfig {
pub sample_threshold: Option<u64>,
pub sample_size: Option<u64>,
}
impl GraphGomoryHuConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
const SECTIONS: &[&str] = &["graph", "gomory_hu"];
Ok(Self {
sample_threshold: optional_u64_path(document, SECTIONS, "sample_threshold")?,
sample_size: optional_u64_path(document, SECTIONS, "sample_size")?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct GraphMemoryConfig {
pub snapshot_cap_mb: Option<u64>,
pub per_algorithm_cap_mb: Option<u64>,
pub degraded_below_pct: Option<u64>,
pub growth_multiplier_basis_points: Option<u64>,
}
impl GraphMemoryConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
const SECTIONS: &[&str] = &["graph", "memory"];
Ok(Self {
snapshot_cap_mb: optional_positive_u64_path(document, SECTIONS, "snapshot_cap_mb")?,
per_algorithm_cap_mb: optional_positive_u64_path(
document,
SECTIONS,
"per_algorithm_cap_mb",
)?,
degraded_below_pct: optional_percent_u64_path(
document,
SECTIONS,
"degraded_below_pct",
)?,
growth_multiplier_basis_points: optional_positive_u64_path(
document,
SECTIONS,
"growth_multiplier_basis_points",
)?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct GraphWitnessesConfig {
pub retention_days: Option<u64>,
pub algorithm_ttl_days: Option<BTreeMap<String, u64>>,
}
impl GraphWitnessesConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
const SECTIONS: &[&str] = &["graph", "witnesses"];
Ok(Self {
retention_days: optional_u64_path(document, SECTIONS, "retention_days")?,
algorithm_ttl_days: optional_u64_map_path(document, SECTIONS, "algorithm_ttl_days")?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct GraphFeatureFlagsConfig {
pub ppr_enabled: Option<bool>,
pub pack_dna_enabled: Option<bool>,
pub causal_explain_enabled: Option<bool>,
pub structural_health_enabled: Option<bool>,
pub structural_decay_enabled: Option<bool>,
pub proximity_enabled: Option<bool>,
pub revision_dominance_enabled: Option<bool>,
pub skyline_enabled: Option<bool>,
pub load_bearing_enabled: Option<bool>,
pub hits_profiles_enabled: Option<bool>,
}
impl GraphFeatureFlagsConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
ppr_enabled: optional_bool_path(document, &["graph", "feature", "ppr"], "enabled")?,
pack_dna_enabled: optional_bool_path(
document,
&["graph", "feature", "pack_dna"],
"enabled",
)?,
causal_explain_enabled: optional_bool_path(
document,
&["graph", "feature", "causal_explain"],
"enabled",
)?,
structural_health_enabled: optional_bool_path(
document,
&["graph", "feature", "structural_health"],
"enabled",
)?,
structural_decay_enabled: optional_bool_path(
document,
&["graph", "feature", "structural_decay"],
"enabled",
)?,
proximity_enabled: optional_bool_path(
document,
&["graph", "feature", "proximity"],
"enabled",
)?,
revision_dominance_enabled: optional_bool_path(
document,
&["graph", "feature", "revision_dominance"],
"enabled",
)?,
skyline_enabled: optional_bool_path(
document,
&["graph", "feature", "skyline"],
"enabled",
)?,
load_bearing_enabled: optional_bool_path(
document,
&["graph", "feature", "load_bearing"],
"enabled",
)?,
hits_profiles_enabled: optional_bool_path(
document,
&["graph", "feature", "hits_profiles"],
"enabled",
)?,
})
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct CurationConfig {
pub duplicate_similarity: Option<f64>,
pub harmful_weight: Option<f64>,
pub decay_half_life_days: Option<u64>,
pub specificity_min: Option<f64>,
}
impl CurationConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
duplicate_similarity: optional_unit_float(
document,
"curation",
"duplicate_similarity",
)?,
harmful_weight: optional_nonnegative_float(document, "curation", "harmful_weight")?,
decay_half_life_days: optional_u64(document, "curation", "decay_half_life_days")?,
specificity_min: optional_unit_float(document, "curation", "specificity_min")?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct JournalConfig {
pub enabled: Option<bool>,
pub retention_days: Option<u64>,
}
impl JournalConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
enabled: optional_bool(document, "journal", "enabled")?,
retention_days: optional_u64(document, "journal", "retention_days")?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct PrimerConfig {
pub default_tokens: Option<u64>,
}
impl PrimerConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
default_tokens: optional_u64(document, "primer", "default_tokens")?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct DecideConfig {
pub revisit_warning_days: Option<u64>,
}
impl DecideConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
revisit_warning_days: optional_u64(document, "decide", "revisit_warning_days")?,
})
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct LearnConfig {
pub cluster_coherence_threshold: Option<f64>,
pub decay: LearnDecayConfig,
}
impl LearnConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
cluster_coherence_threshold: optional_unit_float_path(
document,
&["learn"],
"cluster_coherence_threshold",
)?,
decay: LearnDecayConfig::parse(document)?,
})
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct LearnDecayConfig {
pub demote_threshold: Option<f64>,
pub forget_threshold: Option<f64>,
pub working_half_life_days: Option<f64>,
pub episodic_event_half_life_days: Option<f64>,
pub episodic_failure_half_life_days: Option<f64>,
pub semantic_fact_half_life_days: Option<f64>,
pub procedural_rule_half_life_days: Option<f64>,
pub default_half_life_days: Option<f64>,
}
impl LearnDecayConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
const SECTIONS: &[&str] = &["learn", "decay"];
Ok(Self {
demote_threshold: optional_unit_float_path(document, SECTIONS, "demote_threshold")?,
forget_threshold: optional_unit_float_path(document, SECTIONS, "forget_threshold")?,
working_half_life_days: optional_positive_float_path(
document,
SECTIONS,
"working_half_life_days",
)?,
episodic_event_half_life_days: optional_positive_float_path(
document,
SECTIONS,
"episodic_event_half_life_days",
)?,
episodic_failure_half_life_days: optional_positive_float_path(
document,
SECTIONS,
"episodic_failure_half_life_days",
)?,
semantic_fact_half_life_days: optional_positive_float_path(
document,
SECTIONS,
"semantic_fact_half_life_days",
)?,
procedural_rule_half_life_days: optional_positive_float_path(
document,
SECTIONS,
"procedural_rule_half_life_days",
)?,
default_half_life_days: optional_positive_float_path(
document,
SECTIONS,
"default_half_life_days",
)?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct FeedbackConfig {
pub harmful_per_source_per_hour: Option<u64>,
pub harmful_burst_window_seconds: Option<u64>,
}
impl FeedbackConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
harmful_per_source_per_hour: optional_u64(
document,
"feedback",
"harmful_per_source_per_hour",
)?,
harmful_burst_window_seconds: optional_u64(
document,
"feedback",
"harmful_burst_window_seconds",
)?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct RedactionConfig {
pub defaults: RedactionDefaultsConfig,
}
impl RedactionConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
defaults: RedactionDefaultsConfig::parse(document)?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct RedactionDefaultsConfig {
pub export: Option<RedactionLevel>,
pub handoff_create: Option<RedactionLevel>,
pub context_json: Option<RedactionLevel>,
pub support_bundle: Option<RedactionLevel>,
}
impl RedactionDefaultsConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
const SECTIONS: &[&str] = &["redaction", "defaults"];
Ok(Self {
export: optional_redaction_level_path(document, SECTIONS, "export")?,
handoff_create: optional_redaction_level_path(document, SECTIONS, "handoff_create")?,
context_json: optional_redaction_level_path(document, SECTIONS, "context_json")?,
support_bundle: optional_redaction_level_path(document, SECTIONS, "support_bundle")?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct PolicyConfig {
pub secret_detector: SecretDetectorConfig,
pub output_redaction: OutputRedactionConfig,
}
impl PolicyConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
secret_detector: SecretDetectorConfig::parse(document)?,
output_redaction: OutputRedactionConfig::parse(document)?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct OutputRedactionConfig {
pub enabled: Option<bool>,
}
impl OutputRedactionConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
enabled: optional_bool_path(document, &["policy", "output_redaction"], "enabled")?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct SecretDetectorConfig {
pub allow_phrases: Option<Vec<String>>,
pub allow_regex: Option<Vec<String>>,
}
impl SecretDetectorConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
allow_phrases: optional_string_array_path(
document,
&["policy", "secret_detector"],
"allow_phrases",
)?,
allow_regex: optional_regex_array_path(
document,
&["policy", "secret_detector"],
"allow_regex",
)?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct PrivacyConfig {
pub redact_secrets: Option<bool>,
pub redaction_classes: Option<Vec<String>>,
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct MemoryConfig {
pub include_global: Option<bool>,
pub participate: Option<bool>,
}
impl MemoryConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
include_global: optional_bool(document, "memory", "include_global")?,
participate: optional_bool(document, "memory", "participate")?,
})
}
}
impl PrivacyConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
redact_secrets: optional_bool(document, "privacy", "redact_secrets")?,
redaction_classes: optional_string_array(document, "privacy", "redaction_classes")?,
})
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct TrustConfig {
pub default_class: Option<String>,
pub prompt_injection_guard: Option<bool>,
}
impl TrustConfig {
fn parse(document: &DocumentMut) -> Result<Self, ConfigParseError> {
Ok(Self {
default_class: optional_string(document, "trust", "default_class")?,
prompt_injection_guard: optional_bool(document, "trust", "prompt_injection_guard")?,
})
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ConfigParseError {
Toml {
message: String,
},
InvalidType {
key: String,
expected: &'static str,
},
InvalidValue {
key: String,
value: String,
message: String,
},
PathExpansion {
key: String,
source: PathExpansionError,
},
UnknownKey {
key: String,
suggestion: Option<String>,
},
}
impl fmt::Display for ConfigParseError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Toml { message } => write!(formatter, "invalid TOML config: {message}"),
Self::InvalidType { key, expected } => {
write!(formatter, "config key `{key}` must be {expected}")
}
Self::InvalidValue {
key,
value,
message,
} => write!(
formatter,
"config key `{key}` has invalid value `{value}`: {message}"
),
Self::PathExpansion { key, source } => {
write!(formatter, "failed to expand config path `{key}`: {source}")
}
Self::UnknownKey { key, suggestion } => {
write!(formatter, "unknown config key `{key}`")?;
if let Some(suggestion) = suggestion {
write!(formatter, "; did you mean `{suggestion}`?")?;
}
Ok(())
}
}
}
}
impl std::error::Error for ConfigParseError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::PathExpansion { source, .. } => Some(source),
Self::Toml { .. }
| Self::InvalidType { .. }
| Self::InvalidValue { .. }
| Self::UnknownKey { .. } => None,
}
}
}
#[derive(Clone, Copy)]
enum ConfigKeyPolicy {
Closed(&'static [&'static str]),
Open,
}
fn config_key_policy(table_path: &str) -> Option<ConfigKeyPolicy> {
let policy = match table_path {
"" => ConfigKeyPolicy::Closed(&[
"storage",
"runtime",
"write",
"cass",
"search",
"pack",
"task_lens",
"handoff",
"cache",
"mesh",
"swarm",
"graph",
"curation",
"journal",
"primer",
"decide",
"learn",
"feedback",
"redaction",
"policy",
"privacy",
"trust",
"profile",
"memory",
]),
"storage" => {
ConfigKeyPolicy::Closed(&["database_path", "index_dir", "jsonl_export", "read_pool"])
}
"storage.read_pool" => ConfigKeyPolicy::Closed(&[
"size",
"idle_timeout_seconds",
"max_pin_duration_seconds",
"acquire_timeout_ms",
"pin_snapshot",
]),
"runtime" => ConfigKeyPolicy::Closed(&["daemon", "job_budget_ms", "import_batch_size"]),
"write" => ConfigKeyPolicy::Closed(&[
"group_commit_enabled",
"batch_window_ms",
"max_batch_size",
"max_inflight_bytes",
]),
"cass" => {
ConfigKeyPolicy::Closed(&["enabled", "binary", "since", "subprocess_timeout_secs"])
}
"search" => ConfigKeyPolicy::Closed(&[
"default_speed",
"lexical_weight",
"semantic_weight",
"graph_weight",
"rerank",
"rerank_top_k",
"query_miss_retention_days",
"lexical_ram_tier",
]),
"search.lexical_ram_tier" => {
ConfigKeyPolicy::Closed(&["enabled", "request_hugepages", "populate_on_open"])
}
"pack" => ConfigKeyPolicy::Closed(&[
"default_profile",
"default_format",
"default_max_tokens",
"adaptive_budget",
"mmr_lambda",
"candidate_pool",
"memory_tier_admission",
"lod_full_basis_points",
"lod_truncated_preview_basis_points",
"lod_link_only_basis_points",
"baseline_ledger_max_rows",
]),
"task_lens" => ConfigKeyPolicy::Closed(&["overrides"]),
"task_lens.overrides[]" => ConfigKeyPolicy::Closed(&[
"id",
"version",
"description",
"context_profile",
"source_mode",
"strict_source_mode",
"pack_profile",
"resource_profile",
"redaction",
"memory_scope",
"max_tokens",
"candidate_pool",
"max_results",
"coverage_facets",
"allowed_kinds",
"deprioritized_kinds",
]),
"handoff" => ConfigKeyPolicy::Closed(&["stale_threshold"]),
"handoff.stale_threshold" => ConfigKeyPolicy::Closed(&[
"memories_added",
"any_expired_in_pack",
"content_drift_score",
"memories_revised",
]),
"cache" => ConfigKeyPolicy::Closed(&["pack_l2"]),
"cache.pack_l2" => {
ConfigKeyPolicy::Closed(&["enabled", "directory", "max_bytes", "max_age_days"])
}
"mesh" => ConfigKeyPolicy::Closed(&[
"enabled",
"command_mode",
"last_containment_schema",
"peer_group_bindings",
"peer_policies",
]),
"mesh.peer_group_bindings[]" => ConfigKeyPolicy::Closed(&[
"workspace_id",
"workspace_alias",
"peer_group_id",
"peer_group_label",
"peer_ids",
"origin_workspace_ids",
"lanes",
"default_action",
]),
"mesh.peer_group_bindings[].lanes" | "mesh.peer_policies[].allowed_lanes" => {
ConfigKeyPolicy::Closed(&[
"metadata",
"body",
"embedding",
"graph_link",
"revision_notice",
"curation_signal",
])
}
"mesh.peer_policies[]" => ConfigKeyPolicy::Closed(&[
"policy_id",
"workspace_id",
"workspace_alias",
"peer_id",
"peer_alias",
"origin_workspace_ids",
"trust_lane",
"import_trust_class",
"allowed_lanes",
"redaction",
"body_fetch",
"default_action",
]),
"mesh.peer_policies[].redaction" => {
ConfigKeyPolicy::Closed(&["metadata", "preview", "body", "embedding"])
}
"mesh.peer_policies[].body_fetch" => {
ConfigKeyPolicy::Closed(&["allowed", "requires_consent", "max_bytes"])
}
"swarm" => ConfigKeyPolicy::Closed(&["adaptive"]),
"swarm.adaptive" => ConfigKeyPolicy::Closed(&[
"enabled",
"prefetch_top_k",
"prefetch_budget_ms",
"similarity_threshold",
"noisy_neighbor_p99_ms",
"noisy_neighbor_backoff_ms",
]),
"graph" => ConfigKeyPolicy::Closed(&[
"ppr",
"health",
"curate",
"hits",
"causal",
"pack_dna",
"gomory_hu",
"memory",
"witnesses",
"feature",
]),
"graph.ppr" => ConfigKeyPolicy::Closed(&["alpha"]),
"graph.health" => ConfigKeyPolicy::Closed(&["contradiction_threshold"]),
"graph.curate" => {
ConfigKeyPolicy::Closed(&["onion_decay_max", "articulation_protection_multiplier"])
}
"graph.hits" => ConfigKeyPolicy::Closed(&["profile_boost"]),
"graph.causal" => ConfigKeyPolicy::Closed(&["min_cost_normalization"]),
"graph.pack_dna" => ConfigKeyPolicy::Closed(&["max_items", "max_edges"]),
"graph.gomory_hu" => ConfigKeyPolicy::Closed(&["sample_threshold", "sample_size"]),
"graph.memory" => ConfigKeyPolicy::Closed(&[
"snapshot_cap_mb",
"per_algorithm_cap_mb",
"degraded_below_pct",
"growth_multiplier_basis_points",
]),
"graph.witnesses" => ConfigKeyPolicy::Closed(&["retention_days", "algorithm_ttl_days"]),
"graph.witnesses.algorithm_ttl_days" => ConfigKeyPolicy::Open,
"graph.feature" => ConfigKeyPolicy::Closed(&[
"ppr",
"pack_dna",
"causal_explain",
"structural_health",
"structural_decay",
"proximity",
"revision_dominance",
"skyline",
"load_bearing",
"hits_profiles",
]),
"graph.feature.ppr"
| "graph.feature.pack_dna"
| "graph.feature.causal_explain"
| "graph.feature.structural_health"
| "graph.feature.structural_decay"
| "graph.feature.proximity"
| "graph.feature.revision_dominance"
| "graph.feature.skyline"
| "graph.feature.load_bearing"
| "graph.feature.hits_profiles" => ConfigKeyPolicy::Closed(&["enabled"]),
"curation" => ConfigKeyPolicy::Closed(&[
"duplicate_similarity",
"harmful_weight",
"decay_half_life_days",
"specificity_min",
]),
"journal" => ConfigKeyPolicy::Closed(&["enabled", "retention_days"]),
"primer" => ConfigKeyPolicy::Closed(&["default_tokens"]),
"decide" => ConfigKeyPolicy::Closed(&["revisit_warning_days"]),
"learn" => ConfigKeyPolicy::Closed(&["cluster_coherence_threshold", "decay"]),
"learn.decay" => ConfigKeyPolicy::Closed(&[
"demote_threshold",
"forget_threshold",
"working_half_life_days",
"episodic_event_half_life_days",
"episodic_failure_half_life_days",
"semantic_fact_half_life_days",
"procedural_rule_half_life_days",
"default_half_life_days",
]),
"feedback" => ConfigKeyPolicy::Closed(&[
"harmful_per_source_per_hour",
"harmful_burst_window_seconds",
]),
"redaction" => ConfigKeyPolicy::Closed(&["defaults"]),
"redaction.defaults" => {
ConfigKeyPolicy::Closed(&["export", "handoff_create", "context_json", "support_bundle"])
}
"policy" => ConfigKeyPolicy::Closed(&["secret_detector", "output_redaction"]),
"policy.secret_detector" => ConfigKeyPolicy::Closed(&["allow_phrases", "allow_regex"]),
"policy.output_redaction" => ConfigKeyPolicy::Closed(&["enabled"]),
"privacy" => ConfigKeyPolicy::Closed(&["redact_secrets", "redaction_classes"]),
"memory" => ConfigKeyPolicy::Closed(&["include_global", "participate"]),
"trust" => ConfigKeyPolicy::Closed(&["default_class", "prompt_injection_guard"]),
"profile" => ConfigKeyPolicy::Closed(&["selected", "budgets"]),
"profile.budgets" => ConfigKeyPolicy::Closed(&[
"search_candidate_limit",
"search_concurrent_index_readers",
"search_stale_index_tolerance",
"pack_max_tokens",
"pack_max_candidate_memories",
"pack_explanation_verbosity",
"cache_memory_cap_mb",
"cache_entry_cap",
"cache_hotset_prewarm_limit",
"write_spool_queue_cap",
"write_spool_batch_cap",
"write_spool_retry_budget",
"steward_maintenance_window_ms",
"steward_graph_refresh_budget",
"steward_daemon_prewarm",
"verification_recipe",
"verification_target_dir_posture",
"verification_timeout_class",
"verification_heavy_strategy",
"diagnostics_support_bundle_profile",
"diagnostics_redaction",
]),
_ => return None,
};
Some(policy)
}
fn validate_config_keys(document: &DocumentMut) -> Result<(), ConfigParseError> {
validate_config_table(document.as_table(), "", "")
}
fn validate_config_table(
table: &dyn TableLike,
schema_path: &str,
display_path: &str,
) -> Result<(), ConfigParseError> {
let Some(policy) = config_key_policy(schema_path) else {
return Ok(());
};
let ConfigKeyPolicy::Closed(allowed_keys) = policy else {
return Ok(());
};
for (key, item) in table.iter() {
if !allowed_keys.contains(&key) {
let suggestion = closest_config_key(key, allowed_keys)
.map(|candidate| append_config_path(display_path, candidate));
return Err(ConfigParseError::UnknownKey {
key: append_config_path(display_path, key),
suggestion,
});
}
let child_schema_path = append_config_path(schema_path, key);
let child_display_path = append_config_path(display_path, key);
if let Some(tables) = item.as_array_of_tables() {
let array_schema_path = format!("{child_schema_path}[]");
if config_key_policy(&array_schema_path).is_some() {
for (index, child) in tables.iter().enumerate() {
validate_config_table(
child,
&array_schema_path,
&format!("{child_display_path}[{index}]"),
)?;
}
}
} else if let Some(child) = item.as_table_like()
&& config_key_policy(&child_schema_path).is_some()
{
validate_config_table(child, &child_schema_path, &child_display_path)?;
}
}
Ok(())
}
fn append_config_path(parent: &str, child: &str) -> String {
if parent.is_empty() {
child.to_string()
} else {
format!("{parent}.{child}")
}
}
fn closest_config_key(unknown: &str, candidates: &'static [&'static str]) -> Option<&'static str> {
let mut best_candidate = None;
let mut best_distance = usize::MAX;
let mut tied = false;
for &candidate in candidates {
let distance = ascii_edit_distance(unknown, candidate);
if distance < best_distance {
best_candidate = Some(candidate);
best_distance = distance;
tied = false;
} else if distance == best_distance {
tied = true;
}
}
let maximum_distance = if unknown.len() <= 4 { 1 } else { 2 };
best_candidate.filter(|_| best_distance <= maximum_distance && !tied)
}
fn ascii_edit_distance(left: &str, right: &str) -> usize {
let left = left.to_ascii_lowercase();
let right = right.to_ascii_lowercase();
let mut previous = (0..=right.len()).collect::<Vec<_>>();
let mut current = vec![0; right.len() + 1];
for (left_index, left_byte) in left.bytes().enumerate() {
current[0] = left_index + 1;
for (right_index, right_byte) in right.bytes().enumerate() {
let deletion = previous[right_index + 1] + 1;
let insertion = current[right_index] + 1;
let substitution = previous[right_index] + usize::from(left_byte != right_byte);
current[right_index + 1] = deletion.min(insertion).min(substitution);
}
std::mem::swap(&mut previous, &mut current);
}
previous[right.len()]
}
fn item<'a>(document: &'a DocumentMut, section: &str, key: &str) -> Option<&'a Item> {
document.get(section).and_then(|table| table.get(key))
}
fn item_path<'a>(document: &'a DocumentMut, sections: &[&str], key: &str) -> Option<&'a Item> {
let (first, rest) = sections.split_first()?;
let mut current = document.get(first)?;
for section in rest {
current = current.get(section)?;
}
current.get(key)
}
fn key_name(section: &str, key: &str) -> String {
format!("{section}.{key}")
}
fn key_path_name(sections: &[&str], key: &str) -> String {
format!("{}.{}", sections.join("."), key)
}
fn optional_string(
document: &DocumentMut,
section: &str,
key: &str,
) -> Result<Option<String>, ConfigParseError> {
match item(document, section, key) {
Some(value) => value
.as_str()
.map(|text| Some(text.to_string()))
.ok_or_else(|| ConfigParseError::InvalidType {
key: key_name(section, key),
expected: "a string",
}),
None => Ok(None),
}
}
fn optional_string_path(
document: &DocumentMut,
sections: &[&str],
key: &str,
) -> Result<Option<String>, ConfigParseError> {
match item_path(document, sections, key) {
Some(value) => value
.as_str()
.map(|text| Some(text.to_string()))
.ok_or_else(|| ConfigParseError::InvalidType {
key: key_path_name(sections, key),
expected: "a string",
}),
None => Ok(None),
}
}
fn optional_redaction_level_path(
document: &DocumentMut,
sections: &[&str],
key: &str,
) -> Result<Option<RedactionLevel>, ConfigParseError> {
let Some(raw) = optional_string_path(document, sections, key)? else {
return Ok(None);
};
let level = raw
.parse::<RedactionLevel>()
.map_err(|error| ConfigParseError::InvalidValue {
key: key_path_name(sections, key),
value: error.invalid,
message: "expected one of: none, minimal, standard, strict, paranoid".to_owned(),
})?;
if level == RedactionLevel::Full {
return Err(ConfigParseError::InvalidValue {
key: key_path_name(sections, key),
value: raw,
message: "expected one of: none, minimal, standard, strict, paranoid".to_owned(),
});
}
Ok(Some(level))
}
fn optional_bool(
document: &DocumentMut,
section: &str,
key: &str,
) -> Result<Option<bool>, ConfigParseError> {
match item(document, section, key) {
Some(value) => value
.as_bool()
.map(Some)
.ok_or_else(|| ConfigParseError::InvalidType {
key: key_name(section, key),
expected: "a boolean",
}),
None => Ok(None),
}
}
fn optional_bool_path(
document: &DocumentMut,
sections: &[&str],
key: &str,
) -> Result<Option<bool>, ConfigParseError> {
match item_path(document, sections, key) {
Some(value) => value
.as_bool()
.map(Some)
.ok_or_else(|| ConfigParseError::InvalidType {
key: key_path_name(sections, key),
expected: "a boolean",
}),
None => Ok(None),
}
}
fn optional_u64(
document: &DocumentMut,
section: &str,
key: &str,
) -> Result<Option<u64>, ConfigParseError> {
match item(document, section, key) {
Some(value) => match value.as_integer() {
Some(integer) if integer >= 0 => Ok(Some(integer as u64)),
Some(integer) => Err(ConfigParseError::InvalidValue {
key: key_name(section, key),
value: integer.to_string(),
message: "expected a non-negative integer".to_string(),
}),
None => Err(ConfigParseError::InvalidType {
key: key_name(section, key),
expected: "an integer",
}),
},
None => Ok(None),
}
}
fn optional_u64_path(
document: &DocumentMut,
sections: &[&str],
key: &str,
) -> Result<Option<u64>, ConfigParseError> {
match item_path(document, sections, key) {
Some(value) => match value.as_integer() {
Some(integer) if integer >= 0 => Ok(Some(integer as u64)),
Some(integer) => Err(ConfigParseError::InvalidValue {
key: key_path_name(sections, key),
value: integer.to_string(),
message: "expected a non-negative integer".to_string(),
}),
None => Err(ConfigParseError::InvalidType {
key: key_path_name(sections, key),
expected: "an integer",
}),
},
None => Ok(None),
}
}
fn optional_positive_u64_path(
document: &DocumentMut,
sections: &[&str],
key: &str,
) -> Result<Option<u64>, ConfigParseError> {
match optional_u64_path(document, sections, key)? {
Some(0) => Err(ConfigParseError::InvalidValue {
key: key_path_name(sections, key),
value: "0".to_string(),
message: "expected a positive integer".to_string(),
}),
Some(value) => Ok(Some(value)),
None => Ok(None),
}
}
fn optional_percent_u64_path(
document: &DocumentMut,
sections: &[&str],
key: &str,
) -> Result<Option<u64>, ConfigParseError> {
match optional_u64_path(document, sections, key)? {
Some(value) if value <= 100 => Ok(Some(value)),
Some(value) => Err(ConfigParseError::InvalidValue {
key: key_path_name(sections, key),
value: value.to_string(),
message: "expected an integer in the range 0..=100".to_string(),
}),
None => Ok(None),
}
}
fn optional_u64_map_path(
document: &DocumentMut,
sections: &[&str],
key: &str,
) -> Result<Option<BTreeMap<String, u64>>, ConfigParseError> {
let Some(value) = item_path(document, sections, key) else {
return Ok(None);
};
let Some(table) = value.as_table() else {
return Err(ConfigParseError::InvalidType {
key: key_path_name(sections, key),
expected: "a table of non-negative integers",
});
};
let prefix = key_path_name(sections, key);
let mut parsed = BTreeMap::new();
for (name, item) in table {
match item.as_integer() {
Some(integer) if integer >= 0 => {
parsed.insert(name.to_string(), integer as u64);
}
Some(integer) => {
return Err(ConfigParseError::InvalidValue {
key: format!("{prefix}.{name}"),
value: integer.to_string(),
message: "expected a non-negative integer".to_string(),
});
}
None => {
return Err(ConfigParseError::InvalidType {
key: format!("{prefix}.{name}"),
expected: "an integer",
});
}
}
}
Ok(Some(parsed))
}
fn optional_float(
document: &DocumentMut,
section: &str,
key: &str,
) -> Result<Option<f64>, ConfigParseError> {
match item(document, section, key) {
Some(value) => match value
.as_float()
.or_else(|| value.as_integer().map(|i| i as f64))
{
Some(number) if number.is_finite() => Ok(Some(number)),
Some(number) => Err(ConfigParseError::InvalidValue {
key: key_name(section, key),
value: number.to_string(),
message: "expected a finite number".to_string(),
}),
None => Err(ConfigParseError::InvalidType {
key: key_name(section, key),
expected: "a number",
}),
},
None => Ok(None),
}
}
fn optional_float_path(
document: &DocumentMut,
sections: &[&str],
key: &str,
) -> Result<Option<f64>, ConfigParseError> {
match item_path(document, sections, key) {
Some(value) => match value
.as_float()
.or_else(|| value.as_integer().map(|i| i as f64))
{
Some(number) if number.is_finite() => Ok(Some(number)),
Some(number) => Err(ConfigParseError::InvalidValue {
key: key_path_name(sections, key),
value: number.to_string(),
message: "expected a finite number".to_string(),
}),
None => Err(ConfigParseError::InvalidType {
key: key_path_name(sections, key),
expected: "a number",
}),
},
None => Ok(None),
}
}
fn optional_unit_float(
document: &DocumentMut,
section: &str,
key: &str,
) -> Result<Option<f64>, ConfigParseError> {
match optional_float(document, section, key)? {
Some(number) if (0.0..=1.0).contains(&number) => Ok(Some(number)),
Some(number) => Err(ConfigParseError::InvalidValue {
key: key_name(section, key),
value: number.to_string(),
message: "expected a number in 0.0..=1.0".to_string(),
}),
None => Ok(None),
}
}
fn optional_unit_float_path(
document: &DocumentMut,
sections: &[&str],
key: &str,
) -> Result<Option<f64>, ConfigParseError> {
match optional_float_path(document, sections, key)? {
Some(number) if (0.0..=1.0).contains(&number) => Ok(Some(number)),
Some(number) => Err(ConfigParseError::InvalidValue {
key: key_path_name(sections, key),
value: number.to_string(),
message: "expected a number in 0.0..=1.0".to_string(),
}),
None => Ok(None),
}
}
fn optional_nonnegative_float(
document: &DocumentMut,
section: &str,
key: &str,
) -> Result<Option<f64>, ConfigParseError> {
match optional_float(document, section, key)? {
Some(number) if number >= 0.0 => Ok(Some(number)),
Some(number) => Err(ConfigParseError::InvalidValue {
key: key_name(section, key),
value: number.to_string(),
message: "expected a non-negative number".to_string(),
}),
None => Ok(None),
}
}
fn optional_nonnegative_float_path(
document: &DocumentMut,
sections: &[&str],
key: &str,
) -> Result<Option<f64>, ConfigParseError> {
match optional_float_path(document, sections, key)? {
Some(number) if number >= 0.0 => Ok(Some(number)),
Some(number) => Err(ConfigParseError::InvalidValue {
key: key_path_name(sections, key),
value: number.to_string(),
message: "expected a non-negative number".to_string(),
}),
None => Ok(None),
}
}
fn optional_positive_float_path(
document: &DocumentMut,
sections: &[&str],
key: &str,
) -> Result<Option<f64>, ConfigParseError> {
match optional_float_path(document, sections, key)? {
Some(number) if number > 0.0 => Ok(Some(number)),
Some(number) => Err(ConfigParseError::InvalidValue {
key: key_path_name(sections, key),
value: number.to_string(),
message: "expected a positive number".to_string(),
}),
None => Ok(None),
}
}
fn optional_path(
document: &DocumentMut,
section: &str,
key: &str,
expander: Option<&PathExpander>,
) -> Result<Option<PathBuf>, ConfigParseError> {
let Some(raw) = optional_string(document, section, key)? else {
return Ok(None);
};
match expander {
Some(expander) => {
expander
.expand(&raw)
.map(Some)
.map_err(|source| ConfigParseError::PathExpansion {
key: key_name(section, key),
source,
})
}
None => Ok(Some(PathBuf::from(raw))),
}
}
fn optional_path_path(
document: &DocumentMut,
sections: &[&str],
key: &str,
expander: Option<&PathExpander>,
) -> Result<Option<PathBuf>, ConfigParseError> {
let Some(item) = item_path(document, sections, key) else {
return Ok(None);
};
let Some(raw) = item.as_str().map(str::to_owned) else {
return Err(ConfigParseError::InvalidType {
key: key_path_name(sections, key),
expected: "a string",
});
};
match expander {
Some(expander) => {
expander
.expand(&raw)
.map(Some)
.map_err(|source| ConfigParseError::PathExpansion {
key: key_path_name(sections, key),
source,
})
}
None => Ok(Some(PathBuf::from(raw))),
}
}
fn optional_search_speed(
document: &DocumentMut,
section: &str,
key: &str,
) -> Result<Option<SearchSpeed>, ConfigParseError> {
match optional_string(document, section, key)? {
Some(value) => value.parse().map(Some),
None => Ok(None),
}
}
fn optional_search_rerank_mode(
document: &DocumentMut,
section: &str,
key: &str,
) -> Result<Option<SearchRerankMode>, ConfigParseError> {
match optional_string(document, section, key)? {
Some(value) => value.parse().map(Some),
None => Ok(None),
}
}
fn optional_mesh_command_mode(
document: &DocumentMut,
section: &str,
key: &str,
) -> Result<Option<MeshCommandMode>, ConfigParseError> {
match optional_string(document, section, key)? {
Some(value) => value.parse().map(Some),
None => Ok(None),
}
}
fn optional_string_array(
document: &DocumentMut,
section: &str,
key: &str,
) -> Result<Option<Vec<String>>, ConfigParseError> {
let Some(value) = item(document, section, key) else {
return Ok(None);
};
let Some(array) = value.as_array() else {
return Err(ConfigParseError::InvalidType {
key: key_name(section, key),
expected: "an array of strings",
});
};
let mut out = Vec::new();
for entry in array.iter() {
match entry {
Value::String(text) => out.push(text.value().to_string()),
_ => {
return Err(ConfigParseError::InvalidType {
key: key_name(section, key),
expected: "an array of strings",
});
}
}
}
Ok(Some(out))
}
fn optional_string_array_path(
document: &DocumentMut,
sections: &[&str],
key: &str,
) -> Result<Option<Vec<String>>, ConfigParseError> {
let Some(value) = item_path(document, sections, key) else {
return Ok(None);
};
let Some(array) = value.as_array() else {
return Err(ConfigParseError::InvalidType {
key: key_path_name(sections, key),
expected: "an array of strings",
});
};
let mut out = Vec::new();
for entry in array.iter() {
match entry {
Value::String(text) => out.push(text.value().to_string()),
_ => {
return Err(ConfigParseError::InvalidType {
key: key_path_name(sections, key),
expected: "an array of strings",
});
}
}
}
Ok(Some(out))
}
fn optional_task_lens_overrides(document: &DocumentMut) -> Result<Vec<TaskLens>, ConfigParseError> {
let Some(item) = item_path(document, &["task_lens"], "overrides") else {
return Ok(Vec::new());
};
let Some(tables) = item.as_array_of_tables() else {
return Err(ConfigParseError::InvalidType {
key: "task_lens.overrides".to_string(),
expected: "an array of tables",
});
};
if tables.len() > MAX_WORKSPACE_TASK_LENSES {
return Err(ConfigParseError::InvalidValue {
key: "task_lens.overrides".to_string(),
value: tables.len().to_string(),
message: format!("expected at most {MAX_WORKSPACE_TASK_LENSES} task lens overrides"),
});
}
let mut overrides = Vec::with_capacity(tables.len());
for (index, table) in tables.iter().enumerate() {
overrides.push(parse_task_lens_override(table, index)?);
}
Ok(overrides)
}
fn parse_task_lens_override(table: &Table, index: usize) -> Result<TaskLens, ConfigParseError> {
let prefix = format!("task_lens.overrides[{index}]");
let id = required_table_string(table, &prefix, "id")?;
let version = optional_table_u32(table, &prefix, "version")?.unwrap_or(TASK_LENS_VERSION);
let description = required_table_string(table, &prefix, "description")?;
let overlay = TaskLensOverlay {
context_profile: optional_table_string(table, &prefix, "context_profile")?,
source_mode: optional_table_string(table, &prefix, "source_mode")?,
strict_source_mode: optional_table_bool(table, &prefix, "strict_source_mode")?,
pack_profile: optional_table_string(table, &prefix, "pack_profile")?,
resource_profile: optional_table_string(table, &prefix, "resource_profile")?,
redaction: optional_table_redaction_level(table, &prefix, "redaction")?,
memory_scope: optional_table_string(table, &prefix, "memory_scope")?,
max_tokens: optional_table_u32(table, &prefix, "max_tokens")?,
candidate_pool: optional_table_u32(table, &prefix, "candidate_pool")?,
max_results: optional_table_u32(table, &prefix, "max_results")?,
coverage_facets: optional_table_string_array(table, &prefix, "coverage_facets")?
.unwrap_or_default(),
allowed_kinds: optional_table_string_array(table, &prefix, "allowed_kinds")?
.unwrap_or_default(),
deprioritized_kinds: optional_table_string_array(table, &prefix, "deprioritized_kinds")?
.unwrap_or_default(),
};
TaskLens::new(TaskLensInput {
id: id.clone(),
version,
description,
overlay,
})
.map_err(|error| ConfigParseError::InvalidValue {
key: prefix,
value: id,
message: error.to_string(),
})
}
fn optional_peer_group_bindings(
document: &DocumentMut,
) -> Result<Option<Vec<MeshPeerGroupBinding>>, ConfigParseError> {
let Some(item) = item_path(document, &["mesh"], "peer_group_bindings") else {
return Ok(None);
};
let Some(tables) = item.as_array_of_tables() else {
return Err(ConfigParseError::InvalidType {
key: "mesh.peer_group_bindings".to_string(),
expected: "an array of tables",
});
};
let mut bindings = Vec::with_capacity(tables.len());
for (index, table) in tables.iter().enumerate() {
bindings.push(parse_peer_group_binding(table, index)?);
}
Ok(Some(bindings))
}
fn optional_peer_policies(
document: &DocumentMut,
) -> Result<Option<Vec<MeshPeerPolicyConfig>>, ConfigParseError> {
let Some(item) = item_path(document, &["mesh"], "peer_policies") else {
return Ok(None);
};
let Some(tables) = item.as_array_of_tables() else {
return Err(ConfigParseError::InvalidType {
key: "mesh.peer_policies".to_string(),
expected: "an array of tables",
});
};
let mut policies = Vec::with_capacity(tables.len());
for (index, table) in tables.iter().enumerate() {
policies.push(parse_peer_policy(table, index)?);
}
Ok(Some(policies))
}
fn parse_peer_group_binding(
table: &Table,
index: usize,
) -> Result<MeshPeerGroupBinding, ConfigParseError> {
let prefix = format!("mesh.peer_group_bindings[{index}]");
Ok(MeshPeerGroupBinding {
workspace_id: optional_table_string(table, &prefix, "workspace_id")?,
workspace_alias: optional_table_string(table, &prefix, "workspace_alias")?,
peer_group_id: optional_table_string(table, &prefix, "peer_group_id")?,
peer_group_label: optional_table_string(table, &prefix, "peer_group_label")?,
peer_ids: optional_table_string_array(table, &prefix, "peer_ids")?,
origin_workspace_ids: optional_table_string_array(table, &prefix, "origin_workspace_ids")?,
lanes: parse_lane_grants(table, &prefix)?,
default_action: optional_table_default_action(table, &prefix)?,
})
}
fn parse_peer_policy(
table: &Table,
index: usize,
) -> Result<MeshPeerPolicyConfig, ConfigParseError> {
let prefix = format!("mesh.peer_policies[{index}]");
Ok(MeshPeerPolicyConfig {
policy_id: required_table_string(table, &prefix, "policy_id")?,
workspace_id: required_table_string(table, &prefix, "workspace_id")?,
workspace_alias: optional_table_string(table, &prefix, "workspace_alias")?,
peer_id: required_table_string(table, &prefix, "peer_id")?,
peer_alias: optional_table_string(table, &prefix, "peer_alias")?,
origin_workspace_ids: required_table_string_array(table, &prefix, "origin_workspace_ids")?,
trust_lane: required_table_peer_trust_lane(table, &prefix)?,
import_trust_class: required_table_peer_import_trust_class(table, &prefix)?,
allowed_lanes: parse_required_lane_grants(table, &prefix)?,
redaction: parse_required_redaction_policy(table, &prefix)?,
body_fetch: parse_required_body_fetch_policy(table, &prefix)?,
default_action: required_table_default_action(table, &prefix)?,
})
}
fn parse_lane_grants(table: &Table, prefix: &str) -> Result<MeshLaneGrants, ConfigParseError> {
let Some(lanes) = table.get("lanes") else {
return Ok(MeshLaneGrants::default());
};
let Some(lanes) = lanes.as_table() else {
return Err(ConfigParseError::InvalidType {
key: format!("{prefix}.lanes"),
expected: "a table",
});
};
Ok(MeshLaneGrants {
metadata: optional_table_lane_decision(lanes, &format!("{prefix}.lanes"), "metadata")?,
body: optional_table_lane_decision(lanes, &format!("{prefix}.lanes"), "body")?,
embedding: optional_table_lane_decision(lanes, &format!("{prefix}.lanes"), "embedding")?,
graph_link: optional_table_lane_decision(lanes, &format!("{prefix}.lanes"), "graph_link")?,
revision_notice: optional_table_lane_decision(
lanes,
&format!("{prefix}.lanes"),
"revision_notice",
)?,
curation_signal: optional_table_lane_decision(
lanes,
&format!("{prefix}.lanes"),
"curation_signal",
)?,
})
}
fn parse_required_lane_grants(
table: &Table,
prefix: &str,
) -> Result<MeshLaneGrants, ConfigParseError> {
let lanes = required_table(table, prefix, "allowed_lanes")?;
let lanes_prefix = format!("{prefix}.allowed_lanes");
Ok(MeshLaneGrants {
metadata: Some(required_table_lane_decision(
lanes,
&lanes_prefix,
"metadata",
)?),
body: Some(required_table_lane_decision(lanes, &lanes_prefix, "body")?),
embedding: Some(required_table_lane_decision(
lanes,
&lanes_prefix,
"embedding",
)?),
graph_link: Some(required_table_lane_decision(
lanes,
&lanes_prefix,
"graph_link",
)?),
revision_notice: Some(required_table_lane_decision(
lanes,
&lanes_prefix,
"revision_notice",
)?),
curation_signal: Some(required_table_lane_decision(
lanes,
&lanes_prefix,
"curation_signal",
)?),
})
}
fn parse_required_redaction_policy(
table: &Table,
prefix: &str,
) -> Result<MeshRedactionPolicyConfig, ConfigParseError> {
let redaction = required_table(table, prefix, "redaction")?;
let redaction_prefix = format!("{prefix}.redaction");
Ok(MeshRedactionPolicyConfig {
metadata: required_table_redaction_decision(redaction, &redaction_prefix, "metadata")?,
preview: required_table_redaction_decision(redaction, &redaction_prefix, "preview")?,
body: required_table_redaction_decision(redaction, &redaction_prefix, "body")?,
embedding: required_table_redaction_decision(redaction, &redaction_prefix, "embedding")?,
})
}
fn parse_required_body_fetch_policy(
table: &Table,
prefix: &str,
) -> Result<MeshBodyFetchPolicyConfig, ConfigParseError> {
let body_fetch = required_table(table, prefix, "body_fetch")?;
let body_fetch_prefix = format!("{prefix}.body_fetch");
Ok(MeshBodyFetchPolicyConfig {
allowed: required_table_bool(body_fetch, &body_fetch_prefix, "allowed")?,
requires_consent: required_table_bool(body_fetch, &body_fetch_prefix, "requires_consent")?,
max_bytes: optional_table_usize(body_fetch, &body_fetch_prefix, "max_bytes")?,
})
}
fn required_table<'a>(
table: &'a Table,
prefix: &str,
key: &str,
) -> Result<&'a Table, ConfigParseError> {
let Some(value) = table.get(key) else {
return Err(ConfigParseError::InvalidType {
key: format!("{prefix}.{key}"),
expected: "a table",
});
};
value
.as_table()
.ok_or_else(|| ConfigParseError::InvalidType {
key: format!("{prefix}.{key}"),
expected: "a table",
})
}
fn required_table_string(
table: &Table,
prefix: &str,
key: &str,
) -> Result<String, ConfigParseError> {
optional_table_string(table, prefix, key)?.ok_or_else(|| ConfigParseError::InvalidType {
key: format!("{prefix}.{key}"),
expected: "a string",
})
}
fn optional_table_string(
table: &Table,
prefix: &str,
key: &str,
) -> Result<Option<String>, ConfigParseError> {
match table.get(key) {
Some(value) => value
.as_str()
.map(|text| Some(text.to_string()))
.ok_or_else(|| ConfigParseError::InvalidType {
key: format!("{prefix}.{key}"),
expected: "a string",
}),
None => Ok(None),
}
}
fn required_table_bool(table: &Table, prefix: &str, key: &str) -> Result<bool, ConfigParseError> {
match table.get(key) {
Some(value) => value
.as_bool()
.ok_or_else(|| ConfigParseError::InvalidType {
key: format!("{prefix}.{key}"),
expected: "a boolean",
}),
None => Err(ConfigParseError::InvalidType {
key: format!("{prefix}.{key}"),
expected: "a boolean",
}),
}
}
fn optional_table_bool(
table: &Table,
prefix: &str,
key: &str,
) -> Result<Option<bool>, ConfigParseError> {
match table.get(key) {
Some(value) => value
.as_bool()
.map(Some)
.ok_or_else(|| ConfigParseError::InvalidType {
key: format!("{prefix}.{key}"),
expected: "a boolean",
}),
None => Ok(None),
}
}
fn optional_table_u32(
table: &Table,
prefix: &str,
key: &str,
) -> Result<Option<u32>, ConfigParseError> {
let Some(value) = table.get(key) else {
return Ok(None);
};
let Some(integer) = value.as_integer() else {
return Err(ConfigParseError::InvalidType {
key: format!("{prefix}.{key}"),
expected: "a non-negative integer",
});
};
u32::try_from(integer)
.map(Some)
.map_err(|_| ConfigParseError::InvalidValue {
key: format!("{prefix}.{key}"),
value: integer.to_string(),
message: "expected a non-negative integer no larger than u32::MAX".to_string(),
})
}
fn optional_table_redaction_level(
table: &Table,
prefix: &str,
key: &str,
) -> Result<Option<RedactionLevel>, ConfigParseError> {
let Some(value) = optional_table_string(table, prefix, key)? else {
return Ok(None);
};
value
.parse::<RedactionLevel>()
.map(Some)
.map_err(|error| ConfigParseError::InvalidValue {
key: format!("{prefix}.{key}"),
value: error.invalid,
message: "expected one of: none, minimal, standard, strict, paranoid".to_string(),
})
}
fn optional_table_usize(
table: &Table,
prefix: &str,
key: &str,
) -> Result<Option<usize>, ConfigParseError> {
let Some(value) = table.get(key) else {
return Ok(None);
};
let Some(integer) = value.as_integer() else {
return Err(ConfigParseError::InvalidType {
key: format!("{prefix}.{key}"),
expected: "a non-negative integer",
});
};
usize::try_from(integer)
.map(Some)
.map_err(|_| ConfigParseError::InvalidValue {
key: format!("{prefix}.{key}"),
value: integer.to_string(),
message: "expected a non-negative integer".to_string(),
})
}
fn required_table_peer_trust_lane(
table: &Table,
prefix: &str,
) -> Result<MeshTrustLane, ConfigParseError> {
let key = "trust_lane";
let value = required_table_string(table, prefix, key)?;
let lane = MeshTrustLane::parse_for_key(&value, format!("{prefix}.{key}"))?;
if lane == MeshTrustLane::LocalHuman {
return Err(ConfigParseError::InvalidValue {
key: format!("{prefix}.{key}"),
value,
message: "`localHuman` is reserved for local records and cannot be assigned to peer policy imports".to_string(),
});
}
Ok(lane)
}
fn required_table_peer_import_trust_class(
table: &Table,
prefix: &str,
) -> Result<TrustClass, ConfigParseError> {
let key = "import_trust_class";
let value = required_table_string(table, prefix, key)?;
let trust_class = value
.parse::<TrustClass>()
.map_err(|_| ConfigParseError::InvalidValue {
key: format!("{prefix}.{key}"),
value: value.clone(),
message: "expected one of `agent_assertion` or `agent_validated`".to_string(),
})?;
match trust_class {
TrustClass::AgentAssertion | TrustClass::AgentValidated => Ok(trust_class),
_ => Err(ConfigParseError::InvalidValue {
key: format!("{prefix}.{key}"),
value,
message: "generic peer policy may import only as `agent_assertion` or `agent_validated`; `peer_human_attested` requires the dedicated signed-member admission path, and `human_explicit`, `cass_evidence`, and `legacy_import` remain disallowed".to_string(),
}),
}
}
fn required_table_lane_decision(
table: &Table,
prefix: &str,
key: &str,
) -> Result<MeshLaneDecision, ConfigParseError> {
let value = required_table_string(table, prefix, key)?;
MeshLaneDecision::parse_for_key(&value, format!("{prefix}.{key}"))
}
fn optional_table_lane_decision(
table: &Table,
prefix: &str,
key: &str,
) -> Result<Option<MeshLaneDecision>, ConfigParseError> {
let Some(value) = optional_table_string(table, prefix, key)? else {
return Ok(None);
};
MeshLaneDecision::parse_for_key(&value, format!("{prefix}.{key}")).map(Some)
}
fn required_table_redaction_decision(
table: &Table,
prefix: &str,
key: &str,
) -> Result<MeshRedactionDecision, ConfigParseError> {
let value = required_table_string(table, prefix, key)?;
MeshRedactionDecision::parse_for_key(&value, format!("{prefix}.{key}"))
}
fn required_table_default_action(
table: &Table,
prefix: &str,
) -> Result<MeshLaneDecision, ConfigParseError> {
let key = "default_action";
let value = required_table_string(table, prefix, key)?;
match normalized_config_enum_token(&value).as_str() {
"deny" => Ok(MeshLaneDecision::Deny),
_ => Err(ConfigParseError::InvalidValue {
key: format!("{prefix}.{key}"),
value,
message: "expected `deny`; mesh peer policies are default-deny".to_string(),
}),
}
}
fn optional_table_default_action(
table: &Table,
prefix: &str,
) -> Result<Option<MeshLaneDecision>, ConfigParseError> {
let key = "default_action";
let Some(value) = optional_table_string(table, prefix, key)? else {
return Ok(None);
};
match normalized_config_enum_token(&value).as_str() {
"deny" => Ok(Some(MeshLaneDecision::Deny)),
_ => Err(ConfigParseError::InvalidValue {
key: format!("{prefix}.{key}"),
value,
message: "expected `deny`; mesh peer-group bindings are default-deny".to_string(),
}),
}
}
fn optional_table_string_array(
table: &Table,
prefix: &str,
key: &str,
) -> Result<Option<Vec<String>>, ConfigParseError> {
let Some(value) = table.get(key) else {
return Ok(None);
};
let Some(array) = value.as_array() else {
return Err(ConfigParseError::InvalidType {
key: format!("{prefix}.{key}"),
expected: "an array of strings",
});
};
let mut out = Vec::new();
for entry in array.iter() {
match entry {
Value::String(text) => out.push(text.value().to_string()),
_ => {
return Err(ConfigParseError::InvalidType {
key: format!("{prefix}.{key}"),
expected: "an array of strings",
});
}
}
}
Ok(Some(out))
}
fn required_table_string_array(
table: &Table,
prefix: &str,
key: &str,
) -> Result<Vec<String>, ConfigParseError> {
optional_table_string_array(table, prefix, key)?.ok_or_else(|| ConfigParseError::InvalidType {
key: format!("{prefix}.{key}"),
expected: "an array of strings",
})
}
fn optional_regex_array_path(
document: &DocumentMut,
sections: &[&str],
key: &str,
) -> Result<Option<Vec<String>>, ConfigParseError> {
let Some(patterns) = optional_string_array_path(document, sections, key)? else {
return Ok(None);
};
for pattern in &patterns {
Regex::new(pattern).map_err(|source| ConfigParseError::InvalidValue {
key: key_path_name(sections, key),
value: pattern.clone(),
message: format!("expected a valid regex: {source}"),
})?;
}
Ok(Some(patterns))
}
#[cfg(test)]
mod tests {
use std::collections::BTreeMap;
use std::ffi::OsString;
use std::path::PathBuf;
use super::{
ConfigFile, ConfigParseError, MeshCommandMode, MeshLane, MeshLaneDecision,
MeshRedactionDecision, MeshTrustLane, PathExpander, SearchSpeed, optional_string_array,
};
use crate::models::{RedactionLevel, TrustClass};
type TestResult = Result<(), String>;
fn expect_config_error(input: &str) -> Result<ConfigParseError, String> {
match ConfigFile::parse(input) {
Ok(config) => Err(format!("expected parse error, got {config:?}")),
Err(error) => Ok(error),
}
}
fn ensure(condition: bool, message: impl Into<String>) -> TestResult {
if condition {
Ok(())
} else {
Err(message.into())
}
}
fn ensure_equal<T>(actual: &T, expected: &T, context: &str) -> TestResult
where
T: std::fmt::Debug + PartialEq,
{
if actual == expected {
Ok(())
} else {
Err(format!("{context}: expected {expected:?}, got {actual:?}"))
}
}
#[test]
fn parses_readme_style_config() -> TestResult {
let input = r#"
[storage]
database_path = "~/.local/share/ee/ee.db"
index_dir = "$EE_INDEX_ROOT"
jsonl_export = false
[storage.read_pool]
size = 4
idle_timeout_seconds = 120
max_pin_duration_seconds = 45
acquire_timeout_ms = 250
pin_snapshot = true
[runtime]
daemon = false
job_budget_ms = 5000
import_batch_size = 200
[write]
group_commit_enabled = false
batch_window_ms = 2
max_batch_size = 64
max_inflight_bytes = 4194304
[cass]
enabled = true
binary = "cass"
since = "90d"
subprocess_timeout_secs = 45
[search]
default_speed = "balanced"
lexical_weight = 0.45
semantic_weight = 0.45
graph_weight = 0.10
[search.lexical_ram_tier]
enabled = true
request_hugepages = true
populate_on_open = false
[pack]
default_profile = "balanced"
default_format = "markdown"
default_max_tokens = 4000
adaptive_budget = true
mmr_lambda = 0.7
candidate_pool = 100
memory_tier_admission = true
[handoff.stale_threshold]
memories_added = 20
any_expired_in_pack = true
content_drift_score = 0.15
memories_revised = 0
[cache.pack_l2]
enabled = true
directory = "$EE_CACHE_ROOT"
max_bytes = 1073741824
max_age_days = 30
[mesh]
enabled = false
command_mode = "off"
[swarm.adaptive]
enabled = true
prefetch_top_k = 3
prefetch_budget_ms = 50
similarity_threshold = 0.10
noisy_neighbor_p99_ms = 200
noisy_neighbor_backoff_ms = 25
[[mesh.peer_group_bindings]]
workspace_id = "wsp_local_release_001"
workspace_alias = "local-release"
peer_group_id = "pg_release_mesh_001"
peer_group_label = "release-mesh"
peer_ids = ["peer_alice_laptop_001", "peer_builder_host_001"]
origin_workspace_ids = ["wsp_remote_release_001"]
default_action = "deny"
[mesh.peer_group_bindings.lanes]
metadata = "allow"
body = "deny"
embedding = "deny"
graph_link = "allow"
revision_notice = "allow"
curation_signal = "quarantine"
[[mesh.peer_policies]]
policy_id = "pol_metadata_only_001"
workspace_id = "wsp_local_release_001"
workspace_alias = "local-release"
peer_id = "peer_builder_host_001"
peer_alias = "builder-host"
origin_workspace_ids = ["wsp_remote_release_001"]
trust_lane = "peerHumanViaPeer"
import_trust_class = "agent_assertion"
default_action = "deny"
[mesh.peer_policies.allowed_lanes]
metadata = "allow"
body = "deny"
embedding = "deny"
graph_link = "quarantine"
revision_notice = "allow"
curation_signal = "deny"
[mesh.peer_policies.redaction]
metadata = "share"
preview = "redact"
body = "deny"
embedding = "deny"
[mesh.peer_policies.body_fetch]
allowed = false
requires_consent = true
max_bytes = 0
[graph.ppr]
alpha = 0.30
[graph.health]
contradiction_threshold = 0.20
[graph.curate]
onion_decay_max = 3.0
articulation_protection_multiplier = 0.5
[graph.hits]
profile_boost = 0.5
[graph.causal]
min_cost_normalization = 1.0
[graph.pack_dna]
max_items = 10
max_edges = 30
[graph.gomory_hu]
sample_threshold = 500
sample_size = 100
[graph.memory]
snapshot_cap_mb = 250
per_algorithm_cap_mb = 100
degraded_below_pct = 80
growth_multiplier_basis_points = 15000
[curation]
duplicate_similarity = 0.92
harmful_weight = 2.5
decay_half_life_days = 60
specificity_min = 0.45
[decide]
revisit_warning_days = 21
[learn]
cluster_coherence_threshold = 0.55
[learn.decay]
demote_threshold = 0.05
forget_threshold = 0.01
working_half_life_days = 1
episodic_event_half_life_days = 30
episodic_failure_half_life_days = 90
semantic_fact_half_life_days = 180
procedural_rule_half_life_days = 365
default_half_life_days = 30
[redaction.defaults]
export = "strict"
handoff_create = "standard"
context_json = "minimal"
support_bundle = "paranoid"
[policy.secret_detector]
allow_phrases = ["OAuth refresh token", "secret ballot"]
allow_regex = ["fake-key-[A-Z]{4}"]
[policy.output_redaction]
enabled = false
[privacy]
redact_secrets = true
redaction_classes = ["api_key", "jwt", "password"]
[trust]
default_class = "agent_assertion"
prompt_injection_guard = true
"#;
let mut env = BTreeMap::new();
env.insert(
"EE_INDEX_ROOT".to_string(),
OsString::from("/tmp/ee-indexes"),
);
env.insert("EE_CACHE_ROOT".to_string(), OsString::from("/tmp/ee-cache"));
let expander = PathExpander::with_env(Some(PathBuf::from("/home/tester")), env);
let config = ConfigFile::parse_with_expander(input, &expander)
.map_err(|error| format!("config should parse: {error}"))?;
ensure_equal(
&config.storage.database_path,
&Some(PathBuf::from("/home/tester/.local/share/ee/ee.db")),
"database path",
)?;
ensure_equal(
&config.storage.index_dir,
&Some(PathBuf::from("/tmp/ee-indexes")),
"index dir",
)?;
ensure_equal(&config.storage.jsonl_export, &Some(false), "jsonl export")?;
ensure_equal(&config.storage.read_pool.size, &Some(4), "read pool size")?;
ensure_equal(
&config.storage.read_pool.idle_timeout_seconds,
&Some(120),
"read pool idle timeout",
)?;
ensure_equal(
&config.storage.read_pool.max_pin_duration_seconds,
&Some(45),
"read pool max pin duration",
)?;
ensure_equal(
&config.storage.read_pool.acquire_timeout_ms,
&Some(250),
"read pool acquire timeout",
)?;
ensure_equal(
&config.storage.read_pool.pin_snapshot,
&Some(true),
"read pool snapshot pinning",
)?;
ensure_equal(&config.runtime.job_budget_ms, &Some(5000), "job budget")?;
ensure_equal(
&config.write.group_commit_enabled,
&Some(false),
"write group commit enabled",
)?;
ensure_equal(
&config.write.batch_window_ms,
&Some(2),
"write group commit batch window",
)?;
ensure_equal(
&config.write.max_batch_size,
&Some(64),
"write group commit max batch size",
)?;
ensure_equal(
&config.write.max_inflight_bytes,
&Some(4_194_304),
"write group commit max inflight bytes",
)?;
ensure_equal(&config.cass.binary.as_deref(), &Some("cass"), "cass binary")?;
ensure_equal(
&config.cass.subprocess_timeout_secs,
&Some(45),
"cass subprocess timeout secs",
)?;
ensure_equal(
&config.search.default_speed,
&Some(SearchSpeed::Balanced),
"search speed",
)?;
ensure_equal(&config.search.lexical_weight, &Some(0.45), "lexical weight")?;
ensure_equal(
&config.search.lexical_ram_tier.enabled,
&Some(true),
"lexical RAM tier enabled",
)?;
ensure_equal(
&config.search.lexical_ram_tier.request_hugepages,
&Some(true),
"lexical RAM tier hugepages",
)?;
ensure_equal(
&config.search.lexical_ram_tier.populate_on_open,
&Some(false),
"lexical RAM tier populate",
)?;
ensure_equal(
&config.pack.default_profile.as_deref(),
&Some("balanced"),
"pack default profile",
)?;
ensure_equal(
&config.pack.default_format.as_deref(),
&Some("markdown"),
"pack default format",
)?;
ensure_equal(&config.pack.default_max_tokens, &Some(4000), "max tokens")?;
ensure_equal(
&config.pack.adaptive_budget,
&Some(true),
"adaptive pack budget",
)?;
ensure_equal(
&config.pack.memory_tier_admission,
&Some(true),
"memory tier admission",
)?;
ensure_equal(
&config.handoff.stale_threshold.memories_added,
&Some(20),
"handoff stale memories added threshold",
)?;
ensure_equal(
&config.handoff.stale_threshold.any_expired_in_pack,
&Some(true),
"handoff stale expired threshold",
)?;
ensure_equal(
&config.handoff.stale_threshold.content_drift_score,
&Some(0.15),
"handoff stale content drift threshold",
)?;
ensure_equal(
&config.handoff.stale_threshold.memories_revised,
&Some(0),
"handoff stale memories revised threshold",
)?;
ensure_equal(
&config.cache.pack_l2.enabled,
&Some(true),
"pack L2 cache enabled",
)?;
ensure_equal(
&config.cache.pack_l2.directory,
&Some(PathBuf::from("/tmp/ee-cache")),
"pack L2 cache directory",
)?;
ensure_equal(
&config.cache.pack_l2.max_bytes,
&Some(1_073_741_824),
"pack L2 cache max bytes",
)?;
ensure_equal(
&config.cache.pack_l2.max_age_days,
&Some(30),
"pack L2 cache max age",
)?;
ensure_equal(&config.mesh.enabled, &Some(false), "mesh enabled")?;
ensure_equal(
&config.mesh.command_mode,
&Some(MeshCommandMode::Off),
"mesh command mode",
)?;
ensure_equal(
&config.swarm.adaptive.enabled,
&Some(true),
"swarm adaptive enabled",
)?;
ensure_equal(
&config.swarm.adaptive.prefetch_top_k,
&Some(3),
"swarm adaptive prefetch top-k",
)?;
ensure_equal(
&config.swarm.adaptive.prefetch_budget_ms,
&Some(50),
"swarm adaptive prefetch budget",
)?;
ensure_equal(
&config.swarm.adaptive.similarity_threshold,
&Some(0.10),
"swarm adaptive similarity threshold",
)?;
ensure_equal(
&config.swarm.adaptive.noisy_neighbor_p99_ms,
&Some(200),
"swarm adaptive noisy-neighbor p99",
)?;
ensure_equal(
&config.swarm.adaptive.noisy_neighbor_backoff_ms,
&Some(25),
"swarm adaptive noisy-neighbor backoff",
)?;
let binding = config
.mesh
.peer_group_bindings
.as_ref()
.and_then(|bindings| bindings.first())
.ok_or_else(|| "expected one mesh peer-group binding".to_string())?;
ensure_equal(
&binding.workspace_id.as_deref(),
&Some("wsp_local_release_001"),
"mesh binding workspace id",
)?;
ensure_equal(
&binding.decision_for(
"wsp_local_release_001",
"peer_alice_laptop_001",
"wsp_remote_release_001",
MeshLane::Metadata,
),
&MeshLaneDecision::Allow,
"mesh metadata lane",
)?;
ensure_equal(
&binding.decision_for(
"wsp_local_release_001",
"peer_alice_laptop_001",
"wsp_remote_release_001",
MeshLane::Body,
),
&MeshLaneDecision::Deny,
"mesh body lane",
)?;
let peer_policy = config
.mesh
.peer_policies
.as_ref()
.and_then(|policies| policies.first())
.ok_or_else(|| "expected one mesh peer policy".to_string())?;
ensure_equal(
&peer_policy.policy_id.as_str(),
&"pol_metadata_only_001",
"mesh peer policy id",
)?;
ensure_equal(
&peer_policy.trust_lane,
&MeshTrustLane::PeerHumanViaPeer,
"mesh peer policy trust lane",
)?;
ensure_equal(
&peer_policy.import_trust_class,
&TrustClass::AgentAssertion,
"mesh peer policy import trust",
)?;
ensure_equal(
&peer_policy.allowed_lanes.decision(MeshLane::Metadata),
&MeshLaneDecision::Allow,
"mesh peer policy metadata lane",
)?;
ensure_equal(
&peer_policy.allowed_lanes.decision(MeshLane::Body),
&MeshLaneDecision::Deny,
"mesh peer policy body lane",
)?;
ensure_equal(
&peer_policy.redaction.body,
&MeshRedactionDecision::Deny,
"mesh peer policy body redaction",
)?;
ensure_equal(
&peer_policy.body_fetch.allowed,
&false,
"mesh peer policy body fetch allowed",
)?;
ensure_equal(&config.graph.ppr.alpha, &Some(0.30), "graph ppr alpha")?;
ensure_equal(
&config.graph.health.contradiction_threshold,
&Some(0.20),
"graph contradiction threshold",
)?;
ensure_equal(
&config.graph.curate.onion_decay_max,
&Some(3.0),
"graph onion decay max",
)?;
ensure_equal(
&config.graph.curate.articulation_protection_multiplier,
&Some(0.5),
"graph articulation protection multiplier",
)?;
ensure_equal(
&config.graph.hits.profile_boost,
&Some(0.5),
"graph hits profile boost",
)?;
ensure_equal(
&config.graph.causal.min_cost_normalization,
&Some(1.0),
"graph causal min-cost normalization",
)?;
ensure_equal(
&config.graph.pack_dna.max_items,
&Some(10),
"graph pack dna max items",
)?;
ensure_equal(
&config.graph.pack_dna.max_edges,
&Some(30),
"graph pack dna max edges",
)?;
ensure_equal(
&config.graph.gomory_hu.sample_threshold,
&Some(500),
"graph gomory-hu sample threshold",
)?;
ensure_equal(
&config.graph.gomory_hu.sample_size,
&Some(100),
"graph gomory-hu sample size",
)?;
ensure_equal(
&config.graph.memory.snapshot_cap_mb,
&Some(250),
"graph memory snapshot cap",
)?;
ensure_equal(
&config.graph.memory.per_algorithm_cap_mb,
&Some(100),
"graph memory per-algorithm cap",
)?;
ensure_equal(
&config.graph.memory.degraded_below_pct,
&Some(80),
"graph memory degraded threshold",
)?;
ensure_equal(
&config.graph.memory.growth_multiplier_basis_points,
&Some(15_000),
"graph memory growth multiplier",
)?;
ensure_equal(
&config.curation.harmful_weight,
&Some(2.5),
"harmful weight",
)?;
ensure_equal(
&config.curation.specificity_min,
&Some(0.45),
"specificity min",
)?;
ensure_equal(
&config.decide.revisit_warning_days,
&Some(21),
"decide revisit warning days",
)?;
ensure_equal(
&config.learn.decay.demote_threshold,
&Some(0.05),
"learn decay demote threshold",
)?;
ensure_equal(
&config.learn.cluster_coherence_threshold,
&Some(0.55),
"learn cluster coherence threshold",
)?;
ensure_equal(
&config.learn.decay.forget_threshold,
&Some(0.01),
"learn decay forget threshold",
)?;
ensure_equal(
&config.learn.decay.procedural_rule_half_life_days,
&Some(365.0),
"procedural rule half-life",
)?;
ensure_equal(
&config.policy.secret_detector.allow_phrases,
&Some(vec![
"OAuth refresh token".to_string(),
"secret ballot".to_string(),
]),
"secret detector allow phrases",
)?;
ensure_equal(
&config.policy.secret_detector.allow_regex,
&Some(vec!["fake-key-[A-Z]{4}".to_string()]),
"secret detector allow regex",
)?;
ensure_equal(
&config.policy.output_redaction.enabled,
&Some(false),
"output redaction enabled",
)?;
ensure_equal(
&config.redaction.defaults.export,
&Some(RedactionLevel::Strict),
"export redaction default",
)?;
ensure_equal(
&config.redaction.defaults.handoff_create,
&Some(RedactionLevel::Standard),
"handoff create redaction default",
)?;
ensure_equal(
&config.redaction.defaults.context_json,
&Some(RedactionLevel::Minimal),
"context JSON redaction default",
)?;
ensure_equal(
&config.redaction.defaults.support_bundle,
&Some(RedactionLevel::Paranoid),
"support bundle redaction default",
)?;
ensure_equal(
&config.privacy.redaction_classes,
&Some(vec![
"api_key".to_string(),
"jwt".to_string(),
"password".to_string(),
]),
"redaction classes",
)?;
ensure_equal(
&config.trust.prompt_injection_guard,
&Some(true),
"prompt injection guard",
)
}
#[test]
fn missing_sections_default_to_none() -> TestResult {
let config =
ConfigFile::parse("").map_err(|error| format!("empty config should parse: {error}"))?;
ensure_equal(&config.storage.database_path, &None, "database path")?;
ensure_equal(&config.storage.read_pool.size, &None, "read pool size")?;
ensure_equal(
&config.storage.read_pool.idle_timeout_seconds,
&None,
"read pool idle timeout",
)?;
ensure_equal(
&config.storage.read_pool.max_pin_duration_seconds,
&None,
"read pool max pin duration",
)?;
ensure_equal(
&config.storage.read_pool.acquire_timeout_ms,
&None,
"read pool acquire timeout",
)?;
ensure_equal(
&config.storage.read_pool.pin_snapshot,
&None,
"read pool pin snapshot",
)?;
ensure_equal(&config.runtime.daemon, &None, "runtime daemon")?;
ensure_equal(
&config.write.group_commit_enabled,
&None,
"write group commit enabled",
)?;
ensure_equal(
&config.write.batch_window_ms,
&None,
"write group commit batch window",
)?;
ensure_equal(
&config.write.max_batch_size,
&None,
"write group commit max batch size",
)?;
ensure_equal(
&config.write.max_inflight_bytes,
&None,
"write group commit max inflight bytes",
)?;
ensure_equal(&config.search.default_speed, &None, "search default speed")?;
ensure_equal(
&config.search.lexical_ram_tier.enabled,
&None,
"lexical RAM tier enabled",
)?;
ensure_equal(
&config.search.lexical_ram_tier.request_hugepages,
&None,
"lexical RAM tier hugepages",
)?;
ensure_equal(
&config.search.lexical_ram_tier.populate_on_open,
&None,
"lexical RAM tier populate",
)?;
ensure_equal(
&config.learn.decay.demote_threshold,
&None,
"learn decay threshold",
)?;
ensure_equal(
&config.learn.cluster_coherence_threshold,
&None,
"learn cluster coherence threshold",
)?;
ensure_equal(
&config.policy.secret_detector.allow_phrases,
&None,
"allow phrases",
)?;
ensure_equal(
&config.policy.output_redaction.enabled,
&None,
"output redaction enabled",
)?;
ensure_equal(
&config.redaction.defaults.export,
&None,
"export redaction default",
)?;
ensure_equal(
&config.redaction.defaults.handoff_create,
&None,
"handoff create redaction default",
)?;
ensure_equal(
&config.redaction.defaults.context_json,
&None,
"context JSON redaction default",
)?;
ensure_equal(
&config.redaction.defaults.support_bundle,
&None,
"support bundle redaction default",
)?;
ensure_equal(
&config.handoff.stale_threshold.memories_added,
&None,
"handoff stale memories added threshold",
)?;
ensure_equal(
&config.handoff.stale_threshold.any_expired_in_pack,
&None,
"handoff stale expired threshold",
)?;
ensure_equal(
&config.cache.pack_l2.enabled,
&None,
"pack L2 cache enabled",
)?;
ensure_equal(
&config.cache.pack_l2.directory,
&None,
"pack L2 cache directory",
)?;
ensure_equal(
&config.cache.pack_l2.max_bytes,
&None,
"pack L2 cache max bytes",
)?;
ensure_equal(
&config.cache.pack_l2.max_age_days,
&None,
"pack L2 cache max age",
)?;
ensure_equal(&config.task_lens.overrides.len(), &0, "task lens overrides")?;
ensure_equal(&config.graph.ppr.alpha, &None, "graph ppr alpha")?;
ensure_equal(&config.mesh.enabled, &None, "mesh enabled")?;
ensure_equal(&config.mesh.command_mode, &None, "mesh command mode")?;
ensure_equal(
&config.swarm.adaptive.enabled,
&None,
"swarm adaptive enabled",
)?;
ensure_equal(
&config.swarm.adaptive.prefetch_top_k,
&None,
"swarm adaptive prefetch top-k",
)?;
ensure_equal(
&config.swarm.adaptive.prefetch_budget_ms,
&None,
"swarm adaptive prefetch budget",
)?;
ensure_equal(
&config.swarm.adaptive.similarity_threshold,
&None,
"swarm adaptive similarity threshold",
)?;
ensure_equal(
&config.swarm.adaptive.noisy_neighbor_p99_ms,
&None,
"swarm adaptive noisy-neighbor p99",
)?;
ensure_equal(
&config.swarm.adaptive.noisy_neighbor_backoff_ms,
&None,
"swarm adaptive noisy-neighbor backoff",
)?;
ensure_equal(
&config.mesh.peer_group_bindings,
&None,
"mesh peer-group bindings",
)?;
ensure_equal(
&config.graph.gomory_hu.sample_threshold,
&None,
"graph gomory-hu sample threshold",
)?;
ensure_equal(
&config.graph.memory.snapshot_cap_mb,
&None,
"graph memory snapshot cap",
)?;
ensure_equal(
&config.privacy.redaction_classes,
&None,
"redaction classes",
)
}
#[test]
fn parses_task_lens_workspace_override() -> TestResult {
let config = ConfigFile::parse(
r#"
[[task_lens.overrides]]
id = "BugFix"
version = 2
description = "Local bugfix lens for a small checkout."
context_profile = "compact"
source_mode = "lexical-only"
strict_source_mode = true
pack_profile = "lean"
resource_profile = "lean"
redaction = "strict"
memory_scope = "workspace"
max_tokens = 3000
candidate_pool = 80
max_results = 20
coverage_facets = ["root-cause", "verification"]
allowed_kinds = ["failure", "risk"]
deprioritized_kinds = ["fact"]
"#,
)
.map_err(|error| format!("task lens override should parse: {error}"))?;
ensure_equal(&config.task_lens.overrides.len(), &1, "override count")?;
let lens = &config.task_lens.overrides[0];
ensure_equal(&lens.id.as_str(), &"bugfix", "normalized id")?;
ensure_equal(&lens.version, &2, "version")?;
ensure_equal(
&lens.overlay.context_profile.as_deref(),
&Some("compact"),
"context profile",
)?;
ensure_equal(
&lens.overlay.source_mode.as_deref(),
&Some("lexical_only"),
"source mode",
)?;
ensure_equal(
&lens.overlay.strict_source_mode,
&Some(true),
"strict source mode",
)?;
ensure_equal(
&lens.overlay.redaction,
&Some(RedactionLevel::Strict),
"redaction",
)?;
ensure(
lens.lens_hash.starts_with("blake3:"),
"lens hash should use stable blake3 prefix",
)
}
#[test]
fn rejects_unknown_task_lens_key_with_indexed_suggestion() -> TestResult {
let error = expect_config_error(
r#"
[[task_lens.overrides]]
id = "bugfix"
description = "Bug-fixing lens."
allowed_kind = ["failure"]
"#,
)?;
ensure(
matches!(
error,
ConfigParseError::UnknownKey {
ref key,
suggestion: Some(ref suggestion),
} if key == "task_lens.overrides[0].allowed_kind"
&& suggestion == "task_lens.overrides[0].allowed_kinds"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn rejects_removed_trust_team_members_nickname_list() -> TestResult {
let error = expect_config_error("[trust]\nteam_members = [\"GreenField\"]\n")?;
ensure(
matches!(
error,
ConfigParseError::UnknownKey {
ref key,
..
} if key == "trust.team_members"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn rejects_unknown_root_table_without_misleading_suggestion() -> TestResult {
let error = expect_config_error("[lens.math_verify]\nenabled = true\n")?;
ensure(
matches!(
error,
ConfigParseError::UnknownKey {
ref key,
suggestion: None,
} if key == "lens"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn rejects_unknown_inline_table_key() -> TestResult {
let error = expect_config_error(
"search = { default_speed = \"balanced\", default_speeed = \"fast\" }\n",
)?;
ensure(
matches!(
error,
ConfigParseError::UnknownKey {
ref key,
suggestion: Some(ref suggestion),
} if key == "search.default_speeed" && suggestion == "search.default_speed"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn rejects_unknown_nested_mesh_key_with_indexed_suggestion() -> TestResult {
let error = expect_config_error(
r#"
[[mesh.peer_group_bindings]]
workspace_id = "workspace-local"
[mesh.peer_group_bindings.lanes]
metdata = "allow"
"#,
)?;
ensure(
matches!(
error,
ConfigParseError::UnknownKey {
ref key,
suggestion: Some(ref suggestion),
} if key == "mesh.peer_group_bindings[0].lanes.metdata"
&& suggestion == "mesh.peer_group_bindings[0].lanes.metadata"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn accepts_dynamic_graph_witness_algorithm_keys() -> TestResult {
let config = ConfigFile::parse(
r#"
[graph.witnesses.algorithm_ttl_days]
ppr = 7
custom_ranker = 21
"#,
)
.map_err(|error| format!("dynamic witness keys should parse: {error}"))?;
let expected = BTreeMap::from([("custom_ranker".to_string(), 21), ("ppr".to_string(), 7)]);
ensure_equal(
&config.graph.witnesses.algorithm_ttl_days,
&Some(expected),
"algorithm TTL map",
)
}
#[test]
fn accepts_externally_owned_profile_keys() -> TestResult {
ConfigFile::parse(
r#"
[profile]
selected = "portable"
[profile.budgets]
search_candidate_limit = 100
pack_max_tokens = 4000
steward_daemon_prewarm = false
verification_recipe = "standard"
diagnostics_redaction = "strict"
"#,
)
.map(|_| ())
.map_err(|error| format!("profile-generated config should parse: {error}"))
}
#[test]
fn rejects_bad_task_lens_workspace_override() -> TestResult {
let error = expect_config_error(
r#"
[[task_lens.overrides]]
id = "bad lens"
version = 1
description = "Bad lens."
source_mode = "random"
"#,
)?;
ensure(
matches!(
error,
ConfigParseError::InvalidValue { ref key, ref value, .. }
if key == "task_lens.overrides[0]" && value == "bad lens"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn rejects_wrong_type_for_known_key() -> TestResult {
let error = expect_config_error("[runtime]\njob_budget_ms = \"slow\"\n")?;
ensure(
matches!(
error,
ConfigParseError::InvalidType { ref key, expected }
if key == "runtime.job_budget_ms" && expected == "an integer"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn known_type_errors_precede_unknown_key_errors() -> TestResult {
let error =
expect_config_error("[runtime]\njob_budget_ms = \"slow\"\njob_budget_mss = 5000\n")?;
ensure(
matches!(
error,
ConfigParseError::InvalidType { ref key, expected }
if key == "runtime.job_budget_ms" && expected == "an integer"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn rejects_unknown_search_speed() -> TestResult {
let error = expect_config_error("[search]\ndefault_speed = \"reckless\"\n")?;
ensure(
matches!(
error,
ConfigParseError::InvalidValue { ref key, .. }
if key == "search.default_speed"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn rejects_wrong_type_for_lexical_ram_tier_bool() -> TestResult {
let error = expect_config_error("[search.lexical_ram_tier]\nenabled = \"yes\"\n")?;
ensure(
matches!(
error,
ConfigParseError::InvalidType { ref key, expected }
if key == "search.lexical_ram_tier.enabled" && expected == "a boolean"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn search_speed_normalizes_config_values() -> TestResult {
let config = ConfigFile::parse("[search]\ndefault_speed = \" Thorough \"\n")
.map_err(|error| format!("search speed should parse: {error}"))?;
ensure_equal(
&config.search.default_speed,
&Some(SearchSpeed::Thorough),
"normalized search speed",
)
}
#[test]
fn search_query_miss_retention_days_parses() -> TestResult {
let config = ConfigFile::parse("[search]\nquery_miss_retention_days = 30\n")
.map_err(|error| format!("query miss retention should parse: {error}"))?;
ensure_equal(
&config.search.query_miss_retention_days,
&Some(30),
"query miss retention days",
)
}
#[test]
fn rejects_unknown_redaction_default_level() -> TestResult {
let error = expect_config_error("[redaction.defaults]\ncontext_json = \"full\"\n")?;
ensure(
matches!(
error,
ConfigParseError::InvalidValue { ref key, ref value, .. }
if key == "redaction.defaults.context_json" && value == "full"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn rejects_out_of_range_unit_weights() -> TestResult {
let error = expect_config_error("[pack]\nmmr_lambda = 1.5\n")?;
ensure(
matches!(
error,
ConfigParseError::InvalidValue { ref key, .. } if key == "pack.mmr_lambda"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn rejects_out_of_range_swarm_adaptive_threshold() -> TestResult {
let error = expect_config_error("[swarm.adaptive]\nsimilarity_threshold = 1.5\n")?;
ensure(
matches!(
error,
ConfigParseError::InvalidValue { ref key, .. }
if key == "swarm.adaptive.similarity_threshold"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn rejects_out_of_range_graph_thresholds() -> TestResult {
let error = expect_config_error("[graph.health]\ncontradiction_threshold = 2.0\n")?;
ensure(
matches!(
error,
ConfigParseError::InvalidValue { ref key, .. }
if key == "graph.health.contradiction_threshold"
),
format!("unexpected error: {error:?}"),
)?;
let error = expect_config_error("[graph.curate]\nonion_decay_max = 0.0\n")?;
ensure(
matches!(
error,
ConfigParseError::InvalidValue { ref key, .. }
if key == "graph.curate.onion_decay_max"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn rejects_out_of_range_graph_memory_limits() -> TestResult {
for (input, expected_key) in [
(
"[graph.memory]\nsnapshot_cap_mb = 0\n",
"graph.memory.snapshot_cap_mb",
),
(
"[graph.memory]\nper_algorithm_cap_mb = 0\n",
"graph.memory.per_algorithm_cap_mb",
),
(
"[graph.memory]\ndegraded_below_pct = 101\n",
"graph.memory.degraded_below_pct",
),
(
"[graph.memory]\ngrowth_multiplier_basis_points = 0\n",
"graph.memory.growth_multiplier_basis_points",
),
] {
let error = expect_config_error(input)?;
ensure(
matches!(
error,
ConfigParseError::InvalidValue { ref key, .. } if key == expected_key
),
format!("unexpected error for {expected_key}: {error:?}"),
)?;
}
Ok(())
}
#[test]
fn peer_group_binding_denies_without_explicit_workspace_binding() -> TestResult {
let config = ConfigFile::parse(
r#"
[[mesh.peer_group_bindings]]
workspace_id = "wsp_workspace_a_001"
workspace_alias = "workspace-a"
peer_group_id = "pg_team_alpha_001"
peer_ids = ["peer_agent_001"]
origin_workspace_ids = ["wsp_origin_001"]
[mesh.peer_group_bindings.lanes]
metadata = "allow"
"#,
)
.map_err(|error| format!("config should parse: {error}"))?;
let binding = config
.mesh
.peer_group_bindings
.as_ref()
.and_then(|bindings| bindings.first())
.ok_or_else(|| "expected peer-group binding".to_string())?;
ensure_equal(
&binding.decision_for(
"wsp_workspace_b_001",
"peer_agent_001",
"wsp_origin_001",
MeshLane::Metadata,
),
&MeshLaneDecision::Deny,
"workspace B without explicit binding must deny",
)
}
#[test]
fn mesh_command_mode_parses_all_stable_modes() -> TestResult {
for (raw, expected) in [
("off", MeshCommandMode::Off),
("cache", MeshCommandMode::Cache),
("revisable", MeshCommandMode::Revisable),
("blocking", MeshCommandMode::Blocking),
(" Blocking ", MeshCommandMode::Blocking),
] {
let config = ConfigFile::parse(&format!("[mesh]\ncommand_mode = \"{raw}\"\n"))
.map_err(|error| format!("mesh mode {raw} should parse: {error}"))?;
ensure_equal(
&config.mesh.command_mode,
&Some(expected),
"mesh command mode",
)?;
ensure_equal(
&expected.as_str(),
&raw.trim().to_ascii_lowercase().as_str(),
"mesh command mode string",
)?;
}
Ok(())
}
#[test]
fn mesh_command_mode_rejects_unknown_mode() -> TestResult {
let error = expect_config_error("[mesh]\ncommand_mode = \"auto\"\n")?;
ensure(
matches!(
error,
ConfigParseError::InvalidValue { ref key, .. }
if key == "mesh.command_mode"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn peer_group_binding_can_allow_metadata_while_denying_body_and_embedding() -> TestResult {
let config = ConfigFile::parse(
r#"
[[mesh.peer_group_bindings]]
workspace_id = "wsp_workspace_a_001"
workspace_alias = "workspace-a"
peer_group_id = "pg_team_alpha_001"
peer_ids = ["peer_agent_001"]
origin_workspace_ids = ["wsp_origin_001"]
[mesh.peer_group_bindings.lanes]
metadata = "allow"
body = "deny"
embedding = "deny"
revision_notice = "allow"
"#,
)
.map_err(|error| format!("config should parse: {error}"))?;
let binding = config
.mesh
.peer_group_bindings
.as_ref()
.and_then(|bindings| bindings.first())
.ok_or_else(|| "expected peer-group binding".to_string())?;
for (lane, expected, context) in [
(MeshLane::Metadata, MeshLaneDecision::Allow, "metadata"),
(MeshLane::Body, MeshLaneDecision::Deny, "body"),
(MeshLane::Embedding, MeshLaneDecision::Deny, "embedding"),
] {
ensure_equal(
&binding.decision_for(
"wsp_workspace_a_001",
"peer_agent_001",
"wsp_origin_001",
lane,
),
&expected,
context,
)?;
}
Ok(())
}
#[test]
fn peer_group_binding_missing_lane_and_unknown_origin_deny_by_default() -> TestResult {
let config = ConfigFile::parse(
r#"
[[mesh.peer_group_bindings]]
workspace_id = "wsp_workspace_a_001"
workspace_alias = "workspace-a"
peer_group_id = "pg_team_alpha_001"
peer_ids = ["peer_agent_001"]
origin_workspace_ids = ["wsp_origin_001"]
[mesh.peer_group_bindings.lanes]
metadata = "allow"
"#,
)
.map_err(|error| format!("config should parse: {error}"))?;
let binding = config
.mesh
.peer_group_bindings
.as_ref()
.and_then(|bindings| bindings.first())
.ok_or_else(|| "expected peer-group binding".to_string())?;
ensure_equal(
&binding.decision_for(
"wsp_workspace_a_001",
"peer_agent_001",
"wsp_unknown_origin_001",
MeshLane::Metadata,
),
&MeshLaneDecision::Deny,
"unknown origin must deny",
)?;
ensure_equal(
&binding.decision_for(
"wsp_workspace_a_001",
"peer_agent_001",
"wsp_origin_001",
MeshLane::CurationSignal,
),
&MeshLaneDecision::Deny,
"missing curation signal lane must deny",
)
}
#[test]
fn peer_group_binding_rejects_non_deny_default_action() -> TestResult {
let error = expect_config_error(
r#"
[[mesh.peer_group_bindings]]
workspace_id = "wsp_workspace_a_001"
workspace_alias = "workspace-a"
peer_group_id = "pg_team_alpha_001"
peer_ids = ["peer_agent_001"]
origin_workspace_ids = ["wsp_origin_001"]
default_action = "allow"
"#,
)?;
ensure(
matches!(
error,
ConfigParseError::InvalidValue { ref key, .. }
if key == "mesh.peer_group_bindings[0].default_action"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn peer_policy_parses_default_deny_redaction_and_body_fetch() -> TestResult {
let config = ConfigFile::parse(
r#"
[[mesh.peer_policies]]
policy_id = "pol_body_denied_001"
workspace_id = "wsp_workspace_a_001"
workspace_alias = "workspace-a"
peer_id = "peer_agent_001"
peer_alias = "agent-one"
origin_workspace_ids = ["wsp_origin_001"]
trust_lane = "peerAgent"
import_trust_class = "agent_validated"
default_action = "deny"
[mesh.peer_policies.allowed_lanes]
metadata = "allow"
body = "deny"
embedding = "deny"
graph_link = "allow"
revision_notice = "allow"
curation_signal = "quarantine"
[mesh.peer_policies.redaction]
metadata = "share"
preview = "redact"
body = "deny"
embedding = "deny"
[mesh.peer_policies.body_fetch]
allowed = false
requires_consent = true
max_bytes = 0
"#,
)
.map_err(|error| format!("config should parse: {error}"))?;
let policy = config
.mesh
.peer_policies
.as_ref()
.and_then(|policies| policies.first())
.ok_or_else(|| "expected peer policy".to_string())?;
ensure_equal(
&policy.policy_id.as_str(),
&"pol_body_denied_001",
"policy id",
)?;
ensure_equal(&policy.trust_lane, &MeshTrustLane::PeerAgent, "trust lane")?;
ensure_equal(
&policy.import_trust_class,
&TrustClass::AgentValidated,
"import trust class",
)?;
ensure_equal(
&policy.allowed_lanes.decision(MeshLane::CurationSignal),
&MeshLaneDecision::Quarantine,
"curation signal lane",
)?;
ensure_equal(
&policy.redaction.preview,
&MeshRedactionDecision::Redact,
"preview redaction",
)?;
ensure_equal(&policy.body_fetch.max_bytes, &Some(0), "body max bytes")
}
#[test]
fn mesh_policy_values_accept_operator_spelling_variants() -> TestResult {
let config = ConfigFile::parse(
r#"
[[mesh.peer_group_bindings]]
workspace_id = "wsp_workspace_a_001"
peer_ids = ["peer_agent_001"]
origin_workspace_ids = ["wsp_origin_001"]
default_action = " DENY "
[mesh.peer_group_bindings.lanes]
metadata = " ALLOW "
body = "deny"
[[mesh.peer_policies]]
policy_id = "pol_variants_001"
workspace_id = "wsp_workspace_a_001"
peer_id = "peer_agent_001"
origin_workspace_ids = ["wsp_origin_001"]
trust_lane = " peer-agent "
import_trust_class = "agent-validated"
default_action = " DENY "
[mesh.peer_policies.allowed_lanes]
metadata = "ALLOW"
body = "deny"
embedding = " Deny "
graph_link = "allow"
revision_notice = "allow"
curation_signal = "QUARANTINE"
[mesh.peer_policies.redaction]
metadata = "SHARE"
preview = " redact "
body = "deny"
embedding = "deny"
[mesh.peer_policies.body_fetch]
allowed = false
requires_consent = true
"#,
)
.map_err(|error| format!("config should parse spelling variants: {error}"))?;
let binding = config
.mesh
.peer_group_bindings
.as_ref()
.and_then(|bindings| bindings.first())
.ok_or_else(|| "expected peer-group binding".to_string())?;
ensure_equal(
&binding.decision_for(
"wsp_workspace_a_001",
"peer_agent_001",
"wsp_origin_001",
MeshLane::Metadata,
),
&MeshLaneDecision::Allow,
"peer-group lane decision",
)?;
let policy = config
.mesh
.peer_policies
.as_ref()
.and_then(|policies| policies.first())
.ok_or_else(|| "expected peer policy".to_string())?;
ensure_equal(&policy.trust_lane, &MeshTrustLane::PeerAgent, "trust lane")?;
ensure_equal(
&policy.import_trust_class,
&TrustClass::AgentValidated,
"import trust class",
)?;
ensure_equal(
&policy.allowed_lanes.decision(MeshLane::CurationSignal),
&MeshLaneDecision::Quarantine,
"curation signal lane",
)?;
ensure_equal(
&policy.redaction.preview,
&MeshRedactionDecision::Redact,
"preview redaction",
)
}
#[test]
fn peer_policy_rejects_missing_required_redaction_field() -> TestResult {
let error = expect_config_error(
r#"
[[mesh.peer_policies]]
policy_id = "pol_missing_redaction_001"
workspace_id = "wsp_workspace_a_001"
peer_id = "peer_agent_001"
origin_workspace_ids = ["wsp_origin_001"]
trust_lane = "peerAgent"
import_trust_class = "agent_validated"
default_action = "deny"
[mesh.peer_policies.allowed_lanes]
metadata = "allow"
body = "deny"
embedding = "deny"
graph_link = "allow"
revision_notice = "allow"
curation_signal = "deny"
[mesh.peer_policies.redaction]
metadata = "share"
preview = "redact"
body = "deny"
[mesh.peer_policies.body_fetch]
allowed = false
requires_consent = true
"#,
)?;
ensure(
matches!(
error,
ConfigParseError::InvalidType { ref key, .. }
if key == "mesh.peer_policies[0].redaction.embedding"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn peer_policy_rejects_local_human_lane_and_non_peer_safe_import_trust() -> TestResult {
let local_human_error = expect_config_error(
r#"
[[mesh.peer_policies]]
policy_id = "pol_local_human_001"
workspace_id = "wsp_workspace_a_001"
peer_id = "peer_agent_001"
origin_workspace_ids = ["wsp_origin_001"]
trust_lane = "localHuman"
import_trust_class = "agent_validated"
default_action = "deny"
[mesh.peer_policies.allowed_lanes]
metadata = "allow"
body = "deny"
embedding = "deny"
graph_link = "allow"
revision_notice = "allow"
curation_signal = "deny"
[mesh.peer_policies.redaction]
metadata = "share"
preview = "redact"
body = "deny"
embedding = "deny"
[mesh.peer_policies.body_fetch]
allowed = false
requires_consent = true
"#,
)?;
ensure(
matches!(
local_human_error,
ConfigParseError::InvalidValue { ref key, .. }
if key == "mesh.peer_policies[0].trust_lane"
),
format!("unexpected localHuman error: {local_human_error:?}"),
)?;
for disallowed_class in [
"human_explicit",
"peer_human_attested",
"cass_evidence",
"legacy_import",
] {
let config = format!(
r#"
[[mesh.peer_policies]]
policy_id = "pol_disallowed_import_001"
workspace_id = "wsp_workspace_a_001"
peer_id = "peer_agent_001"
origin_workspace_ids = ["wsp_origin_001"]
trust_lane = "peerAgent"
import_trust_class = "{disallowed_class}"
default_action = "deny"
[mesh.peer_policies.allowed_lanes]
metadata = "allow"
body = "deny"
embedding = "deny"
graph_link = "allow"
revision_notice = "allow"
curation_signal = "deny"
[mesh.peer_policies.redaction]
metadata = "share"
preview = "redact"
body = "deny"
embedding = "deny"
[mesh.peer_policies.body_fetch]
allowed = false
requires_consent = true
"#,
);
let error = expect_config_error(&config)?;
ensure(
matches!(
error,
ConfigParseError::InvalidValue { ref key, ref value, ref message }
if key == "mesh.peer_policies[0].import_trust_class"
&& value == disallowed_class
&& message.contains("agent_assertion")
&& message.contains("agent_validated")
&& message.contains("peer_human_attested")
&& message.contains("human_explicit")
&& message.contains("cass_evidence")
&& message.contains("legacy_import")
),
format!("unexpected {disallowed_class} error: {error:?}"),
)?;
}
Ok(())
}
#[test]
fn rejects_invalid_learn_decay_values() -> TestResult {
let cluster_error = expect_config_error("[learn]\ncluster_coherence_threshold = 1.5\n")?;
ensure(
matches!(
cluster_error,
ConfigParseError::InvalidValue { ref key, .. }
if key == "learn.cluster_coherence_threshold"
),
format!("unexpected cluster threshold error: {cluster_error:?}"),
)?;
let threshold_error = expect_config_error("[learn.decay]\ndemote_threshold = 1.5\n")?;
ensure(
matches!(
threshold_error,
ConfigParseError::InvalidValue { ref key, .. }
if key == "learn.decay.demote_threshold"
),
format!("unexpected threshold error: {threshold_error:?}"),
)?;
let half_life_error =
expect_config_error("[learn.decay]\nprocedural_rule_half_life_days = 0\n")?;
ensure(
matches!(
half_life_error,
ConfigParseError::InvalidValue { ref key, .. }
if key == "learn.decay.procedural_rule_half_life_days"
),
format!("unexpected half-life error: {half_life_error:?}"),
)
}
#[test]
fn rejects_invalid_handoff_stale_threshold_values() -> TestResult {
let drift_error =
expect_config_error("[handoff.stale_threshold]\ncontent_drift_score = 1.5\n")?;
ensure(
matches!(
drift_error,
ConfigParseError::InvalidValue { ref key, .. }
if key == "handoff.stale_threshold.content_drift_score"
),
format!("unexpected drift threshold error: {drift_error:?}"),
)?;
let added_error = expect_config_error("[handoff.stale_threshold]\nmemories_added = -1\n")?;
ensure(
matches!(
added_error,
ConfigParseError::InvalidValue { ref key, .. }
if key == "handoff.stale_threshold.memories_added"
),
format!("unexpected memories added threshold error: {added_error:?}"),
)
}
#[test]
fn rejects_non_string_redaction_classes() -> TestResult {
let parsed =
"[privacy]\nredaction_classes = [\"api_key\", 7]\n".parse::<toml_edit::DocumentMut>();
let document = parsed.map_err(|error| format!("test TOML should parse: {error}"))?;
let error = match optional_string_array(&document, "privacy", "redaction_classes") {
Ok(value) => return Err(format!("expected array type error, got {value:?}")),
Err(error) => error,
};
ensure(
matches!(
error,
ConfigParseError::InvalidType { ref key, expected }
if key == "privacy.redaction_classes" && expected == "an array of strings"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn rejects_invalid_secret_detector_allow_regex() -> TestResult {
let error = expect_config_error("[policy.secret_detector]\nallow_regex = [\"[\"]\n")?;
ensure(
matches!(
error,
ConfigParseError::InvalidValue { ref key, .. }
if key == "policy.secret_detector.allow_regex"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn wraps_path_expansion_errors_with_config_key() -> TestResult {
let expander = PathExpander::with_env(Some(PathBuf::from("/home/tester")), BTreeMap::new());
let error = match ConfigFile::parse_with_expander(
"[storage]\nindex_dir = \"$EE_MISSING\"\n",
&expander,
) {
Ok(config) => return Err(format!("expected path expansion error, got {config:?}")),
Err(error) => error,
};
ensure(
matches!(
error,
ConfigParseError::PathExpansion { ref key, .. } if key == "storage.index_dir"
),
format!("unexpected error: {error:?}"),
)
}
#[test]
fn parses_memory_global_lane_keys() -> TestResult {
let config = ConfigFile::parse("[memory]\ninclude_global = false\nparticipate = true\n")
.map_err(|error| format!("parse failed: {error:?}"))?;
ensure(
config.memory.include_global == Some(false),
format!("include_global wrong: {:?}", config.memory),
)?;
ensure(
config.memory.participate == Some(true),
format!("participate wrong: {:?}", config.memory),
)
}
#[test]
fn rejects_unknown_memory_section_key() -> TestResult {
let error = match ConfigFile::parse("[memory]\ninclude_globall = true\n") {
Ok(config) => return Err(format!("expected unknown-key rejection, got {config:?}")),
Err(error) => error,
};
ensure(
format!("{error:?}").contains("include_globall"),
format!("unexpected error: {error:?}"),
)
}
}