# Configuration Validation Guide\n\n## Overview\n\nThe new configuration system includes comprehensive schema validation to catch errors early and ensure configuration correctness.\n\n## Schema Validation Features\n\n### 1. Required Fields Validation\n\nEnsures all required fields are present:\n\n```\n# Schema definition\n[required]\nfields = ["name", "version", "enabled"]\n\n# Valid config\nname = "my-service"\nversion = "1.0.0"\nenabled = true\n\n# Invalid - missing 'enabled'\nname = "my-service"\nversion = "1.0.0"\n# Error: Required field missing: enabled\n```\n\n### 2. Type Validation\n\nValidates field types:\n\n```\n# Schema\n[fields.port]\ntype = "int"\n\n[fields.name]\ntype = "string"\n\n[fields.enabled]\ntype = "bool"\n\n# Valid\nport = 8080\nname = "orchestrator"\nenabled = true\n\n# Invalid - wrong type\nport = "8080"  # Error: Expected int, got string\n```\n\n### 3. Enum Validation\n\nRestricts values to predefined set:\n\n```\n# Schema\n[fields.environment]\ntype = "string"\nenum = ["dev", "staging", "prod"]\n\n# Valid\nenvironment = "prod"\n\n# Invalid\nenvironment = "production"  # Error: Must be one of: dev, staging, prod\n```\n\n### 4. Range Validation\n\nValidates numeric ranges:\n\n```\n# Schema\n[fields.port]\ntype = "int"\nmin = 1024\nmax = 65535\n\n# Valid\nport = 8080\n\n# Invalid - below minimum\nport = 80  # Error: Must be >= 1024\n\n# Invalid - above maximum\nport = 70000  # Error: Must be <= 65535\n```\n\n### 5. Pattern Validation\n\nValidates string patterns using regex:\n\n```\n# Schema\n[fields.email]\ntype = "string"\npattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"\n\n# Valid\nemail = "admin@example.com"\n\n# Invalid\nemail = "not-an-email"  # Error: Does not match pattern\n```\n\n### 6. Deprecated Fields\n\nWarns about deprecated configuration:\n\n```\n# Schema\n[deprecated]\nfields = ["old_field"]\n\n[deprecated_replacements]\nold_field = "new_field"\n\n# Config using deprecated field\nold_field = "value"  # Warning: old_field is deprecated. Use new_field instead.\n```\n\n## Using Schema Validator\n\n### Command Line\n\n```\n# Validate workspace config\nprovisioning workspace config validate\n\n# Validate provider config\nprovisioning provider validate aws\n\n# Validate platform service config\nprovisioning platform validate orchestrator\n\n# Validate with detailed output\nprovisioning workspace config validate --verbose\n```\n\n### Programmatic Usage\n\n```\nuse provisioning/core/nulib/lib_provisioning/config/schema_validator.nu *\n\n# Load config\nlet config = (open ~/workspaces/my-project/config/provisioning.yaml | from yaml)\n\n# Validate against schema\nlet result = (validate-workspace-config $config)\n\n# Check results\nif $result.valid {\n  print "✅ Configuration is valid"\n} else {\n  print "❌ Configuration has errors:"\n  for error in $result.errors {\n    print $"  • ($error.message)"\n  }\n}\n\n# Display warnings\nif ($result.warnings | length) > 0 {\n  print "⚠️  Warnings:"\n  for warning in $result.warnings {\n    print $"  • ($warning.message)"\n  }\n}\n```\n\n### Pretty Print Results\n\n```\n# Validate and print formatted results\nlet result = (validate-workspace-config $config)\nprint-validation-results $result\n```\n\n## Schema Examples\n\n### Workspace Schema\n\nFile: `/Users/Akasha/project-provisioning/provisioning/config/workspace.schema.toml`\n\n```\n[required]\nfields = ["workspace", "paths"]\n\n[fields.workspace]\ntype = "record"\n\n[fields.workspace.name]\ntype = "string"\npattern = "^[a-z][a-z0-9-]*$"\n\n[fields.workspace.version]\ntype = "string"\npattern = "^\\d+\\.\\d+\\.\\d+$"\n\n[fields.paths]\ntype = "record"\n\n[fields.paths.base]\ntype = "string"\n\n[fields.paths.infra]\ntype = "string"\n\n[fields.debug]\ntype = "record"\n\n[fields.debug.enabled]\ntype = "bool"\n\n[fields.debug.log_level]\ntype = "string"\nenum = ["debug", "info", "warn", "error"]\n```\n\n### Provider Schema (AWS)\n\nFile: `/Users/Akasha/project-provisioning/provisioning/extensions/providers/aws/config.schema.toml`\n\n```\n[required]\nfields = ["provider", "credentials"]\n\n[fields.provider]\ntype = "record"\n\n[fields.provider.name]\ntype = "string"\nenum = ["aws"]\n\n[fields.provider.region]\ntype = "string"\npattern = "^[a-z]{2}-[a-z]+-\\d+$"\n\n[fields.provider.enabled]\ntype = "bool"\n\n[fields.credentials]\ntype = "record"\n\n[fields.credentials.type]\ntype = "string"\nenum = ["environment", "file", "iam_role"]\n\n[fields.compute]\ntype = "record"\n\n[fields.compute.default_instance_type]\ntype = "string"\n\n[fields.compute.default_ami]\ntype = "string"\npattern = "^ami-[a-f0-9]{8,17}$"\n\n[fields.network]\ntype = "record"\n\n[fields.network.vpc_id]\ntype = "string"\npattern = "^vpc-[a-f0-9]{8,17}$"\n\n[fields.network.subnet_id]\ntype = "string"\npattern = "^subnet-[a-f0-9]{8,17}$"\n\n[deprecated]\nfields = ["old_region_field"]\n\n[deprecated_replacements]\nold_region_field = "provider.region"\n```\n\n### Platform Service Schema (Orchestrator)\n\nFile: `/Users/Akasha/project-provisioning/provisioning/platform/orchestrator/config.schema.toml`\n\n```\n[required]\nfields = ["service", "server"]\n\n[fields.service]\ntype = "record"\n\n[fields.service.name]\ntype = "string"\nenum = ["orchestrator"]\n\n[fields.service.enabled]\ntype = "bool"\n\n[fields.server]\ntype = "record"\n\n[fields.server.host]\ntype = "string"\n\n[fields.server.port]\ntype = "int"\nmin = 1024\nmax = 65535\n\n[fields.workers]\ntype = "int"\nmin = 1\nmax = 32\n\n[fields.queue]\ntype = "record"\n\n[fields.queue.max_size]\ntype = "int"\nmin = 100\nmax = 10000\n\n[fields.queue.storage_path]\ntype = "string"\n```\n\n### KMS Service Schema\n\nFile: `/Users/Akasha/project-provisioning/provisioning/core/services/kms/config.schema.toml`\n\n```\n[required]\nfields = ["kms", "encryption"]\n\n[fields.kms]\ntype = "record"\n\n[fields.kms.enabled]\ntype = "bool"\n\n[fields.kms.provider]\ntype = "string"\nenum = ["aws_kms", "gcp_kms", "azure_kv", "vault", "local"]\n\n[fields.encryption]\ntype = "record"\n\n[fields.encryption.algorithm]\ntype = "string"\nenum = ["AES-256-GCM", "ChaCha20-Poly1305"]\n\n[fields.encryption.key_rotation_days]\ntype = "int"\nmin = 30\nmax = 365\n\n[fields.vault]\ntype = "record"\n\n[fields.vault.address]\ntype = "string"\npattern = "^https?://.*$"\n\n[fields.vault.token_path]\ntype = "string"\n\n[deprecated]\nfields = ["old_kms_type"]\n\n[deprecated_replacements]\nold_kms_type = "kms.provider"\n```\n\n## Validation Workflow\n\n### 1. Development\n\n```\n# Create new config\nvim ~/workspaces/dev/config/provisioning.yaml\n\n# Validate immediately\nprovisioning workspace config validate\n\n# Fix errors and revalidate\nvim ~/workspaces/dev/config/provisioning.yaml\nprovisioning workspace config validate\n```\n\n### 2. CI/CD Pipeline\n\n```\n# GitLab CI\nvalidate-config:\n  stage: validate\n  script:\n    - provisioning workspace config validate\n    - provisioning provider validate aws\n    - provisioning provider validate upcloud\n    - provisioning platform validate orchestrator\n  only:\n    changes:\n      - "*/config/**/*"\n```\n\n### 3. Pre-Deployment\n\n```\n# Validate all configurations before deployment\nprovisioning workspace config validate --verbose\nprovisioning provider validate --all\nprovisioning platform validate --all\n\n# If valid, proceed with deployment\nif [[ $? -eq 0 ]]; then\n  provisioning deploy --workspace production\nfi\n```\n\n## Error Messages\n\n### Clear Error Format\n\n```\n❌ Validation failed\n\nErrors:\n  • Required field missing: workspace.name\n  • Field port type mismatch: expected int, got string\n  • Field environment must be one of: dev, staging, prod\n  • Field port must be >= 1024\n  • Field email does not match pattern: ^[a-zA-Z0-9._%+-]+@.*$\n\n⚠️  Warnings:\n  • Field old_field is deprecated. Use new_field instead.\n```\n\n### Error Details\n\nEach error includes:\n\n- **field**: Which field has the error\n- **type**: Error type (missing_required, type_mismatch, invalid_enum, etc.)\n- **message**: Human-readable description\n- **Additional context**: Expected values, patterns, ranges\n\n## Common Validation Patterns\n\n### Pattern 1: Hostname Validation\n\n```\n[fields.hostname]\ntype = "string"\npattern = "^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$"\n```\n\n### Pattern 2: Email Validation\n\n```\n[fields.email]\ntype = "string"\npattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"\n```\n\n### Pattern 3: Semantic Version\n\n```\n[fields.version]\ntype = "string"\npattern = "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9]+)?$"\n```\n\n### Pattern 4: URL Validation\n\n```\n[fields.url]\ntype = "string"\npattern = "^https?://[a-zA-Z0-9.-]+(:[0-9]+)?(/.*)?$"\n```\n\n### Pattern 5: IPv4 Address\n\n```\n[fields.ip_address]\ntype = "string"\npattern = "^(?:[0-9]{1,3}\\.){3}[0-9]{1,3}$"\n```\n\n### Pattern 6: AWS Resource ID\n\n```\n[fields.instance_id]\ntype = "string"\npattern = "^i-[a-f0-9]{8,17}$"\n\n[fields.ami_id]\ntype = "string"\npattern = "^ami-[a-f0-9]{8,17}$"\n\n[fields.vpc_id]\ntype = "string"\npattern = "^vpc-[a-f0-9]{8,17}$"\n```\n\n## Testing Validation\n\n### Unit Tests\n\n```\n# Run validation test suite\nnu provisioning/tests/config_validation_tests.nu\n```\n\n### Integration Tests\n\n```\n# Test with real configs\nprovisioning test validate --workspace dev\nprovisioning test validate --workspace staging\nprovisioning test validate --workspace prod\n```\n\n### Custom Validation\n\n```\n# Create custom validation function\ndef validate-custom-config [config: record] {\n  let result = (validate-workspace-config $config)\n\n  # Add custom business logic validation\n  if ($config.workspace.name | str starts-with "prod") {\n    if not $config.debug.enabled == false {\n      $result.errors = ($result.errors | append {\n        field: "debug.enabled"\n        type: "custom"\n        message: "Debug must be disabled in production"\n      })\n    }\n  }\n\n  $result\n}\n```\n\n## Best Practices\n\n### 1. Validate Early\n\n```\n# Validate during development\nprovisioning workspace config validate\n\n# Don't wait for deployment\n```\n\n### 2. Use Strict Schemas\n\n```\n# Be explicit about types and constraints\n[fields.port]\ntype = "int"\nmin = 1024\nmax = 65535\n\n# Don't leave fields unvalidated\n```\n\n### 3. Document Patterns\n\n```\n# Include examples in schema\n[fields.email]\ntype = "string"\npattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"\n# Example: user@example.com\n```\n\n### 4. Handle Deprecation\n\n```\n# Always provide replacement guidance\n[deprecated_replacements]\nold_field = "new_field"  # Clear migration path\n```\n\n### 5. Test Schemas\n\n```\n# Include test cases in comments\n# Valid: "admin@example.com"\n# Invalid: "not-an-email"\n```\n\n## Troubleshooting\n\n### Schema File Not Found\n\n```\n# Error: Schema file not found: /path/to/schema.toml\n\n# Solution: Ensure schema exists\nls -la /Users/Akasha/project-provisioning/provisioning/config/*.schema.toml\n```\n\n### Pattern Not Matching\n\n```\n# Error: Field hostname does not match pattern\n\n# Debug: Test pattern separately\necho "my-hostname" | grep -E "^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$"\n```\n\n### Type Mismatch\n\n```\n# Error: Expected int, got string\n\n# Check config\ncat ~/workspaces/dev/config/provisioning.yaml | yq '.server.port'\n# Output: "8080" (string)\n\n# Fix: Remove quotes\nvim ~/workspaces/dev/config/provisioning.yaml\n# Change: port: "8080"\n# To:     port: 8080\n```\n\n## Additional Resources\n\n- [Migration Guide](./MIGRATION_GUIDE.md)\n- [Workspace Guide](./WORKSPACE_GUIDE.md)\n- [Schema Files](../config/*.schema.toml)\n- [Validation Tests](../tests/config_validation_tests.nu)
