# ADR-010: Configuration File Format Strategy\n\n**Status**: Accepted\n**Date**: 2025-12-03\n**Decision Makers**: Architecture Team\n**Implementation**: Multi-phase migration (KCL workspace configs + template reorganization)\n\n---\n\n## Context\n\nThe provisioning project historically used a single configuration format (YAML/TOML environment variables) for all purposes. As the system evolved,\ndifferent parts naturally adopted different formats:\n\n- **TOML** for modular provider and platform configurations (`providers/*.toml`, `platform/*.toml`)\n- **KCL** for infrastructure-as-code definitions with type safety\n- **YAML** for workspace metadata\n\nHowever, the workspace configuration remained in **YAML** (`provisioning.yaml`),\ncreating inconsistency and leaving type-unsafe configuration handling. Meanwhile,\ncomplete KCL schemas for workspace configuration were designed but unused.\n\n**Problem**: Three different formats in the same system without documented rationale or consistent patterns.\n\n---\n\n## Decision\n\nAdopt a **three-format strategy** with clear separation of concerns:\n\n| Format | Purpose | Use Cases |\n| -------- | --------- | ----------- |\n| **KCL** | Infrastructure as Code & Schemas | Workspace config, infrastructure definitions, type-safe validation |\n| **TOML** | Application Configuration & Settings | System defaults, provider settings, user preferences, interpolation |\n| **YAML** | Metadata & Kubernetes Resources | K8s manifests, tool metadata, version tracking, CI/CD resources |\n\n---\n\n## Implementation Strategy\n\n### Phase 1: Documentation (Complete)\n\nDefine and document the three-format approach through:\n\n1. **ADR-010** (this document) - Rationale and strategy\n2. **CLAUDE.md updates** - Quick reference for developers\n3. **Configuration hierarchy** - Explicit precedence rules\n\n### Phase 2: Workspace Config Migration (In Progress)\n\n**Migrate workspace configuration from YAML to KCL**:\n\n1. Create comprehensive workspace configuration schema in KCL\n2. Implement backward-compatible config loader (KCL first, fallback to YAML)\n3. Provide migration script to convert existing workspaces\n4. Update workspace initialization to generate KCL configs\n\n**Expected Outcome**:\n\n- `workspace/config/provisioning.ncl` (KCL, type-safe, validated)\n- Full schema validation with semantic versioning checks\n- Automatic validation at config load time\n\n### Phase 3: Template File Reorganization (In Progress)\n\n**Move template files to proper directory structure and correct extensions**:\n\n```\nPrevious (KCL):\n  provisioning/kcl/templates/*.k  (had Nushell/Jinja2 code, not KCL)\n\nCurrent (Nickel):\n  provisioning/templates/\n    ├── nushell/*.nu.j2\n    ├── config/*.toml.j2\n    ├── nickel/*.ncl.j2\n    └── README.md\n```\n\n**Expected Outcome**:\n\n- Templates properly classified and discoverable\n- KCL validation passes (15/16 errors eliminated)\n- Template system clean and maintainable\n\n---\n\n## Rationale for Each Format\n\n### KCL for Workspace Configuration\n\n**Why KCL over YAML or TOML?**\n\n1. **Type Safety**: Catch configuration errors at schema validation time, not runtime\n\n   ```kcl\n   schema WorkspaceDeclaration:\n       metadata: Metadata\n       check:\n           regex.match(metadata.version, r"^\d+\.\d+\.\d+$"), \\n               "Version must be semantic versioning"\n   ```\n\n1. **Schema-First Development**: Schemas are first-class citizens\n   - Document expected structure upfront\n   - IDE support for auto-completion\n   - Enforce required fields and value ranges\n\n2. **Immutable by Default**: Infrastructure configurations are immutable\n   - Prevents accidental mutations\n   - Better for reproducible deployments\n   - Aligns with PAP principle: "configuration-driven, not hardcoded"\n\n3. **Complex Validation**: KCL supports sophisticated validation rules\n   - Semantic versioning validation\n   - Dependency checking\n   - Cross-field validation\n   - Range constraints on numeric values\n\n4. **Ecosystem Consistency**: KCL is already used for infrastructure definitions\n   - Server configurations use KCL\n   - Cluster definitions use KCL\n   - Taskserv definitions use KCL\n   - Using KCL for workspace config maintains consistency\n\n5. **Existing Schemas**: `provisioning/kcl/generator/declaration.ncl` already defines complete workspace schemas\n   - No design work needed\n   - Production-ready schemas\n   - Well-tested patterns\n\n### TOML for Application Configuration\n\n**Why TOML for settings?**\n\n1. **Hierarchical Structure**: Native support for nested configurations\n\n   ```toml\n   [http]\n   use_curl = false\n   timeout = 30\n\n   [debug]\n   enabled = false\n   log_level = "info"\n   ```\n\n2. **Interpolation Support**: Dynamic variable substitution\n\n   ```toml\n   base_path = "/Users/home/provisioning"\n   cache_path = "{{base_path}}/.cache"\n   ```\n\n3. **Industry Standard**: Widely used for application configuration (Rust, Python, Go)\n\n4. **Human Readable**: Clear, explicit, easy to edit\n\n5. **Validation Support**: Schema files (`.schema.toml`) for validation\n\n**Use Cases**:\n\n- System defaults: `provisioning/config/config.defaults.toml`\n- Provider settings: `workspace/config/providers/*.toml`\n- Platform services: `workspace/config/platform/*.toml`\n- User preferences: User config files\n\n### YAML for Metadata and Kubernetes Resources\n\n**Why YAML for metadata?**\n\n1. **Kubernetes Compatibility**: YAML is K8s standard\n   - K8s manifests use YAML\n   - Consistent with ecosystem\n   - Familiar to DevOps engineers\n\n2. **Lightweight**: Good for simple data structures\n\n   ```yaml\n   workspace:\n     name: "librecloud"\n     version: "1.0.0"\n     created: "2025-10-06T12:29:43Z"\n   ```\n\n3. **Version Control**: Human-readable format\n   - Diffs are clear and meaningful\n   - Git-friendly\n   - Comments supported\n\n**Use Cases**:\n\n- K8s resource definitions\n- Tool metadata (versions, sources, tags)\n- CI/CD configuration files\n- User workspace metadata (during transition)\n\n---\n\n## Configuration Hierarchy (Priority)\n\n**When loading configuration, use this precedence (highest to lowest)**:\n\n1. **Runtime Arguments** (highest priority)\n   - CLI flags passed to commands\n   - Explicit user input\n\n2. **Environment Variables** (PROVISIONING_*)\n   - Override system settings\n   - Deployment-specific overrides\n   - Secrets via env vars\n\n3. **User Configuration** (Centralized)\n   - User preferences: `~/.config/provisioning/user_config.yaml`\n   - User workspace overrides: `workspace/config/local-overrides.toml`\n\n4. **Infrastructure Configuration**\n   - Workspace KCL config: `workspace/config/provisioning.ncl`\n   - Platform services: `workspace/config/platform/*.toml`\n   - Provider configs: `workspace/config/providers/*.toml`\n\n5. **System Defaults** (lowest priority)\n   - System config: `provisioning/config/config.defaults.toml`\n   - Schema defaults: defined in KCL schemas\n\n---\n\n## Migration Path\n\n### For Existing Workspaces\n\n1. **Migration Path**: Config loader checks for `.ncl` first, then falls back to `.yaml` for legacy systems\n\n   ```nushell\n   # Try Nickel first (current)\n   if ($config_nickel | path exists) {\n       let config = (load_nickel_workspace_config $config_nickel)\n   } else if ($config_yaml | path exists) {\n       # Legacy YAML support (from pre-migration)\n       let config = (open $config_yaml)\n   }\n   ```\n\n2. **Automatic Migration**: Migration script converts YAML/KCL → Nickel\n\n   ```bash\n   provisioning workspace migrate-config --all\n   ```\n\n3. **Validation**: New KCL configs validated against schemas\n\n### For New Workspaces\n\n1. **Generate KCL**: Workspace initialization creates `.k` files\n\n   ```bash\n   provisioning workspace create my-workspace\n   # Creates: workspace/my-workspace/config/provisioning.ncl\n   ```\n\n2. **Use Existing Schemas**: Leverage `provisioning/kcl/generator/declaration.ncl`\n\n3. **Schema Validation**: Automatic validation during config load\n\n---\n\n## File Format Guidelines for Developers\n\n### When to Use Each Format\n\n**Use KCL for**:\n\n- Infrastructure definitions (servers, clusters, taskservs)\n- Configuration with type requirements\n- Schema definitions\n- Any config that needs validation rules\n- Workspace configuration\n\n**Use TOML for**:\n\n- Application settings (HTTP client, logging, timeouts)\n- Provider-specific settings\n- Platform service configuration\n- User preferences and overrides\n- System defaults with interpolation\n\n**Use YAML for**:\n\n- Kubernetes manifests\n- CI/CD configuration (GitHub Actions, GitLab CI)\n- Tool metadata\n- Human-readable documentation files\n- Version control metadata\n\n---\n\n## Consequences\n\n### Benefits\n\n✅ **Type Safety**: KCL schema validation catches config errors early\n✅ **Consistency**: Infrastructure definitions and configs use same language\n✅ **Maintainability**: Clear separation of concerns (IaC vs settings vs metadata)\n✅ **Validation**: Semantic versioning, required fields, range checks\n✅ **Tooling**: IDE support for KCL auto-completion\n✅ **Documentation**: Self-documenting schemas with descriptions\n✅ **Ecosystem Alignment**: TOML for settings (Rust standard), YAML for K8s\n\n### Trade-offs\n\n⚠️ **Learning Curve**: Developers must understand three formats\n⚠️ **Migration Effort**: Existing YAML configs need conversion\n⚠️ **Tooling Requirements**: KCL compiler needed (already a dependency)\n\n### Risk Mitigation\n\n1. **Documentation**: Clear guidelines in CLAUDE.md\n2. **Backward Compatibility**: YAML support maintained during transition\n3. **Automation**: Migration scripts for existing workspaces\n4. **Gradual Migration**: No hard cutoff, both formats supported for extended period\n\n---\n\n## Template File Reorganization\n\n### Problem\n\nCurrently, 15/16 files in `provisioning/kcl/templates/` have `.k` extension but contain Nushell/Jinja2 code, not KCL:\n\n```\nprovisioning/kcl/templates/\n├── server.ncl          # Actually Nushell/Jinja2 template\n├── taskserv.ncl        # Actually Nushell/Jinja2 template\n└── ...               # 15 more template files\n```\n\nThis causes:\n\n- KCL validation failures (96.6% of errors)\n- Misclassification (templates in KCL directory)\n- Confusing directory structure\n\n### Solution\n\nReorganize into type-specific directories:\n\n```\nprovisioning/templates/\n├── nushell/           # Nushell code generation (*.nu.j2)\n│   ├── server.nu.j2\n│   ├── taskserv.nu.j2\n│   └── ...\n├── config/            # Config file generation (*.toml.j2, *.yaml.j2)\n│   ├── provider.toml.j2\n│   └── ...\n├── kcl/               # KCL file generation (*.k.j2)\n│   ├── workspace.ncl.j2\n│   └── ...\n└── README.md\n```\n\n### Outcome\n\n✅ Correct file classification\n✅ KCL validation passes completely\n✅ Clear template organization\n✅ Easier to discover and maintain templates\n\n---\n\n## References\n\n### Existing KCL Schemas\n\n1. **Workspace Declaration**: `provisioning/kcl/generator/declaration.ncl`\n   - `WorkspaceDeclaration` - Complete workspace specification\n   - `Metadata` - Name, version, author, timestamps\n   - `DeploymentConfig` - Deployment modes, servers, HA settings\n   - Includes validation rules and semantic versioning\n\n2. **Workspace Layer**: `provisioning/workspace/layers/workspace.layer.ncl`\n   - `WorkspaceLayer` - Template paths, priorities, metadata\n\n3. **Core Settings**: `provisioning/kcl/settings.ncl`\n   - `Settings` - Main provisioning settings\n   - `SecretProvider` - SOPS/KMS configuration\n   - `AIProvider` - AI provider configuration\n\n### Related ADRs\n\n- **ADR-001**: Project Structure\n- **ADR-005**: Extension Framework\n- **ADR-006**: Provisioning CLI Refactoring\n- **ADR-009**: Security System Complete\n\n---\n\n## Decision Status\n\n**Status**: Accepted\n\n**Next Steps**:\n\n1. ✅ Document strategy (this ADR)\n2. ⏳ Create workspace configuration KCL schema\n3. ⏳ Implement backward-compatible config loader\n4. ⏳ Create migration script for YAML → KCL\n5. ⏳ Move template files to proper directories\n6. ⏳ Update documentation with examples\n7. ⏳ Migrate workspace_librecloud to KCL\n\n---\n\n**Last Updated**: 2025-12-03
