# Validators\n\nValidation logic for configuration values using constraints and business rules.\n\n## Purpose\n\nValidators provide:\n- **Constraint checking** - Numeric ranges, required fields\n- **Business logic validation** - Service-specific constraints\n- **Error messages** - Clear feedback on invalid values\n- **Composition with configs** - Validators applied during config generation\n\n## File Organization\n\n```\nvalidators/\n├── README.md # This file\n├── common-validator.ncl # Ports, positive numbers, strings\n├── network-validator.ncl # IP addresses, bind addresses\n├── path-validator.ncl # File paths, directories\n├── resource-validator.ncl # CPU, memory, disk\n├── string-validator.ncl # Workspace names, identifiers\n├── orchestrator-validator.ncl # Queue, workflow validation\n├── control-center-validator.ncl # RBAC, policy validation\n├── mcp-server-validator.ncl # MCP tools, capabilities\n└── deployment-validator.ncl # Resource allocation\n```\n\n## Validation Patterns\n\n### 1. Basic Range Validation\n\n```\n# validators/common-validator.ncl\nlet constraints = import "../constraints/constraints.toml" in\n\n{\n ValidPort = fun port =>\n if port < constraints.common.server.port.min then\n std.contract.blame_with_message "Port < 1024" port\n else if port > constraints.common.server.port.max then\n std.contract.blame_with_message "Port > 65535" port\n else\n port,\n}\n```\n\n### 2. Range Validator (Reusable)\n\n```\n# Reusable validator for any numeric range\nValidRange = fun min max value =>\n if value < min then\n std.contract.blame_with_message "Value < %{std.to_string min}" value\n else if value > max then\n std.contract.blame_with_message "Value > %{std.to_string max}" value\n else\n value,\n```\n\n### 3. Enum Validation\n\n```\n{\n ValidStorageBackend = fun backend =>\n if backend != 'filesystem &&\n backend != 'rocksdb &&\n backend != 'surrealdb &&\n backend != 'postgres then\n std.contract.blame_with_message "Invalid backend" backend\n else\n backend,\n}\n```\n\n### 4. String Validation\n\n```\n{\n ValidNonEmptyString = fun s =>\n if s == "" then\n std.contract.blame_with_message "Cannot be empty" s\n else\n s,\n\n ValidWorkspaceName = fun name =>\n if std.string.matches "^[a-z0-9_-]+$" name then\n name\n else\n std.contract.blame_with_message "Invalid workspace name" name,\n}\n```\n\n## Common Validators\n\n### common-validator.ncl\n\n```\nlet constraints = import "../constraints/constraints.toml" in\n\n{\n # Port validation\n ValidPort = fun port =>\n if port < constraints.common.server.port.min then error "Port too low"\n else if port > constraints.common.server.port.max then error "Port too high"\n else port,\n\n # Positive integer\n ValidPositiveNumber = fun n =>\n if n <= 0 then error "Must be positive"\n else n,\n\n # Non-empty string\n ValidNonEmptyString = fun s =>\n if s == "" then error "Cannot be empty"\n else s,\n\n # Generic range validator\n ValidRange = fun min max value =>\n if value < min then error "Value below minimum"\n else if value > max then error "Value above maximum"\n else value,\n}\n```\n\n### resource-validator.ncl\n\n```\nlet constraints = import "../constraints/constraints.toml" in\nlet common = import "./common-validator.ncl" in\n\n{\n # Validate CPU cores for deployment mode\n ValidCPUCores = fun mode cores =>\n let limits = constraints.deployment.{mode} in\n common.ValidRange limits.cpu.min limits.cpu.max cores,\n\n # Validate memory allocation\n ValidMemory = fun mode memory_mb =>\n let limits = constraints.deployment.{mode} in\n common.ValidRange limits.memory_mb.min limits.memory_mb.max memory_mb,\n}\n```\n\n## Service-Specific Validators\n\n### orchestrator-validator.ncl\n\n```\nlet constraints = import "../const