# devops-validate

[![Crates.io](https://img.shields.io/crates/v/devops-validate.svg)](https://crates.io/crates/devops-validate)
[![docs.rs](https://docs.rs/devops-validate/badge.svg)](https://docs.rs/devops-validate)
[![License: MIT OR Apache-2.0](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](LICENSE-MIT)

YAML validation and auto-repair engine for DevOps configuration files.

Works offline — no network required. Validates structure via [`serde`] deserialization,
applies best-practice rules via a built-in rule engine, and repairs common mistakes
automatically through a 6-stage pipeline.

## Supported formats

| Format | Detection | Validation | Best-practice rules |
|--------|-----------|------------|---------------------|
| Kubernetes (all resource kinds) | ✅ | ✅ | ✅ |
| Docker Compose | ✅ | ✅ | — |
| GitLab CI | ✅ | ✅ | ✅ |
| GitHub Actions | ✅ | ✅ | — |
| Prometheus | ✅ | ✅ | — |
| Alertmanager | ✅ | ✅ | — |
| Helm values.yaml | ✅ | ✅ | — |
| Ansible playbooks | ✅ | ✅ | — |
| OpenAPI 3.x | ✅ | — | — |

## Quick start

```toml
[dependencies]
devops-validate = "0.1"
```

### Auto-detect and validate

```rust
use devops_validate::validator::validate_auto;

let yaml = r#"
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: app
          image: my-app:latest
"#;

let result = validate_auto(yaml);

if !result.valid {
    for err in &result.errors {
        eprintln!("Error: {}", err);
    }
}
for warn in &result.warnings {
    println!("Warning: {}", warn);
}
// Warns: replicas=1, image :latest tag, missing resource limits, missing probes
```

### Detect YAML type

```rust
use devops_validate::validator::{parse_yaml, detect_yaml_type};
use devops_models::models::validation::YamlType;

let yaml = "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: x\nspec:\n  selector:\n    matchLabels:\n      app: x\n  template:\n    metadata:\n      labels:\n        app: x\n    spec:\n      containers: []";
let data = parse_yaml(yaml).unwrap();
let yaml_type = detect_yaml_type(&data);
assert_eq!(yaml_type, YamlType::K8sDeployment);
```

### Auto-repair

The 6-stage repair pipeline applies deterministic fixes (type coercion, extra-key
removal, default injection) and identifies fields that need human or LLM assistance:

```rust
use devops_validate::repair::repair_yaml;
use serde_json::json;

let schema = json!({
    "type": "object",
    "properties": {
        "replicas": { "type": "integer", "default": 1 },
        "name": { "type": "string" }
    }
});

let broken = "replicas: \"3\"\nname: my-app";
let result = repair_yaml(broken, &schema);

println!("Repaired YAML:\n{}", result.repaired_yaml);
// "replicas" coerced from string "3" to integer 3
```

### JSON Schema validation

```rust
use devops_validate::schema::SchemaRegistry;

let mut registry = SchemaRegistry::new();
let schema = registry.get_schema_sync("k8s/deployment").unwrap();
```

### Rule engine

```rust
use devops_validate::rules::{load_builtin_rules, load_rules_for_type};
use serde_json::json;

let engine = load_builtin_rules();
let data = json!({ "spec": { "replicas": 1 } });
let diagnostics = engine.evaluate(&data);

assert!(!diagnostics.is_empty());
for diag in &diagnostics {
    println!("[{:?}] {}", diag.severity, diag.message);
}
```

## Feature flags

| Feature | Description |
|---------|-------------|
| `wasm` | Enable WASM-compatible `getrandom` backend. Required when targeting `wasm32-unknown-unknown`. |

```toml
# WASM targets
[target.'cfg(target_arch = "wasm32")'.dependencies]
devops-validate = { version = "0.1", features = ["wasm"] }
```

## Relationship to other crates

- **[devops-models](https://crates.io/crates/devops-models)** — The typed models this crate validates against.
- **[devops-toolkit](https://crates.io/crates/devops-toolkit)** — Meta-crate that re-exports both.

## License

Licensed under either of [MIT](LICENSE-MIT) or [Apache-2.0](LICENSE-APACHE), at your option.
