alpine-protocol-sdk 0.2.4

High-level SDK on top of the ALPINE protocol layer.
Documentation
use std::env;
use std::path::Path;

use crate::network_health::NetworkHealthReport;
use crate::trust::TrustConfig;

#[derive(Debug, Clone)]
pub struct QuickstartItem {
    pub name: String,
    pub ok: bool,
    pub detail: String,
}

#[derive(Debug, Clone)]
pub struct QuickstartChecklist {
    pub items: Vec<QuickstartItem>,
}

impl QuickstartChecklist {
    pub fn run(config: Option<&TrustConfig>) -> Self {
        let mut items = Vec::new();

        let attesters_url = env::var("ALPINE_ATTESTERS_URL").ok();
        let root_key = env::var("ALPINE_ROOT_PUBKEY_B64").ok();
        items.push(QuickstartItem {
            name: "ALPINE_ATTESTERS_URL".to_string(),
            ok: attesters_url.is_some(),
            detail: attesters_url
                .map(|_| "set".to_string())
                .unwrap_or_else(|| "missing".to_string()),
        });
        items.push(QuickstartItem {
            name: "ALPINE_ROOT_PUBKEY_B64".to_string(),
            ok: root_key.is_some(),
            detail: root_key
                .map(|_| "set".to_string())
                .unwrap_or_else(|| "missing".to_string()),
        });

        if let Some(cfg) = config {
            let path = if let Some(override_path) = &cfg.override_path {
                override_path.as_path()
            } else {
                cfg.cache_path.as_path()
            };
            let exists = Path::new(path).exists();
            items.push(QuickstartItem {
                name: "trust_bundle".to_string(),
                ok: exists,
                detail: if exists {
                    format!("found at {}", path.display())
                } else {
                    format!("missing at {}", path.display())
                },
            });
        }

        let health = NetworkHealthReport::probe();
        let detail = if health.ok() {
            "udp ready".to_string()
        } else {
            let mut parts = Vec::new();
            if !health.udp_bind_ok {
                parts.push("udp bind failed");
            }
            if !health.broadcast_ok {
                parts.push("broadcast blocked");
            }
            if !health.multicast_ok {
                parts.push("multicast blocked");
            }
            if parts.is_empty() {
                parts.push("udp health unknown");
            }
            parts.join(", ")
        };
        items.push(QuickstartItem {
            name: "udp reachability".to_string(),
            ok: health.ok(),
            detail,
        });

        Self { items }
    }

    pub fn ok(&self) -> bool {
        self.items.iter().all(|item| item.ok)
    }

    pub fn summary(&self) -> String {
        let mut lines = Vec::new();
        for item in &self.items {
            let status = if item.ok { "ok" } else { "missing" };
            lines.push(format!("{}: {} ({})", item.name, status, item.detail));
        }
        lines.join("\n")
    }
}