@@ -1699,6 +1699,131 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
16991699 }
17001700 }
17011701 }
1702+ "audit" => {
1703+ use crate :: utils:: audit:: AuditCoordinator ;
1704+ use std:: fs;
1705+ use std:: path:: Path ;
1706+
1707+ println ! ( "🔍 OSVM Security Audit" ) ;
1708+ println ! ( "======================" ) ;
1709+
1710+ let output_dir = matches. get_one :: < String > ( "output" ) . unwrap ( ) ;
1711+ let format = matches. get_one :: < String > ( "format" ) . unwrap ( ) ;
1712+ let verbose = matches. get_count ( "verbose" ) ;
1713+ let test_mode = matches. get_flag ( "test" ) ;
1714+
1715+ if verbose > 0 {
1716+ println ! ( "📁 Output directory: {}" , output_dir) ;
1717+ println ! ( "📄 Format: {}" , format) ;
1718+ if test_mode {
1719+ println ! ( "🧪 Test mode: generating sample audit report" ) ;
1720+ }
1721+ }
1722+
1723+ // Create output directory
1724+ if let Err ( e) = fs:: create_dir_all ( output_dir) {
1725+ eprintln ! ( "❌ Failed to create output directory: {}" , e) ;
1726+ exit ( 1 ) ;
1727+ }
1728+
1729+ // Initialize audit coordinator
1730+ let audit_coordinator = AuditCoordinator :: new ( ) ;
1731+
1732+ // Generate audit report
1733+ let report = if test_mode {
1734+ println ! ( "🧪 Generating test audit report..." ) ;
1735+ audit_coordinator. create_test_audit_report ( )
1736+ } else {
1737+ // Run security audit
1738+ match audit_coordinator. run_security_audit ( ) . await {
1739+ Ok ( report) => report,
1740+ Err ( e) => {
1741+ eprintln ! ( "❌ Failed to run security audit: {}" , e) ;
1742+ exit ( 1 ) ;
1743+ }
1744+ }
1745+ } ;
1746+
1747+ println ! ( "✅ Security audit completed successfully" ) ;
1748+ println ! ( "📊 Security Score: {:.1}/100" , report. summary. security_score) ;
1749+ println ! ( "🔍 Total Findings: {}" , report. summary. total_findings) ;
1750+
1751+ if report. summary . critical_findings > 0 {
1752+ println ! ( "🔴 Critical: {}" , report. summary. critical_findings) ;
1753+ }
1754+ if report. summary . high_findings > 0 {
1755+ println ! ( "🟠 High: {}" , report. summary. high_findings) ;
1756+ }
1757+ if report. summary . medium_findings > 0 {
1758+ println ! ( "🟡 Medium: {}" , report. summary. medium_findings) ;
1759+ }
1760+ if report. summary . low_findings > 0 {
1761+ println ! ( "🔵 Low: {}" , report. summary. low_findings) ;
1762+ }
1763+
1764+ // Generate timestamp for unique filenames
1765+ let timestamp = chrono:: Utc :: now ( ) . format ( "%Y%m%d_%H%M%S" ) ;
1766+
1767+ // Generate outputs based on requested format
1768+ let typst_path = Path :: new ( output_dir) . join ( format ! ( "osvm_audit_report_{}.typ" , timestamp) ) ;
1769+ let pdf_path = Path :: new ( output_dir) . join ( format ! ( "osvm_audit_report_{}.pdf" , timestamp) ) ;
1770+
1771+ match format. as_str ( ) {
1772+ "typst" | "both" => {
1773+ if let Err ( e) = audit_coordinator. generate_typst_document ( & report, & typst_path) {
1774+ eprintln ! ( "❌ Failed to generate Typst document: {}" , e) ;
1775+ exit ( 1 ) ;
1776+ }
1777+ println ! ( "📄 Typst document generated: {}" , typst_path. display( ) ) ;
1778+
1779+ if format == "both" {
1780+ if let Err ( e) = audit_coordinator. compile_to_pdf ( & typst_path, & pdf_path) {
1781+ eprintln ! ( "❌ Failed to compile PDF: {}" , e) ;
1782+ eprintln ! ( " Typst document is available at: {}" , typst_path. display( ) ) ;
1783+ } else {
1784+ println ! ( "📋 PDF report generated: {}" , pdf_path. display( ) ) ;
1785+ }
1786+ }
1787+ }
1788+ "pdf" => {
1789+ // Generate Typst document first (temporary)
1790+ if let Err ( e) = audit_coordinator. generate_typst_document ( & report, & typst_path) {
1791+ eprintln ! ( "❌ Failed to generate Typst document: {}" , e) ;
1792+ exit ( 1 ) ;
1793+ }
1794+
1795+ if let Err ( e) = audit_coordinator. compile_to_pdf ( & typst_path, & pdf_path) {
1796+ eprintln ! ( "❌ Failed to compile PDF: {}" , e) ;
1797+ exit ( 1 ) ;
1798+ }
1799+
1800+ // Remove temporary Typst file
1801+ let _ = fs:: remove_file ( & typst_path) ;
1802+ println ! ( "📋 PDF report generated: {}" , pdf_path. display( ) ) ;
1803+ }
1804+ _ => {
1805+ eprintln ! ( "❌ Invalid format specified" ) ;
1806+ exit ( 1 ) ;
1807+ }
1808+ }
1809+
1810+ if verbose > 0 {
1811+ println ! ( "\n 📋 Audit Summary:" ) ;
1812+ println ! ( " Compliance Level: {}" , report. summary. compliance_level) ;
1813+ println ! ( " System: {} {}" , report. system_info. os_info, report. system_info. architecture) ;
1814+ println ! ( " Rust Version: {}" , report. system_info. rust_version) ;
1815+ if let Some ( ref solana_version) = report. system_info . solana_version {
1816+ println ! ( " Solana Version: {}" , solana_version) ;
1817+ }
1818+ }
1819+
1820+ println ! ( "\n 💡 To view the full report, open the generated file." ) ;
1821+
1822+ if !test_mode && ( report. summary . critical_findings > 0 || report. summary . high_findings > 0 ) {
1823+ println ! ( "⚠️ Critical or high-severity findings detected. Please review and address them promptly." ) ;
1824+ exit ( 1 ) ;
1825+ }
1826+ }
17021827 "new_feature_command" => {
17031828 println ! ( "Expected output for new feature" ) ;
17041829 }
0 commit comments