# Configuration Validation Guide

## Overview

The new configuration system includes comprehensive schema validation to catch errors early and ensure configuration correctness.

## Schema Validation Features

### 1. Required Fields Validation

Ensures all required fields are present:

```toml
# Schema definition
[required]
fields = ["name", "version", "enabled"]

# Valid config
name = "my-service"
version = "1.0.0"
enabled = true

# Invalid - missing 'enabled'
name = "my-service"
version = "1.0.0"
# Error: Required field missing: enabled
```plaintext

### 2. Type Validation

Validates field types:

```toml
# Schema
[fields.port]
type = "int"

[fields.name]
type = "string"

[fields.enabled]
type = "bool"

# Valid
port = 8080
name = "orchestrator"
enabled = true

# Invalid - wrong type
port = "8080"  # Error: Expected int, got string
```plaintext

### 3. Enum Validation

Restricts values to predefined set:

```toml
# Schema
[fields.environment]
type = "string"
enum = ["dev", "staging", "prod"]

# Valid
environment = "prod"

# Invalid
environment = "production"  # Error: Must be one of: dev, staging, prod
```plaintext

### 4. Range Validation

Validates numeric ranges:

```toml
# Schema
[fields.port]
type = "int"
min = 1024
max = 65535

# Valid
port = 8080

# Invalid - below minimum
port = 80  # Error: Must be >= 1024

# Invalid - above maximum
port = 70000  # Error: Must be <= 65535
```plaintext

### 5. Pattern Validation

Validates string patterns using regex:

```toml
# Schema
[fields.email]
type = "string"
pattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"

# Valid
email = "admin@example.com"

# Invalid
email = "not-an-email"  # Error: Does not match pattern
```plaintext

### 6. Deprecated Fields

Warns about deprecated configuration:

```toml
# Schema
[deprecated]
fields = ["old_field"]

[deprecated_replacements]
old_field = "new_field"

# Config using deprecated field
old_field = "value"  # Warning: old_field is deprecated. Use new_field instead.
```plaintext

## Using Schema Validator

### Command Line

```bash
# Validate workspace config
provisioning workspace config validate

# Validate provider config
provisioning provider validate aws

# Validate platform service config
provisioning platform validate orchestrator

# Validate with detailed output
provisioning workspace config validate --verbose
```plaintext

### Programmatic Usage

```nushell
use provisioning/core/nulib/lib_provisioning/config/schema_validator.nu *

# Load config
let config = (open ~/workspaces/my-project/config/provisioning.yaml | from yaml)

# Validate against schema
let result = (validate-workspace-config $config)

# Check results
if $result.valid {
  print "✅ Configuration is valid"
} else {
  print "❌ Configuration has errors:"
  for error in $result.errors {
    print $"  • ($error.message)"
  }
}

# Display warnings
if ($result.warnings | length) > 0 {
  print "⚠️  Warnings:"
  for warning in $result.warnings {
    print $"  • ($warning.message)"
  }
}
```plaintext

### Pretty Print Results

```nushell
# Validate and print formatted results
let result = (validate-workspace-config $config)
print-validation-results $result
```plaintext

## Schema Examples

### Workspace Schema

File: `/Users/Akasha/project-provisioning/provisioning/config/workspace.schema.toml`

```toml
[required]
fields = ["workspace", "paths"]

[fields.workspace]
type = "record"

[fields.workspace.name]
type = "string"
pattern = "^[a-z][a-z0-9-]*$"

[fields.workspace.version]
type = "string"
pattern = "^\\d+\\.\\d+\\.\\d+$"

[fields.paths]
type = "record"

[fields.paths.base]
type = "string"

[fields.paths.infra]
type = "string"

[fields.debug]
type = "record"

[fields.debug.enabled]
type = "bool"

[fields.debug.log_level]
type = "string"
enum = ["debug", "info", "warn", "error"]
```plaintext

### Provider Schema (AWS)

File: `/Users/Akasha/project-provisioning/provisioning/extensions/providers/aws/config.schema.toml`

