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:
52
products/06-runbook-automation/agent/src/parser.rs
Normal file
52
products/06-runbook-automation/agent/src/parser.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Parsed runbook step.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct RunbookStep {
|
||||
pub index: usize,
|
||||
pub description: String,
|
||||
pub command: String,
|
||||
pub timeout_seconds: u64,
|
||||
pub on_failure: FailureAction,
|
||||
pub condition: Option<String>, // Optional: only run if previous step output matches
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum FailureAction {
|
||||
Abort,
|
||||
Continue,
|
||||
Retry { max_attempts: u32 },
|
||||
}
|
||||
|
||||
/// Parsed runbook.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Runbook {
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub version: String,
|
||||
pub steps: Vec<RunbookStep>,
|
||||
}
|
||||
|
||||
/// Parse a YAML runbook into structured steps.
|
||||
pub fn parse_yaml(content: &str) -> anyhow::Result<Runbook> {
|
||||
// TODO: Full YAML parsing with serde_yaml
|
||||
// For now, return a placeholder
|
||||
Ok(Runbook {
|
||||
name: "placeholder".into(),
|
||||
description: "TODO: implement YAML parser".into(),
|
||||
version: "0.1.0".into(),
|
||||
steps: vec![],
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_parse_empty_returns_placeholder() {
|
||||
let result = parse_yaml("").unwrap();
|
||||
assert_eq!(result.name, "placeholder");
|
||||
assert!(result.steps.is_empty());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user