mrapids 0.1.31

Your OpenAPI, but executable
Documentation
# OpenAPI Spec Validation Architecture

## Where Do OAS Specs Come From?

### 1. User-Provided Specs (Not Part of Binary)

The OAS files to validate are **NOT part of the MicroRapid binary**. They come from:

```bash
# From URL
mrapids init my-api --from-url https://api.example.com/openapi.yaml

# From local file
mrapids init my-api --from-file ./specs/api.yaml

# Already in project
mrapids validate spec ./specs/api.yaml
```

### 2. Validation Rules (Part of Binary/Package)

What IS included:

```
mrapids binary/
├── mrapids              # Main binary
├── .spectral.yaml       # Default ruleset (bundled)
└── rules/               # Security rules (bundled)
    ├── oas2-rules.yaml  # OAS 2.0 specific
    ├── oas3-rules.yaml  # OAS 3.0.x specific
    └── oas31-rules.yaml # OAS 3.1 specific
```

## Version-Specific Validation

### Detection and Routing

```rust
pub fn validate_spec(content: &str) -> Result<ValidationReport> {
    // Step 1: Detect version from the spec itself
    let version = detect_version(content)?;
    
    // Step 2: Route to appropriate validator
    match version {
        SpecVersion::Swagger2_0 => validate_oas2(content),
        SpecVersion::OpenAPI3_0(_) => validate_oas3(content),
        SpecVersion::OpenAPI3_1(_) => validate_oas31(content),
    }
}

fn detect_version(content: &str) -> Result<SpecVersion> {
    let value: Value = serde_json::from_str(content)
        .or_else(|_| serde_yaml::from_str(content))?;
    
    // Check for Swagger 2.0
    if let Some(v) = value.get("swagger") {
        if v == "2.0" {
            return Ok(SpecVersion::Swagger2_0);
        }
    }
    
    // Check for OpenAPI 3.x
    if let Some(v) = value.get("openapi").and_then(|v| v.as_str()) {
        if v.starts_with("3.0.") {
            return Ok(SpecVersion::OpenAPI3_0(v.to_string()));
        }
        if v.starts_with("3.1.") {
            return Ok(SpecVersion::OpenAPI3_1(v.to_string()));
        }
    }
    
    Err(anyhow!("Unknown spec version"))
}
```

## Bundling Strategy

### Option 1: Embedded Rules (Recommended)
```rust
// Embed validation rules in binary at compile time
const OAS2_RULES: &str = include_str!("../rules/oas2-rules.yaml");
const OAS3_RULES: &str = include_str!("../rules/oas3-rules.yaml");
const OAS31_RULES: &str = include_str!("../rules/oas31-rules.yaml");

pub fn get_rules_for_version(version: &SpecVersion) -> &'static str {
    match version {
        SpecVersion::Swagger2_0 => OAS2_RULES,
        SpecVersion::OpenAPI3_0(_) => OAS3_RULES,
        SpecVersion::OpenAPI3_1(_) => OAS31_RULES,
    }
}
```

### Option 2: External Validator (Alternative)
```toml
# Cargo.toml
[dependencies]
# Use pre-built validators
openapi-validator = "0.5"  # Rust crate
spectral-core = "6.0"      # If available as lib

# Or shell out to installed tools
```

## Version-Specific Rules

### OAS 2.0 (Swagger) Rules
```yaml
# rules/oas2-rules.yaml
extends: [[spectral:swagger2, all]]

rules:
  swagger-version:
    description: Must be Swagger 2.0
    given: $.swagger
    then:
      const: "2.0"
      
  basePath-required:
    description: Swagger 2.0 requires basePath
    given: $
    then:
      field: basePath
      function: truthy
      
  definitions-valid:
    description: Definitions must be objects
    given: $.definitions[*]
    then:
      type: object
```

### OAS 3.0.x Rules
```yaml
# rules/oas3-rules.yaml
extends: [[spectral:oas3_0, all]]

rules:
  openapi-version:
    description: Must be OpenAPI 3.0.x
    given: $.openapi
    then:
      function: pattern
      functionOptions:
        match: "^3\\.0\\.[0-3]$"
        
  servers-required:
    description: OpenAPI 3.0 requires servers
    given: $
    then:
      field: servers
      function: truthy
```

### OAS 3.1 Rules
```yaml
# rules/oas31-rules.yaml
extends: [[spectral:oas3_1, all]]

rules:
  json-schema-compatibility:
    description: Use valid JSON Schema 2020-12
    given: $..schema
    then:
      function: jsonSchema202012Valid
      
  webhooks-valid:
    description: Webhooks must follow operation format
    given: $.webhooks[*][*]
    then:
      function: operation-valid
```

## Binary Distribution Options

### 1. Single Binary with Embedded Rules
```rust
// Everything in one binary (~10MB extra)
cargo build --release --features embedded-rules
```

**Pros**: 
- Simple distribution
- Works offline
- No external dependencies

**Cons**:
- Larger binary size
- Rules updates require new release

### 2. Binary + Runtime Download
```rust
// Minimal binary, download rules on first use
pub async fn ensure_rules_available() -> Result<PathBuf> {
    let rules_dir = dirs::config_dir()
        .unwrap()
        .join("mrapids")
        .join("rules");
    
    if !rules_dir.exists() {
        download_rules(&rules_dir).await?;
    }
    
    Ok(rules_dir)
}
```

**Pros**:
- Smaller binary
- Rules can be updated independently

**Cons**:
- Requires internet on first run
- More complex deployment

### 3. Binary + Bundled Spectral
```dockerfile
# Multi-platform distribution
FROM node:slim as spectral
RUN npm install -g @stoplight/spectral-cli

FROM rust:latest as builder
COPY . .
RUN cargo build --release

FROM debian:slim
COPY --from=builder /target/release/mrapids /usr/local/bin/
COPY --from=spectral /usr/local/bin/spectral /usr/local/bin/
```

## Validation Flow Example

```mermaid
graph TD
    A[User's API Spec] --> B{Detect Version}
    B -->|swagger: 2.0| C[Load OAS 2.0 Rules]
    B -->|openapi: 3.0.x| D[Load OAS 3.0 Rules]
    B -->|openapi: 3.1.x| E[Load OAS 3.1 Rules]
    
    C --> F[Validate with Spectral]
    D --> F
    E --> F
    
    F --> G[Validation Report]
    
    style A fill:#f9f,stroke:#333,stroke-width:2px
    style G fill:#9f9,stroke:#333,stroke-width:2px
```

## Usage Examples

### Validating Different Versions
```bash
# OAS 2.0 (Swagger)
$ mrapids validate spec swagger2-api.yaml
🔍 Detected: Swagger 2.0
✅ Validation passed with Swagger 2.0 rules

# OAS 3.0.2
$ mrapids validate spec openapi3-api.yaml  
🔍 Detected: OpenAPI 3.0.2
✅ Validation passed with OpenAPI 3.0.x rules

# OAS 3.1.0
$ mrapids validate spec openapi31-api.yaml
🔍 Detected: OpenAPI 3.1.0
✅ Validation passed with OpenAPI 3.1 rules
```

## Implementation Priority

1. **Phase 1**: Embed basic rules in binary
2. **Phase 2**: Add Spectral as optional dependency
3. **Phase 3**: Support custom rule loading
4. **Phase 4**: Cloud-based rule updates

## Summary

- **OAS specs**: Come from users, not bundled
- **Validation rules**: Bundled with binary or downloaded
- **Version detection**: Automatic from spec content
- **Distribution**: Single binary with embedded rules (recommended)