liminal-server 0.27.7

Standalone server for the liminal messaging bus
Documentation
use super::*;

// ---- ACCESS-013 R2: the agent registry at the top level, one source of truth ----

const BOTH: &str = "agents are written once: at the top level or under [auth.lys], not both";

fn lys_auth(agents: &str) -> Result<AuthConfig, Box<dyn std::error::Error>> {
    Ok(toml::from_str(&format!(
        "token = \"s3cr3t\"\n[lys]\nissuer = \"https://lys.test\"\nnetwork_id = \"n\"\n\
         keys_path = \"/k\"\napp_credential_path = \"/c\"\n{agents}"
    ))?)
}

#[test]
fn access013_an_open_exchange_with_top_level_agents_validates()
-> Result<(), Box<dyn std::error::Error>> {
    let mut config = sample_config()?;
    config.auth = None;
    config.cluster = None;
    config.agents = Some(crate::agents::config::AgentsConfig::default());
    config.limits.max_channels = Some(64);
    let message = config_validation_message(validate(&mut config, None));
    assert_eq!(message, "", "an open exchange with [agents] validates");
    assert_eq!(config.agents_place(), "top");
    assert!(config.agents_config().is_some());
    Ok(())
}

#[test]
fn access013_agents_in_both_places_are_refused_by_the_exact_words()
-> Result<(), Box<dyn std::error::Error>> {
    let mut config = sample_config()?;
    config.auth = Some(lys_auth("[lys.agents]\n")?);
    config.agents = Some(crate::agents::config::AgentsConfig::default());
    let message = config_validation_message(validate(&mut config, None));
    assert!(
        message.lines().any(|line| line == BOTH),
        "missing {BOTH:?} in {message:?}"
    );
    Ok(())
}

#[test]
fn access013_a_gated_exchange_names_where_its_agents_are_written()
-> Result<(), Box<dyn std::error::Error>> {
    let mut config = sample_config()?;
    config.auth = Some(lys_auth("")?);
    config.agents = Some(crate::agents::config::AgentsConfig::default());
    let message = config_validation_message(validate(&mut config, None));
    assert!(!message.contains(BOTH), "{message}");
    assert_eq!(config.agents_place(), "top");
    config.agents = None;
    config.auth = Some(lys_auth("[lys.agents]\n")?);
    assert_eq!(config.agents_place(), "auth.lys");
    assert!(config.agents_config().is_some());
    config.auth = Some(lys_auth("")?);
    assert_eq!(config.agents_place(), "none");
    assert!(config.agents_config().is_none());
    Ok(())
}

#[test]
fn access013_a_registry_without_a_channel_bound_is_refused_by_name()
-> Result<(), Box<dyn std::error::Error>> {
    const UNBOUNDED: &str = "agents: each station's inbox is a channel registered at runtime; write [limits] max_channels";
    for place in ["top", "auth.lys"] {
        let mut config = sample_config()?;
        config.limits.max_channels = None;
        if place == "top" {
            config.auth = None;
            config.cluster = None;
            config.agents = Some(crate::agents::config::AgentsConfig::default());
        } else {
            config.auth = Some(lys_auth("[lys.agents]\n")?);
        }
        let message = config_validation_message(validate(&mut config, None));
        assert!(
            message.lines().any(|line| line == UNBOUNDED),
            "{place}: missing {UNBOUNDED:?} in {message:?}"
        );
    }
    Ok(())
}