use async_trait::async_trait; use crate::governed::command_trait::*; use crate::governed::session::{GovernedSession, Governed}; pub struct DeployCommand; #[async_trait] impl ShellCommand for DeployCommand { fn name(&self) -> &str { "deploy" } fn tier(&self) -> CommandTier { CommandTier::Engineer } fn required_scope(&self) -> RequiredScope { RequiredScope::Elevated { registry: "schematic".to_string(), verb: "deploy".to_string(), } } fn description(&self) -> &str { "Deploy a schematic version" } fn usage(&self) -> &str { "deploy [environment]" } async fn execute( &self, args: &[String], session: &mut GovernedSession, ) -> Result { if session.tenant_context().is_none() { return Err(CommandError::NoTenantContext); } if args.len() < 2 { return Err(CommandError::InvalidArgs( "Usage: deploy [environment]".to_string(), )); } let schematic_name = &args[0]; let version = &args[1]; let environment = args.get(2).map(|s| s.as_str()).unwrap_or("default"); let tenant = session.tenant_context().unwrap_or("*").to_string(); let lines = vec![ OutputLine::Text(format!( "Deploying: {} v{} -> {} (tenant: {})", schematic_name, version, environment, tenant )), OutputLine::Separator, OutputLine::Status { label: "Schematic".to_string(), value: schematic_name.clone(), color: OutputColor::Cyan, }, OutputLine::Status { label: "Version".to_string(), value: version.clone(), color: OutputColor::Cyan, }, OutputLine::Status { label: "Environment".to_string(), value: environment.to_string(), color: OutputColor::Default, }, OutputLine::Status { label: "Status".to_string(), value: "(stub: deployment not connected)".to_string(), color: OutputColor::Yellow, }, ]; Ok(CommandOutput { lines }) } }