nautalid 0.1.0

Scratch container substrate — TLS 1.3 HTTP/2+3 kernel, LID/AetherDB, optional filter bus (GPL-3.0-or-later).
//! Inline AetherDB KDL for Nautalid wire clients, hub, and cluster data nodes.

use super::topology::Topology;
use crate::aether_tunnel::WireTls;

pub const WIRE_REPLICA_PRESET: &str = "nautalid-wire-client";
pub const HOST_DATA_PRESET: &str = "nautalid-data";

pub fn wire_client_kdl(topology: &Topology, replicate_hex: &str) -> String {
    format!(
        r#"preset "{WIRE_REPLICA_PRESET}" {{
    consistency "strong"
    replication {}
    shards {}
    indexes primary="bplus"
    query "{}"
    durability "wal"
    transport local
    route "storage" handler="storage"
    route "replicate" handler="replication"
    replicate_auth {{
        master_key_hex "{replicate_hex}"
    }}
}}
"#,
        topology.replication, topology.shards, topology.query,
    )
}

pub fn wire_client_kdl_tls(
    topology: &Topology,
    endpoint: &str,
    tls: &WireTls,
    replicate_hex: &str,
) -> String {
    format!(
        r#"preset "{WIRE_REPLICA_PRESET}" {{
    consistency "strong"
    replication {}
    shards {}
    indexes primary="bplus"
    query "{}"
    durability "wal"
    transport zeromq connect="{endpoint}" pattern="router-dealer" {{
        tls {{
            cert_file "{}"
            key_file "{}"
            ca_file "{}"
            client_auth #true
        }}
    }}
    route "storage" handler="storage"
    route "replicate" handler="replication"
    replicate_auth {{
        master_key_hex "{replicate_hex}"
    }}
}}
"#,
        topology.replication,
        topology.shards,
        topology.query,
        tls.cert_file.display(),
        tls.key_file.display(),
        tls.ca_file.display(),
    )
}

pub fn host_data_kdl(
    topology: &Topology,
    bind: &str,
    replicate_hex: &str,
    tls_block: &str,
    control_key_hex: Option<&str>,
) -> String {
    let cluster_block = if topology.is_cluster() {
        let leader = if topology.bootstrap_leader() {
            "\n        bootstrap_leader #true"
        } else {
            ""
        };
        let control_kwt = control_key_hex.map_or(String::new(), |hex| {
            format!(
                r#"
        kwt {{
            mode "required"
            audience "nautalid.cluster"
            master_key_hex "{hex}"
            scope "admin:all"
        }}"#
            )
        });
        format!(
            r#"
    cluster {{
        node_id {}
        shards {}{leader}{control_kwt}
    }}"#,
            topology.node_id, topology.shards
        )
    } else {
        String::new()
    };

    format!(
        r#"preset "{HOST_DATA_PRESET}" {{
    consistency "strong"
    replication {}
    shards {}
    indexes primary="bplus" secondary="bplus"
    query "{}"
    durability "wal"
    transport zeromq bind="{bind}" pattern="router-dealer"{tls_block}
    route "storage" handler="storage"
    route "replicate" handler="replication"
    route "control" handler="control"
    replicate_auth {{
        master_key_hex "{replicate_hex}"
    }}{cluster_block}
}}
"#,
        topology.replication, topology.shards, topology.query,
    )
}

pub fn tls_block_from_paths(
    cert: &std::path::Path,
    key: &std::path::Path,
    ca: &std::path::Path,
) -> String {
    format!(
        r#" {{
        tls {{
            cert_file "{}"
            key_file "{}"
            ca_file "{}"
            client_auth #true
        }}
    }}"#,
        cert.display(),
        key.display(),
        ca.display(),
    )
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::kwt_replay::topology::{DeployMode, Topology};

    #[test]
    fn cluster_host_kdl_includes_cluster_block() {
        let topo = Topology {
            mode: DeployMode::Cluster,
            shards: 8,
            replication: 3,
            node_id: 1,
            query: "sql".into(),
        };
        let kdl = host_data_kdl(&topo, "tcp://0.0.0.0:5555", &"aa".repeat(64), "", None);
        assert!(kdl.contains("cluster {"));
        assert!(kdl.contains("shards 8"));
        assert!(kdl.contains(r#"route "control""#));
    }

    #[test]
    fn wire_client_matches_topology_shards() {
        let topo = Topology {
            mode: DeployMode::Cluster,
            shards: 16,
            replication: 3,
            node_id: 0,
            query: "kv".into(),
        };
        let kdl = wire_client_kdl(&topo, "bb".repeat(64).as_str());
        assert!(kdl.contains("shards 16"));
    }
}