Scaffold dd0c/run: Rust agent (classifier, executor, audit) + TypeScript SaaS
- Rust agent: clap CLI, command classifier (read-only/modifying/destructive), executor with approval gates, audit log entries - Classifier: pattern-based safety classification for shell, AWS, kubectl, terraform/tofu commands - 6 Rust tests: read-only, destructive, modifying, empty, terraform apply, tofu destroy - SaaS backend: Fastify server, runbook CRUD API, approval API, Slack interactive handler - Slack integration: signature verification, block_actions for approve/reject buttons - PostgreSQL schema with RLS: runbooks, executions, audit_entries (append-only), agents - Dual Dockerfiles: Rust multi-stage (agent), Node multi-stage (SaaS) - Gitea Actions CI: Rust test+clippy, Node typecheck+test - Fly.io config for SaaS
This commit is contained in:
85
products/06-runbook-automation/agent/src/main.rs
Normal file
85
products/06-runbook-automation/agent/src/main.rs
Normal file
@@ -0,0 +1,85 @@
|
||||
use clap::{Parser, Subcommand};
|
||||
use tracing::info;
|
||||
|
||||
mod parser;
|
||||
mod classifier;
|
||||
mod executor;
|
||||
mod audit;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(name = "dd0c-run", version, about = "Runbook automation agent")]
|
||||
struct Cli {
|
||||
#[command(subcommand)]
|
||||
command: Commands,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Commands {
|
||||
/// Execute a runbook
|
||||
Run {
|
||||
/// Path to runbook file (YAML/Markdown)
|
||||
#[arg(short, long)]
|
||||
runbook: String,
|
||||
|
||||
/// dd0c SaaS endpoint
|
||||
#[arg(long, default_value = "https://api.dd0c.dev")]
|
||||
endpoint: String,
|
||||
|
||||
/// API key
|
||||
#[arg(long, env = "DD0C_API_KEY")]
|
||||
api_key: String,
|
||||
|
||||
/// Dry run (classify only, don't execute)
|
||||
#[arg(long)]
|
||||
dry_run: bool,
|
||||
},
|
||||
/// Classify a single command
|
||||
Classify {
|
||||
/// Command to classify
|
||||
command: String,
|
||||
},
|
||||
/// Verify agent binary signature
|
||||
Verify {
|
||||
/// Path to signature file
|
||||
#[arg(short, long)]
|
||||
sig: String,
|
||||
/// Path to public key
|
||||
#[arg(short, long)]
|
||||
pubkey: String,
|
||||
},
|
||||
/// Print version
|
||||
Version,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(
|
||||
tracing_subscriber::EnvFilter::try_from_default_env()
|
||||
.unwrap_or_else(|_| "dd0c_run=info".into()),
|
||||
)
|
||||
.json()
|
||||
.init();
|
||||
|
||||
let cli = Cli::parse();
|
||||
|
||||
match cli.command {
|
||||
Commands::Run { runbook, endpoint, api_key, dry_run } => {
|
||||
info!(runbook = %runbook, dry_run, "Starting runbook execution");
|
||||
// TODO: Parse runbook → classify steps → execute with approval gates
|
||||
}
|
||||
Commands::Classify { command } => {
|
||||
let result = classifier::classify(&command);
|
||||
println!("{}", serde_json::to_string_pretty(&result)?);
|
||||
}
|
||||
Commands::Verify { sig, pubkey } => {
|
||||
// TODO: Ed25519 signature verification
|
||||
println!("Signature verification not yet implemented");
|
||||
}
|
||||
Commands::Version => {
|
||||
println!("dd0c/run agent v{}", env!("CARGO_PKG_VERSION"));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user