```toml
[required]
fields = ["provider", "credentials"]

[fields.provider]
type = "record"

[fields.provider.name]
type = "string"
enum = ["aws"]

[fields.provider.region]
type = "string"
pattern = "^[a-z]{2}-[a-z]+-\\d+$"

[fields.provider.enabled]
type = "bool"

[fields.credentials]
type = "record"

[fields.credentials.type]
type = "string"
enum = ["environment", "file", "iam_role"]

[fields.compute]
type = "record"

[fields.compute.default_instance_type]
type = "string"

[fields.compute.default_ami]
type = "string"
pattern = "^ami-[a-f0-9]{8,17}$"

[fields.network]
type = "record"

[fields.network.vpc_id]
type = "string"
pattern = "^vpc-[a-f0-9]{8,17}$"

[fields.network.subnet_id]
type = "string"
pattern = "^subnet-[a-f0-9]{8,17}$"

[deprecated]
fields = ["old_region_field"]

[deprecated_replacements]
old_region_field = "provider.region"
```plaintext

### Platform Service Schema (Orchestrator)

File: `/Users/Akasha/project-provisioning/provisioning/platform/orchestrator/config.schema.toml`

```toml
[required]
fields = ["service", "server"]

[fields.service]
type = "record"

[fields.service.name]
type = "string"
enum = ["orchestrator"]

[fields.service.enabled]
type = "bool"

[fields.server]
type = "record"

[fields.server.host]
type = "string"

[fields.server.port]
type = "int"
min = 1024
max = 65535

[fields.workers]
type = "int"
min = 1
max = 32

[fields.queue]
type = "record"

[fields.queue.max_size]
type = "int"
min = 100
max = 10000

[fields.queue.storage_path]
type = "string"
```plaintext

### KMS Service Schema

File: `/Users/Akasha/project-provisioning/provisioning/core/services/kms/config.schema.toml`

```toml
[required]
fields = ["kms", "encryption"]

[fields.kms]
type = "record"

[fields.kms.enabled]
type = "bool"

[fields.kms.provider]
type = "string"
enum = ["aws_kms", "gcp_kms", "azure_kv", "vault", "local"]

[fields.encryption]
type = "record"

[fields.encryption.algorithm]
type = "string"
enum = ["AES-256-GCM", "ChaCha20-Poly1305"]

[fields.encryption.key_rotation_days]
type = "int"
min = 30
max = 365

[fields.vault]
type = "record"

[fields.vault.address]
type = "string"
pattern = "^https?://.*$"

[fields.vault.token_path]
type = "string"

[deprecated]
fields = ["old_kms_type"]

[deprecated_replacements]
old_kms_type = "kms.provider"
```plaintext

## Validation Workflow

### 1. Development

```bash
# Create new config
vim ~/workspaces/dev/config/provisioning.yaml

# Validate immediately
provisioning workspace config validate

# Fix errors and revalidate
vim ~/workspaces/dev/config/provisioning.yaml
provisioning workspace config validate
```plaintext

### 2. CI/CD Pipeline

```yaml
# GitLab CI
validate-config:
  stage: validate
  script:
    - provisioning workspace config validate
    - provisioning provider validate aws
    - provisioning provider validate upcloud
    - provisioning platform validate orchestrator
  only:
    changes:
      - "*/config/**/*"
```plaintext

### 3. Pre-Deployment

```bash
# Validate all configurations before deployment
provisioning workspace config validate --verbose
provisioning provider validate --all
provisioning platform validate --all

# If valid, proceed with deployment
if [[ $? -eq 0 ]]; then
  provisioning deploy --workspace production
fi
```plaintext

## Error Messages

### Clear Error Format

```plaintext
❌ Validation failed

Errors:
  • Required field missing: workspace.name
  • Field port type mismatch: expected int, got string
  • Field environment must be one of: dev, staging, prod
  • Field port must be >= 1024
  • Field email does not match pattern: ^[a-zA-Z0-9._%+-]+@.*$

⚠️  Warnings:
  • Field old_field is deprecated. Use new_field instead.
```plaintext

