2026-01-14 02:59:52 +00:00
|
|
|
# Constraints\n\nSingle source of truth for validation limits across all services.\n\n## Purpose\n\nThe `constraints.toml` file defines:\n- **Numeric ranges** (min/max values for ports, workers, timeouts, etc.)\n- **Uniqueness rules** (field constraints, array bounds)\n- **Validation bounds** (resource limits, timeout ranges)\n\nThese constraints are used by:\n1. **Validators** (`validators/*.ncl`) - Check that configuration values are within bounds\n2. **TypeDialog forms** (`forms/*.toml`) - Enable constraint interpolation for dynamic field validation\n3. **Nickel schemas** (`schemas/*.ncl`) - Define type contracts with bounds\n\n## File Structure\n\n```\nconstraints/\n└── constraints.toml # All validation constraints in TOML format\n```\n\n## Usage Pattern\n\n### 1. Define Constraint\n\n**constraints.toml**:\n\n```\n[orchestrator.queue.concurrent_tasks]\nmin = 1\nmax = 100\n```\n\n### 2. Reference in Validator\n\n**validators/orchestrator-validator.ncl**:\n\n```\nlet constraints = import "../constraints/constraints.toml" in\n\n{\n ValidConcurrentTasks = fun tasks =>\n if tasks < constraints.orchestrator.queue.concurrent_tasks.min then\n error "Tasks must be >= 1"\n else if tasks > constraints.orchestrator.queue.concurrent_tasks.max then\n error "Tasks must be <= 100"\n else\n tasks,\n}\n```\n\n### 3. Reference in Form\n\n**forms/fragments/orchestrator-queue-section.toml**:\n\n```\n[[elements]]\nname = "max_concurrent_tasks"\ntype = "number"\nmin = "${constraint.orchestrator.queue.concurrent_tasks.min}"\nmax = "${constraint.orchestrator.queue.concurrent_tasks.max}"\nhelp = "Max: ${constraint.orchestrator.queue.concurrent_tasks.max}"\nnickel_path = ["orchestrator", "queue", "max_concurrent_tasks"]\n```\n\n## Constraint Categories\n\n### Service-Specific Constraints\n\n- **Orchestrator** (`[orchestrator.*]`)\n - Worker count bounds\n - Queue concurrency limits\n - Task timeout ranges\n - Batch parallelism limits\n\n- **Control Center** (`[control_center.*]`)\n - JWT token expiration bounds\n - Rate limiting thresholds\n - RBAC policy limits\n\n- **MCP Server** (`[mcp_server.*]`)\n - Tool concurrency limits\n - Resource size bounds\n - Prompt template limits\n\n### Common Constraints\n\n- **Server** (`[common.server.*]`)\n - Port range (1024-65535)\n - Worker count\n - Connection limits\n\n- **Deployment** (`[deployment.{solo,multiuser,cicd,enterprise}.*]`)\n - CPU core bounds\n - Memory allocation bounds\n - Disk space requirements\n\n## Modifying Constraints\n\nWhen changing constraint bounds:\n\n1. **Update constraints.toml**\n2. **Update validators** that use the constraint\n3. **Update forms** that interpolate the constraint\n4. **Test validation** in forms and Nickel typecheck\n5. **Update documentation** of affected services\n\n### Example: Increase Max Queue Tasks\n\n**Before**:\n\n```\n[orchestrator.queue.concurrent_tasks]\nmin = 1\nmax = 100\n```\n\n**After**:\n\n```\n[orchestrator.queue.concurrent_tasks]\nmin = 1\nmax = 200 # Increased from 100\n```\n\n**Then**:\n1. Verify `validators/orchestrator-validator.ncl` still type-checks\n2. Form will automatically show new max (via constraint interpolation)\n3. Test with: `nu scripts/validate-config.nu values/orchestrator.*.ncl`\n\n## Constraint Interpolation in Forms\n\nTypeDialog supports dynamic constraint references via `${constraint.path.to.value}`:\n\n```\n# Static min/max\nmin = 1\nmax = 100\n\n# Dynamic from constraints.toml\nmin = "${constraint.orchestrator.queue.concurrent_tasks.min}"\nmax = "${constraint.orchestrator.queue.concurrent_tasks.max}"\n\n# Help text with dynamic reference\nhelp = "Value must be between ${constraint.orchestrator.queue.concurrent_tasks.min} and ${constraint.orchestrator.queue.concurrent_tasks.max}"\n```\n\n## Best Practices\n\n1. **Single source of truth** - Define constraint once in constraints.toml\n2. **Meaningful names** - Use clear path hierarchy (service.subsystem.property)\n3. **Document ranges** - Add comments explaining why min/max values exist\n4. **Validate propagation**
|