coreason-urn-authority 0.45.1

Epistemic Ledger & OCI Trust Anchor for CoReason URNs.
Documentation
// Copyright (c) 2026 CoReason, Inc.
// All rights reserved.

use serde_json::Value;
use sha2::{Digest, Sha256};
use std::fs;
use std::path::Path;

pub fn get_ram_gb() -> f64 {
    use sysinfo::System;
    let sys = System::new_all();
    sys.total_memory() as f64 / 1024.0 / 1024.0 / 1024.0
}

fn which(name: &str) -> bool {
    if let Ok(path) = std::env::var("PATH") {
        for p in std::env::split_paths(&path) {
            let exe_path = p.join(name);
            #[cfg(target_os = "windows")]
            {
                if exe_path.with_extension("exe").exists() || exe_path.exists() {
                    return true;
                }
            }
            #[cfg(not(target_os = "windows"))]
            {
                if exe_path.exists() {
                    return true;
                }
            }
        }
    }
    false
}

pub fn detect_gpu() -> bool {
    which("nvidia-smi")
}

pub fn calculate_tenant_cid(kyc_json: &str) -> Result<(String, String), String> {
    let val: Value = serde_json::from_str(kyc_json).map_err(|e| e.to_string())?;
    let map = val
        .as_object()
        .ok_or_else(|| "KYC must be a JSON object".to_string())?;
    let canonical = serde_json::to_string(map).map_err(|e| e.to_string())?;

    let mut hasher = Sha256::new();
    hasher.update(canonical.as_bytes());
    let hash = format!("{:x}", hasher.finalize());
    Ok((canonical, hash))
}

pub fn generate_egress_rules(
    target_path: &Path,
    selected_categories: &[String],
) -> Result<(), String> {
    let mut category_domains = std::collections::HashMap::new();
    category_domains.insert(
        "registries",
        vec![
            "ghcr.io",
            "pkg-containers.githubusercontent.com",
            "registry-1.docker.io",
            "auth.docker.io",
            "index.docker.io",
            "production.cloudflare.docker.com",
        ],
    );
    category_domains.insert(
        "huggingface",
        vec![
            "huggingface.co",
            "cdn-lfs.hf.co",
            "cdn-lfs-us-1.hf.co",
            "cdn-lfs-eu-1.hf.co",
            "cas-bridge.xethub.hf.co",
        ],
    );
    category_domains.insert(
        "oidc",
        vec!["login.microsoftonline.com", "accounts.google.com"],
    );
    category_domains.insert(
        "cognitive",
        vec![
            "api.openai.com",
            "api.anthropic.com",
            "us-central1-aiplatform.googleapis.com",
            "bedrock.us-east-1.amazonaws.com",
            "bedrock.us-west-2.amazonaws.com",
        ],
    );

    let mut allowed_domains = Vec::new();
    for cat in selected_categories {
        if let Some(domains) = category_domains.get(cat.as_str()) {
            allowed_domains.extend(domains.iter().map(|d| d.to_string()));
        }
    }

    // 1. Write plain rules file for firewall admin
    let rules_file = target_path.join("egress-whitelist.rules");
    let mut rules_content = String::from(
        "# CoReason Enterprise Outbound Firewall Rules (FQDN Whitelist)\n\
         # Hand this file to your network/firewall security administrator.\n\n",
    );
    for domain in &allowed_domains {
        rules_content.push_str(domain);
        rules_content.push('\n');
    }
    fs::write(&rules_file, rules_content).map_err(|e| e.to_string())?;

    // 2. Write Squid config file for local enforcement container
    let squid_file = target_path.join("egress-whitelist.squid.conf");
    let mut squid_lines = vec![
        "# Squid Proxy Whitelist Configuration for CoReason Sandbox Egress".to_string(),
        "acl SSL_ports port 443".to_string(),
        "acl Safe_ports port 80".to_string(),
        "acl Safe_ports port 443".to_string(),
        "acl CONNECT method CONNECT".to_string(),
        "".to_string(),
        "http_access deny !Safe_ports".to_string(),
        "http_access deny CONNECT !SSL_ports".to_string(),
        "http_access allow localhost manager".to_string(),
        "http_access deny manager".to_string(),
        "".to_string(),
        "# Allow local traffic within docker bridge network".to_string(),
        "acl localnet src 10.0.0.0/8".to_string(),
        "acl localnet src 172.16.0.0/12".to_string(),
        "acl localnet src 192.168.0.0/16".to_string(),
        "http_access allow localhost".to_string(),
        "http_access allow localnet".to_string(),
        "".to_string(),
        "# Whitelisted destination domains".to_string(),
    ];

    for domain in &allowed_domains {
        squid_lines.push(format!("acl allowed_domains dstdomain {}", domain));
        if !domain.starts_with('.') && domain != "pkg-containers.githubusercontent.com" {
            squid_lines.push(format!("acl allowed_domains dstdomain .{}", domain));
        }
    }

    squid_lines.push("http_access allow allowed_domains".to_string());
    squid_lines.push("http_access deny all".to_string());
    squid_lines.push("http_port 3128".to_string());
    squid_lines.push("coredump_dir /var/spool/squid".to_string());
    squid_lines.push("refresh_pattern ^ftp:           1440    20%     10080".to_string());
    squid_lines.push("refresh_pattern ^gopher:        1440    0%      1440".to_string());
    squid_lines.push("refresh_pattern -i (/cgi-bin/|\\?) 0     0%      0".to_string());
    squid_lines.push("refresh_pattern .               0       20%     4320".to_string());
    squid_lines.push("".to_string());

    fs::write(&squid_file, squid_lines.join("\n")).map_err(|e| e.to_string())?;

    Ok(())
}