nautalid 0.1.0

Scratch container substrate — TLS 1.3 HTTP/2+3 kernel, LID/AetherDB, optional filter bus (GPL-3.0-or-later).
//! Bus control for WebTransport ↔ AetherDB routing (paths, routes, backend mode).

use kdl::KdlNode;

use crate::bus::{response, BusModule};
use crate::wt_aether;

pub struct WebTransportModule;

impl BusModule for WebTransportModule {
    fn name(&self) -> &'static str {
        "webtransport"
    }

    fn handle(&self, module_node: &KdlNode, command_nodes: &[&KdlNode]) -> String {
        let cmd = if let Some(node) = command_nodes.first() {
            node
        } else {
            match module_node.children().and_then(|c| c.nodes().first()) {
                Some(node) => node,
                None => return response::err("missing webtransport command"),
            }
        };

        match cmd.name().value() {
            "status" => response::ok(&wt_aether::config_snapshot().status_kdl()),
            "aether" => self.handle_aether(cmd),
            other => response::err(&format!("unknown webtransport command `{other}`")),
        }
    }
}

impl WebTransportModule {
    fn handle_aether(&self, cmd: &KdlNode) -> String {
        if let Some(sub) = cmd.children().and_then(|c| c.nodes().first()) {
            if sub.name().value() == "status" {
                return response::ok(&wt_aether::config_snapshot().status_kdl());
            }
        }

        if crate::security::wt_aether_hot_reload_locked() {
            return response::err(
                "WT aether policy hot-reload is disabled (lock_wt_aether_hot_reload); restart to change WT settings",
            );
        }

        let mut cfg = wt_aether::config_snapshot();
        if let Err(err) = cfg.apply_kdl(cmd) {
            return response::err(&err);
        }
        wt_aether::update_config(|live| *live = cfg);
        response::ok("wt-aether-updated")
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use kdl::KdlDocument;

    #[test]
    fn hot_reload_rejected_when_lock_enabled() {
        crate::security::reset_for_tests();
        unsafe {
            std::env::remove_var("NAUTALID_SECURITY_KDL_PATH");
            std::env::remove_var("NAUTALID_SECURITY_PROFILE");
            std::env::set_var("NAUTALID_SECURITY_LOCK_WT_AETHER_HOT_RELOAD", "1");
        }
        let _ = crate::security::init();
        let doc: KdlDocument = r#"webtransport {
    aether {
        enable #true
    }
}"#
        .parse()
        .unwrap();
        let module_node = doc.nodes().first().unwrap();
        let cmd = module_node.children().unwrap().nodes().first().unwrap();
        let out = WebTransportModule.handle(module_node, &[cmd]);
        assert!(out.contains("hot-reload is disabled"));
        crate::security::reset_for_tests();
        unsafe {
            std::env::remove_var("NAUTALID_SECURITY_LOCK_WT_AETHER_HOT_RELOAD");
        }
    }
}