upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/grasp-audit/src/bin/grasp-audit.rs
blob: b56a8e3dceb10e9152d96e622c9c89aaf0717602 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//! GRASP Audit CLI Tool

use clap::{Parser, Subcommand};
use grasp_audit::*;

#[derive(Parser)]
#[command(name = "grasp-audit")]
#[command(about = "GRASP audit and compliance testing tool", long_about = None)]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand)]
enum Commands {
    /// Run audit tests against a server
    Audit {
        /// Relay URL (e.g., ws://localhost:7000)
        #[arg(short, long)]
        relay: String,

        /// Mode: ci or production
        #[arg(short, long, default_value = "ci")]
        mode: String,

        /// Spec to test (nip01-smoke, all)
        #[arg(short, long, default_value = "nip01-smoke")]
        spec: String,
    },
}

#[tokio::main]
async fn main() -> Result<()> {
    // Initialize logging
    tracing_subscriber::fmt()
        .with_env_filter(
            tracing_subscriber::EnvFilter::from_default_env()
                .add_directive(tracing::Level::INFO.into()),
        )
        .init();

    let cli = Cli::parse();

    match cli.command {
        Commands::Audit { relay, mode, spec } => {
            let config = match mode.as_str() {
                "ci" => AuditConfig::ci(),
                "production" => AuditConfig::production(),
                _ => return Err(anyhow!("Invalid mode: {}. Use 'ci' or 'production'", mode)),
            };

            println!("🔍 GRASP Audit Tool");
            println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
            println!("Relay:   {}", relay);
            println!("Mode:    {}", mode);
            println!("Spec:    {}", spec);
            println!("Run ID:  {}", config.run_id);
            println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
            println!();

            println!("Connecting to relay...");
            let client = AuditClient::new(&relay, config)
                .await
                .map_err(|e| anyhow!("Failed to connect to relay: {}", e))?;

            if !client.is_connected().await {
                return Err(anyhow!("Could not establish connection to relay"));
            }

            println!("✓ Connected\n");

            let results = match spec.as_str() {
                "nip01-smoke" => {
                    println!("Running NIP-01 smoke tests...\n");
                    specs::Nip01SmokeTests::run_all(&client).await
                }
                "all" => {
                    println!("Running all tests...\n");
                    specs::Nip01SmokeTests::run_all(&client).await
                }
                _ => {
                    return Err(anyhow!(
                        "Unknown spec: {}. Use 'nip01-smoke' or 'all'",
                        spec
                    ))
                }
            };

            results.print_report();

            if !results.all_passed() {
                println!("❌ Some tests failed");
                std::process::exit(1);
            } else {
                println!("✅ All tests passed!");
            }
        }
    }

    Ok(())
}