### Error Details

Each error includes:

- **field**: Which field has the error
- **type**: Error type (missing_required, type_mismatch, invalid_enum, etc.)
- **message**: Human-readable description
- **Additional context**: Expected values, patterns, ranges

## Common Validation Patterns

### Pattern 1: Hostname Validation

```toml
[fields.hostname]
type = "string"
pattern = "^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$"
```plaintext

### Pattern 2: Email Validation

```toml
[fields.email]
type = "string"
pattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
```plaintext

### Pattern 3: Semantic Version

```toml
[fields.version]
type = "string"
pattern = "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9]+)?$"
```plaintext

### Pattern 4: URL Validation

```toml
[fields.url]
type = "string"
pattern = "^https?://[a-zA-Z0-9.-]+(:[0-9]+)?(/.*)?$"
```plaintext

### Pattern 5: IPv4 Address

```toml
[fields.ip_address]
type = "string"
pattern = "^(?:[0-9]{1,3}\\.){3}[0-9]{1,3}$"
```plaintext

### Pattern 6: AWS Resource ID

```toml
[fields.instance_id]
type = "string"
pattern = "^i-[a-f0-9]{8,17}$"

[fields.ami_id]
type = "string"
pattern = "^ami-[a-f0-9]{8,17}$"

[fields.vpc_id]
type = "string"
pattern = "^vpc-[a-f0-9]{8,17}$"
```plaintext

## Testing Validation

### Unit Tests

```nushell
# Run validation test suite
nu provisioning/tests/config_validation_tests.nu
```plaintext

### Integration Tests

```bash
# Test with real configs
provisioning test validate --workspace dev
provisioning test validate --workspace staging
provisioning test validate --workspace prod
```plaintext

### Custom Validation

```nushell
# Create custom validation function
def validate-custom-config [config: record] {
  let result = (validate-workspace-config $config)

  # Add custom business logic validation
  if ($config.workspace.name | str starts-with "prod") {
    if not $config.debug.enabled == false {
      $result.errors = ($result.errors | append {
        field: "debug.enabled"
        type: "custom"
        message: "Debug must be disabled in production"
      })
    }
  }

  $result
}
```plaintext

## Best Practices

### 1. Validate Early

```bash
# Validate during development
provisioning workspace config validate

# Don't wait for deployment
```plaintext

### 2. Use Strict Schemas

```toml
# Be explicit about types and constraints
[fields.port]
type = "int"
min = 1024
max = 65535

# Don't leave fields unvalidated
```plaintext

### 3. Document Patterns

```toml
# Include examples in schema
[fields.email]
type = "string"
pattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
# Example: user@example.com
```plaintext

### 4. Handle Deprecation

```toml
# Always provide replacement guidance
[deprecated_replacements]
old_field = "new_field"  # Clear migration path
```plaintext

### 5. Test Schemas

```nushell
# Include test cases in comments
# Valid: "admin@example.com"
# Invalid: "not-an-email"
```plaintext

## Troubleshooting

### Schema File Not Found

```bash
# Error: Schema file not found: /path/to/schema.toml

# Solution: Ensure schema exists
ls -la /Users/Akasha/project-provisioning/provisioning/config/*.schema.toml
```plaintext

### Pattern Not Matching

```bash
# Error: Field hostname does not match pattern

# Debug: Test pattern separately
echo "my-hostname" | grep -E "^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$"
```plaintext

### Type Mismatch

```bash
# Error: Expected int, got string

# Check config
cat ~/workspaces/dev/config/provisioning.yaml | yq '.server.port'
# Output: "8080" (string)

# Fix: Remove quotes
vim ~/workspaces/dev/config/provisioning.yaml
# Change: port: "8080"
# To:     port: 8080
```plaintext

## Additional Resources

- [Migration Guide](./MIGRATION_GUIDE.md)
- [Workspace Guide](./WORKSPACE_GUIDE.md)
- [Schema Files](../config/*.schema.toml)
- [Validation Tests](../tests/config_validation_tests.nu)
