# Schemas Reference

Provisioning uses Nickel schemas for type-safe infrastructure definitions. This reference documents the schema organization, structure, and usage patterns.

## Schema Organization

Schemas are organized in `provisioning/schemas/`:

```plaintext
provisioning/schemas/
├── main.ncl                 # Root schema entry point
├── lib/
│   ├── contracts.ncl        # Type contracts and validators
│   ├── functions.ncl        # Helper functions
│   └── types.ncl            # Common type definitions
├── config/
│   ├── providers.ncl        # Provider configuration schemas
│   ├── settings.ncl         # Platform settings schemas
│   └── workspace.ncl        # Workspace configuration schemas
├── infrastructure/
│   ├── servers.ncl          # Server resource schemas
│   ├── networks.ncl         # Network resource schemas
│   └── storage.ncl          # Storage resource schemas
├── operations/
│   ├── deployment.ncl       # Deployment workflow schemas
│   └── lifecycle.ncl        # Resource lifecycle schemas
├── services/
│   ├── kubernetes.ncl       # Kubernetes schemas
│   └── databases.ncl        # Database schemas
└── integrations/
    ├── cloud_providers.ncl  # Cloud provider integrations
    └── external_services.ncl # External service integrations
```

## Core Contracts

### Server Contract

```nickel
let Server = {
  name
    | doc "Server identifier (must be unique)"
    | String,

  plan
    | doc "Server size (small, medium, large, xlarge)"
    | | [ 'small, 'medium, 'large, 'xlarge | ],

  provider
    | doc "Cloud provider (upcloud, aws, local)"
    | | [ 'upcloud, 'aws, 'local | ],

  zone
    | doc "Availability zone"
    | String
    | optional,

  ip_address
    | doc "Public IP address"
    | String
    | optional,

  storage
    | doc "Storage configuration"
    | Array StorageConfig
    | default = [],

  metadata
    | doc "Custom metadata tags"
    | {_ : String}
    | default = {},
}
```

### Network Contract

```nickel
let Network = {
  name
    | doc "Network identifier"
    | String,

  cidr
    | doc "CIDR block (e.g., 10.0.0.0/16)"
    | String
    | std.string.is_match_regex "^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$",

  subnets
    | doc "Subnet definitions"
    | Array Subnet,

  routing
    | doc "Routing configuration"
    | RoutingConfig
    | optional,
}
```

### Storage Contract

```nickel
let StorageConfig = {
  size_gb
    | doc "Storage size in GB"
    | Number
    | std.number.greater 0,

  type
    | doc "Storage type"
    | | [ 'ssd, 'hdd, 'nvme | ],

  mount_point
    | doc "Mount path"
    | String
    | optional,

  encrypted
    | doc "Enable encryption"
    | Bool
    | default = false,
}
```

## Workspace Schema

Workspace configuration schema:

```nickel
let WorkspaceConfig = {
  name
    | doc "Workspace identifier"
    | String,

  environment
    | doc "Environment type"
    | | [ 'development, 'staging, 'production | ],

  providers
    | doc "Enabled providers"
    | Array | [ 'upcloud, 'aws, 'local | ]
    | default = ['local],

  infrastructure
    | doc "Infrastructure definitions"
    | {
        servers | Array Server | default = [],
        networks | Array Network | default = [],
        storage | Array StorageConfig | default = [],
      },

  settings
    | doc "Workspace-specific settings"
    | {_ : _}
    | default = {},
}
```

## Provider Schemas

### UpCloud Provider

```nickel
let UpCloudConfig = {
  username
    | doc "UpCloud username"
    | String,

  password
    | doc "UpCloud password (encrypted)"
    | String,

  default_zone
    | doc "Default zone"
    | | [ 'fi-hel1, 'fi-hel2, 'de-fra1, 'uk-lon1, 'us-chi1, 'us-sjo1 | ]
    | default = 'fi-hel1,

  timeout_seconds
    | doc "API timeout"
    | Number
    | default = 300,
}
```

### AWS Provider

```nickel
let AWSConfig = {
  access_key_id
    | doc "AWS access key"
    | String,

  secret_access_key
    | doc "AWS secret key (encrypted)"
    | String,

  default_region
    | doc "Default AWS region"
    | String
    | default = "eu-west-1",

  assume_role_arn
    | doc "IAM role ARN"
    | String
    | optional,
}
```

## Service Schemas

### Kubernetes Schema

```nickel
let KubernetesCluster = {
  name
    | doc "Cluster name"
    | String,

  version
    | doc "Kubernetes version"
    | String
    | std.string.is_match_regex "^v[0-9]+\\.[0-9]+\\.[0-9]+$",

  control_plane
    | doc "Control plane configuration"
    | {
        nodes | Number | std.number.greater 0,
        plan | | [ 'small, 'medium, 'large | ],
      },

  workers
    | doc "Worker node pools"
    | Array NodePool,

  networking
    | doc "Network configuration"
    | {
        pod_cidr | String,
        service_cidr | String,
        cni | | [ 'calico, 'cilium, 'flannel | ] | default = 'cilium,
      },

  addons
    | doc "Cluster addons"
    | Array | [ 'metrics-server, 'ingress-nginx, 'cert-manager | ]
    | default = [],
}
```

## Validation Functions

Custom validation functions in `lib/contracts.ncl`:

```nickel
let is_valid_hostname = fun name =>
  std.string.is_match_regex "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" name
in

let is_valid_port = fun port =>
  std.number.is_integer port && port >= 1 && port <= 65535
in

let is_valid_email = fun email =>
  std.string.is_match_regex "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" email
in
```

## Merging and Composition

Schemas support composition through record merging:

```nickel
let base_server = {
  plan = 'medium,
  provider = 'upcloud,
  storage = [],
}

let production_server = base_server & {
  plan = 'large,
  storage = [{size_gb = 100, type = 'ssd}],
}
```

## Contract Enforcement

Type checking is enforced at load time:

```bash
# Typecheck schema
nickel typecheck provisioning/schemas/main.ncl

# Export with validation
nickel export --format json workspace/infra/servers.ncl
```

Invalid configurations are rejected before deployment.

## Best Practices

1. **Define contracts first** - Start with type contracts before implementation
2. **Use enums for choices** - Leverage `| [ 'option1, 'option2 | ]` for fixed sets
3. **Document everything** - Use `|doc "description"` annotations
4. **Validate early** - Run `nickel typecheck` before deployment
5. **Compose, don't duplicate** - Use record merging for common patterns
6. **Version schemas** - Track schema changes alongside infrastructure
7. **Test contracts** - Validate edge cases and constraints

## References

- [Nickel Guide](nickel-guide.md) - Nickel language reference
- [Configuration System](configuration-system.md) - Configuration hierarchy
- [Providers](providers.md) - Provider-specific schemas
