# Validation Binary Packaging Strategy
## What Gets Bundled vs What Doesn't
### 📦 Included in MicroRapid Binary
```
mrapids (single binary ~15-20MB)
├── Core CLI functionality
├── Validation engine
├── Default validation rules (embedded)
│ ├── OAS 2.0 rules
│ ├── OAS 3.0.x rules
│ └── OAS 3.1 rules
└── Security rules (embedded)
```
### 📄 NOT Included (User Provides)
```
User's project/
├── specs/
│ ├── api.yaml # User's OpenAPI spec
│ ├── petstore.json # Another spec
│ └── internal-api.yaml # Yet another spec
├── mrapids.yaml # Project config
└── requests/ # Generated by mrapids
```
## Embedding Validation Rules
### Build-Time Embedding (Recommended)
```rust
// src/validation/rules.rs
// Rules are compiled into the binary
pub mod embedded_rules {
pub const OAS2_RULES: &str = include_str!("../../rules/oas2.spectral.yaml");
pub const OAS3_RULES: &str = include_str!("../../rules/oas3.spectral.yaml");
pub const OAS31_RULES: &str = include_str!("../../rules/oas31.spectral.yaml");
pub const SECURITY_RULES: &str = include_str!("../../rules/security.spectral.yaml");
}
// At runtime, write to temp file for Spectral
pub fn get_ruleset_for_version(version: &SpecVersion) -> Result<PathBuf> {
let rules_content = match version {
SpecVersion::Swagger2_0 => embedded_rules::OAS2_RULES,
SpecVersion::OpenAPI3_0(_) => embedded_rules::OAS3_RULES,
SpecVersion::OpenAPI3_1(_) => embedded_rules::OAS31_RULES,
};
// Write to temp file
let temp_dir = std::env::temp_dir();
let rules_file = temp_dir.join(format!("mrapids-rules-{}.yaml", version));
std::fs::write(&rules_file, rules_content)?;
Ok(rules_file)
}
```
### Binary Size Impact
```
Base mrapids binary: ~12MB
+ Embedded rules: ~200KB
+ Validation logic: ~1MB
+ Compressed: ~8MB (with UPX)
---------------------------------
Total distributed size: ~15-20MB
```
## Distribution Strategies
### Option 1: Pure Rust with Embedded Rules ✅ (Recommended)
```toml
# Cargo.toml
[dependencies]
# Use a Rust OpenAPI validator
openapi-struct = "0.5"
jsonschema = "0.17"
[build-dependencies]
include_dir = "0.7"
# Build script embeds rules at compile time
```
**Pros:**
- Single binary, no dependencies
- Works offline
- Fast startup
- Easy distribution
**Cons:**
- Can't use Spectral directly
- Need to implement rule engine
### Option 2: Bundle Spectral Binary
```bash
# Release package structure
mrapids-v1.0.0-darwin-arm64.tar.gz
├── mrapids # Main CLI
├── bin/
│ └── spectral # Spectral binary
└── rules/ # Rule files
```
**Distribution script:**
```bash
#!/bin/bash
# build-release.sh
# Build mrapids
cargo build --release
# Download platform-specific Spectral
wget https://github.com/stoplightio/spectral/releases/download/v6.11.0/spectral-darwin-x64
# Package together
tar -czf mrapids-darwin-x64.tar.gz \
target/release/mrapids \
spectral-darwin-x64 \
rules/
```
### Option 3: Lazy Download (Not Recommended)
```rust
// Download Spectral on first use
pub async fn ensure_spectral_installed() -> Result<PathBuf> {
let spectral_path = dirs::home_dir()
.unwrap()
.join(".mrapids")
.join("bin")
.join("spectral");
if !spectral_path.exists() {
println!("📥 Downloading Spectral validator...");
download_spectral(&spectral_path).await?;
}
Ok(spectral_path)
}
```
## Platform-Specific Builds
### GitHub Release Structure
```
mrapids/releases/v1.0.0/
├── mrapids-darwin-x64.tar.gz # macOS Intel
├── mrapids-darwin-arm64.tar.gz # macOS Apple Silicon
├── mrapids-linux-x64.tar.gz # Linux x64
├── mrapids-linux-arm64.tar.gz # Linux ARM
└── mrapids-windows-x64.zip # Windows
```
### Build Matrix
```yaml
# .github/workflows/release.yml
strategy:
matrix:
include:
- os: macos-latest
target: x86_64-apple-darwin
- os: macos-latest
target: aarch64-apple-darwin
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
- os: windows-latest
target: x86_64-pc-windows-msvc
```
## Validation at Runtime
### How It Works
```rust
pub fn validate_command(spec_path: &Path) -> Result<()> {
// 1. Load user's spec (NOT bundled)
let spec_content = std::fs::read_to_string(spec_path)?;
// 2. Detect version from spec
let version = detect_oas_version(&spec_content)?;
println!("🔍 Detected: {}", version);
// 3. Get appropriate rules (bundled)
let rules = get_embedded_rules_for_version(&version);
// 4. Validate
let validator = Validator::with_rules(rules);
let results = validator.validate(&spec_content)?;
// 5. Report results
display_validation_results(results);
Ok(())
}
```
### Example Usage
```bash
# User provides their OpenAPI spec
$ ls
my-api.yaml # This is the user's spec, NOT bundled
# MicroRapid validates it using bundled rules
$ mrapids validate spec my-api.yaml
🔍 Reading spec: my-api.yaml
🔍 Detected: OpenAPI 3.0.3
📋 Applying OpenAPI 3.0.x validation rules (bundled)
✅ Validation passed!
# Different spec, different rules
$ mrapids validate spec legacy-swagger.json
🔍 Reading spec: legacy-swagger.json
🔍 Detected: Swagger 2.0
📋 Applying Swagger 2.0 validation rules (bundled)
⚠️ Warning: Missing basePath (required in Swagger 2.0)
```
## Storage Locations
### Where Rules Live
```
# Development
api-runtime/
├── rules/ # Source rules
│ ├── oas2.spectral.yaml
│ ├── oas3.spectral.yaml
│ └── oas31.spectral.yaml
# After compilation (embedded)
target/release/mrapids # All rules inside binary
# At runtime (temporary)
/tmp/mrapids-rules-{uuid}.yaml # Extracted for Spectral
```
### Where User Specs Live
```
# User's project (anywhere)
~/projects/my-api/
├── openapi.yaml # User's spec
├── swagger.json # Another spec
└── specs/
└── internal-api.yaml # More specs
```
## Summary
- **Validation rules**: Embedded in binary at compile time (~200KB)
- **OpenAPI specs**: Provided by users, never bundled
- **Distribution**: Single binary with everything needed
- **Version detection**: Automatic from spec content
- **Platform support**: Build for each OS/architecture
This approach keeps MicroRapid as a single, self-contained binary while supporting all OpenAPI versions!