mrapids 0.1.31

Your OpenAPI, but executable
Documentation
# Validation Opt-In Design

## Philosophy: Fast by Default, Safe When Needed

### Default Behavior (Fast Path)

```bash
# No validation - Maximum speed
mrapids run get-user --id 123        # ~70ms
mrapids test get-user --params '{}'  # ~80ms
mrapids-agent start                   # Validates once at startup
```

### Opt-In Validation (Safe Path)

```bash
# User explicitly requests validation
mrapids run get-user --id 123 --validate     # ~370ms
mrapids test --all --validate                # ~400ms per test
mrapids-agent start --validate-always         # Validates every request
```

## Implementation Pattern

### 1. Add Optional Flag to Commands

```rust
// In cli/mod.rs
#[derive(Parser)]
pub struct RunCommand {
    // ... existing fields ...
    
    /// Validate spec before execution (slower but safer)
    #[arg(long, default_value = "false")]
    pub validate: bool,
    
    /// Validation level when --validate is used
    #[arg(long, value_enum, default_value = "quick")]
    pub validate_level: ValidationLevel,
}

#[derive(ValueEnum, Clone, Copy)]
pub enum ValidationLevel {
    Quick,    // ~50ms - Structure only
    Standard, // ~200ms - OAS compliance  
    Full,     // ~500ms - All rules
}
```

### 2. Conditional Validation Logic

```rust
// In run command implementation
pub async fn execute_run_command(cmd: RunCommand) -> Result<()> {
    let spec = load_spec(&cmd.spec)?;
    
    // Only validate if explicitly requested
    if cmd.validate {
        let start = Instant::now();
        println!("🔍 Validating specification (--validate flag)...");
        
        match cmd.validate_level {
            ValidationLevel::Quick => quick_validate(&spec)?,
            ValidationLevel::Standard => standard_validate(&spec).await?,
            ValidationLevel::Full => full_validate(&spec).await?,
        }
        
        println!("✅ Validated in {}ms", start.elapsed().as_millis());
    }
    
    // Continue with normal execution
    execute_operation(&spec, &cmd).await
}
```

### 3. Environment Variable Override

```bash
# For users who always want validation
export MRAPIDS_ALWAYS_VALIDATE=true
export MRAPIDS_VALIDATE_LEVEL=standard

# Now all commands validate by default
mrapids run get-user  # Will validate
```

```rust
pub fn should_validate(cmd_flag: bool) -> bool {
    // Command flag takes precedence
    if cmd_flag {
        return true;
    }
    
    // Check environment variable
    std::env::var("MRAPIDS_ALWAYS_VALIDATE")
        .map(|v| v.to_lowercase() == "true")
        .unwrap_or(false)
}
```

### 4. Configuration File Support

```yaml
# .mrapids/config.yaml
validation:
  init: true        # Always validate on init
  analyze: true     # Always validate on analyze
  generate: true    # Always validate on generate
  run: false        # Never validate on run (unless --validate)
  test: false       # Never validate on test
  default_level: standard
```

### 5. Smart Caching for Repeated Runs

```rust
use std::sync::OnceLock;

static VALIDATION_CACHE: OnceLock<Mutex<ValidationCache>> = OnceLock::new();

pub struct ValidationCache {
    entries: HashMap<PathBuf, CachedValidation>,
}

struct CachedValidation {
    file_hash: String,
    validated_at: Instant,
    result: ValidationResult,
}

impl ValidationCache {
    pub fn validate_with_cache(
        &mut self,
        spec_path: &Path,
        level: ValidationLevel,
    ) -> Result<ValidationResult> {
        let current_hash = calculate_file_hash(spec_path)?;
        
        // Check cache
        if let Some(cached) = self.entries.get(spec_path) {
            if cached.file_hash == current_hash &&
               cached.validated_at.elapsed() < Duration::from_secs(3600) {
                println!("⚡ Using cached validation result");
                return Ok(cached.result.clone());
            }
        }
        
        // Validate and cache
        let result = perform_validation(spec_path, level)?;
        self.entries.insert(spec_path.to_owned(), CachedValidation {
            file_hash: current_hash,
            validated_at: Instant::now(),
            result: result.clone(),
        });
        
        Ok(result)
    }
}
```

## Use Case Examples

### Development Workflow
```bash
# During development - validate after changes
$ vim api.yaml
$ mrapids validate spec api.yaml     # Full validation
$ mrapids run get-user --id 123      # Fast execution

# Before commit - validate everything
$ mrapids validate spec api.yaml --level full
$ git commit -m "Updated API spec"
```

### Production Deployment
```bash
# CI/CD Pipeline - Always validate
- name: Validate API Spec
  run: mrapids validate spec api.yaml --level full

# Production runtime - Skip validation for speed
$ mrapids run get-user --id $USER_ID  # No validation
```

### Debugging Issues
```bash
# Something's not working? Add validation
$ mrapids run create-order --data @order.json
Error: 400 Bad Request

# Debug with validation
$ mrapids run create-order --data @order.json --validate --validate-level full
🔍 Validating specification...
❌ Validation error: Operation 'create-order' missing required 'security' field
```

### Agent Configuration
```bash
# Development agent - validate everything
mrapids-agent start --validate-always --validate-level full

# Production agent - validate once
mrapids-agent start  # Only validates at startup

# Debug mode - selective validation
mrapids-agent start --validate-operations "create-*,update-*"
```

## Best Practices

### 1. Document the Performance Trade-off
```bash
$ mrapids run --help
OPTIONS:
  --validate    Validate spec before execution (~300ms overhead)
```

### 2. Show Validation Time
```bash
$ mrapids run get-user --validate
🔍 Validating specification...
✅ Validated in 287ms
🚀 Executing request...
```

### 3. Provide Shortcuts
```bash
# Alias for validated runs
alias mrapids-safe='mrapids --validate'

# Now users can choose
mrapids run get-user         # Fast
mrapids-safe run get-user    # Validated
```

## Summary

This opt-in approach provides:
- **Fast by default**: No performance penalty unless requested
- 🛡️ **Safe when needed**: Full validation available on demand
- 🎯 **User control**: Explicit flags and configuration options
- 📊 **Visibility**: Clear feedback about validation overhead
- 🔧 **Flexibility**: Different validation levels for different needs

The key principle: **Don't force users to pay for validation they don't need, but make it easy when they do!**