# ADR-003: Nickel as Source of Truth

**Status**: Accepted | **Date**: 2025-01-16 | **Supersedes**: None

## Context

The Provisioning platform must support infrastructure-as-code with type-safe configuration
management. Historical alternatives included KCL and TOML-based configurations.

## Decision

Nickel is adopted as the **exclusive source of truth** for all infrastructure configurations
across all environments (developer, production, CI/CD). Type safety is mandatory, not optional.

## Rationale

1. **Type Safety**: Nickel provides compile-time type checking preventing configuration errors before deployment
2. **Expressiveness**: Function composition and lazy evaluation support complex infrastructure patterns
3. **Validation**: Integration with Cedar policies ensures security at configuration level
4. **Hierarchy Support**: Seamless merging of configuration layers (core → workspace → profile → environment → runtime)
5. **Tooling**: First-class IDE support (VSCode plugins) and CLI integration

## Consequences

- **Positive**:
  - Zero configuration type errors in production
  - IDE type hints during configuration writing
  - Automatic schema validation
  - Reduced debugging time (validation catches errors early)
  - 100% configuration reproducibility

- **Negative**:
  - Learning curve for developers unfamiliar with functional programming
  - TOML migration required for existing projects
  - Nushell plugin performance impact for large configs (mitigated by caching)

## Implementation

### Configuration Hierarchy

```nickel
# Layer 1: Core defaults (provisioning/schemas/main.ncl)
let defaults = {
  infrastructure.compute.region = "us-east-1",
  infrastructure.compute.auto_scaling = { enabled = false }
}

# Layer 2: Workspace schema (workspace/schema.ncl)
let workspace_config = {
  infrastructure.compute.region = "us-west-2",  # Override defaults
}

# Layer 3: Profile config (workspace/profiles/production.ncl)
let profile_config = {
  infrastructure.compute.auto_scaling.enabled = true,  # Override workspace
}

# Layer 4: Environment config (workspace/env/prod.env.ncl)
let env_config = {
  infrastructure.compute.instance_count = 5,  # Environment-specific
}

# Final merged config
defaults | merge workspace_config | merge profile_config | merge env_config
```

### Type Validation

All configurations must pass type validation:

```nickel
# provisioning/schemas/main.ncl
{
  infrastructure = {
    compute | type = {
      region | type = String,
      instance_type | type = String,
      count | type = Number & (> 0),
      auto_scaling | type = {
        enabled | type = Bool,
        min | type = Number & (> 0),
        max | type = Number & (>= min),
      }
    }
  }
}
```

### Validation Command

```bash
provisioning validate config --profile production --environment prod
# Returns: Type errors, policy violations, or success confirmation
```

## Related ADRs

- [ADR-001: Modular CLI Architecture](./adr-001-modular-cli.md) - CLI supports Nickel validation
- [ADR-002: Workspace-First Design](./adr-002-workspace-first.md) - Workspaces organize Nickel configs
- [ADR-011: Nickel Migration](./adr-011-nickel-migration.md) - KCL → Nickel transition

## Alternatives Considered

1. **TOML** - Rejected: No type safety, parsing errors cascade to runtime
2. **KCL** - Rejected: Superceded by Nickel, full migration complete
3. **Hybrid TOML+Validation** - Rejected: Configuration is truth, validation is secondary (violates IaC principle)
