2026-01-11 22:35:49 +00:00
..
2026-01-11 22:35:49 +00:00

Generated Provisioning Output Example

This directory demonstrates the complete output structure generated by the provisioning generator across all 7 layers.

Directory Structure

output-example/
├── config.ncl                  # Master configuration file
├── constraints.toml            # Layer 1: Validation bounds (single source of truth)
├── schemas/                    # Layer 2: Type contracts
│   ├── http_server.ncl
│   ├── database.ncl
│   ├── authentication.ncl
│   └── ...
├── validators/                 # Layer 3: Validation logic
│   ├── http_server.ncl
│   ├── database.ncl
│   ├── common.ncl
│   └── ...
├── defaults/                   # Layer 4: Default values
│   ├── http_server.ncl
│   ├── database.ncl
│   └── ...
├── fragments/                  # Layer 5: TypeDialog forms
│   ├── http_server-section.toml
│   ├── database-section.toml
│   ├── authentication-section.toml
│   └── ...
├── scripts/                    # Layer 6: Orchestration
│   ├── config.sh
│   ├── config.nu
│   ├── json-to-nickel.sh
│   ├── nickel-to-json.sh
│   ├── validate-nickel.sh
│   └── README.md (orchestration guide)
└── README.md                   # This file
```text

## 7-Layer Validation Architecture

The provisioning system implements a complete validation stack:

### Layer 1: Constraints (Single Source of Truth)
**File**: `constraints.toml`

Defines bounds and rules for all fields:

```toml
[http_server.bind_address]
min_length = 3
max_length = 100

[http_server.timeout_seconds]
min = 1
max = 600

[database.port]
min = 1
max = 65535
unique = false

[authentication.jwt_secret]
min_length = 32
max_length = 256
```text

**Purpose**:
- Single source of truth for validation rules
- Referenced by validators, forms, and documentation
- Enables constraint interpolation across layers
- Facilitates consistency across multiple validation backends

### Layer 2: Schemas (Type Contracts)
**Directory**: `schemas/`

Nickel type definitions for each domain feature:

**Example**: `schemas/http_server.ncl`
```nickel
{
  HttpServer = {
    bind_address | String,
    timeout_seconds | Number,
    max_connections | Number | optional,
  },
}
```text

**Purpose**:
- Type-safe configuration definitions
- Interfaces between application and configuration
- Validated by Nickel before use
- Self-documenting code

### Layer 3: Validators (Validation Logic)
**Directory**: `validators/`

Functions that enforce constraints:

**Example**: `validators/http_server.ncl`
```nickel
let validate_bind_address = fun value =>
  (std.is_string value) &&
  (std.string.length value >= 3) &&
  (std.string.length value <= 100);

let validate_timeout_seconds = fun value =>
  (std.is_number value) &&
  (value >= 1) &&
  (value <= 600);

{
  validate_bind_address,
  validate_timeout_seconds,
}
```text

**Purpose**:
- Enforce constraints defined in Layer 1
- Provide detailed validation error messages
- Can include complex logic (e.g., regex matching)
- Reusable across multiple configs

### Layer 4: Defaults (Default Values)
**Directory**: `defaults/`

Sensible defaults for each feature:

**Example**: `defaults/http_server.ncl`
```nickel
{
  http_server = {
    bind_address = "0.0.0.0:8080",
    timeout_seconds = 30,
    max_connections = 1000,
  },
}
```text

**Purpose**:
- Provide reasonable configuration starting points
- Reduce user decisions
- Document typical values
- Enable incremental configuration

### Layer 5: Fragments (Form Definitions)
**Directory**: `fragments/`

TypeDialog form fragments for user input:

**Example**: `fragments/http_server-section.toml`
```toml
[section.http_server]
description = "HTTP Server Configuration"

[[section.http_server.fields]]
name = "bind_address"
type = "text"
prompt = "Server bind address"
placeholder = "0.0.0.0:8080"
default = "0.0.0.0:8080"
help = "Format: IP:PORT (e.g., 0.0.0.0:8080)"
required = true

[[section.http_server.fields]]
name = "timeout_seconds"
type = "number"
prompt = "Request timeout"
default = 30
min = 1
max = 600
help = "Maximum seconds to wait for request completion"
```text

**Purpose**:
- Provide user-friendly configuration UI
- Enforce constraints client-side
- Guide users with prompts and help text
- Support multiple backends (CLI, TUI, Web)

### Layer 6: Scripts (Orchestration)
**Directory**: `scripts/`

Automated configuration management:

- **config.sh / config.nu**: Master orchestrator
- **json-to-nickel.sh / json-to-nickel.nu**: Convert JSON → Nickel
- **nickel-to-json.sh / nickel-to-json.nu**: Convert Nickel → JSON
- **validate-nickel.sh / validate-nickel.nu**: Validate Nickel syntax

**Purpose**:
- Automate configuration pipeline
- Convert between formats
- Validate configuration integrity
- Enable CI/CD integration

### Layer 7: Master Config
**File**: `config.ncl`

Integrates all layers:

```nickel
let constraints = import "constraints.toml"
let http_server_schema = import "schemas/http_server.ncl"
let http_server_validator = import "validators/http_server.ncl"
let http_server_defaults = import "defaults/http_server.ncl"

{
  http_server = http_server_defaults.http_server
           | http_server_schema.HttpServer
           | http_server_validator,
}
```text

## Using the Generated Structure

### 1. Display Configuration Form
```bash
# Interactive CLI form
typedialog fragments/http_server-section.toml --backend cli

# Web-based form
typedialog-web fragments/http_server-section.toml --port 3000
```text

### 2. Validate Existing Config
```bash
# Validate Nickel syntax
./scripts/validate-nickel.sh < config.ncl

# Convert and validate JSON
./scripts/json-to-nickel.sh < input.json | ./scripts/validate-nickel.sh
```text

### 3. Generate Config from User Input
```bash
# Collect form input
typedialog fragments/*.toml --backend cli --output config.json

# Convert to Nickel
./scripts/json-to-nickel.sh < config.json > config.ncl

# Validate
./scripts/validate-nickel.sh < config.ncl
```text

### 4. Use in Application
```rust
// Load and parse configuration
let config_str = std::fs::read_to_string("config.ncl")?;
let config: ServiceConfig = nickel::evaluate(&config_str)?;

// Use typed configuration
println!("Server: {}:{}", config.http_server.bind_address);
```text

### 5. Export to Other Formats
```bash
# Export to JSON
./scripts/nickel-to-json.sh < config.ncl > config.json

# Export to YAML
./scripts/nickel-to-json.sh < config.ncl | jq -r 'to_entries | map("\(.key): \(.value)") | .[]'
```text

## Constraint Interpolation

Constraints can be referenced in validators and forms:

**In constraints.toml**:
```toml
[http_server.timeout_seconds]
min = 1
max = 600
```text

**In validators**:
```nickel
let max_timeout = {{ constraints.http_server.timeout_seconds.max }};
validate_timeout = fun value => value <= max_timeout
```text

**In fragments**:
```toml
max = {{ constraints.http_server.timeout_seconds.max }}
```text

This ensures single source of truth for validation bounds.

## Field Types Supported

### Primitive Types
- **Text** - Free-form string input
- **Number** - Numeric value (integer or float)
- **Password** - Sensitive text (encrypted)
- **Confirm** - Boolean yes/no toggle

### Selection Types
- **Select** - Single choice from predefined options
- **MultiSelect** - Multiple selections

### Complex Types
- **Editor** - Multi-line code or text editing
- **Date** - Calendar date picker
- **RepeatingGroup** - Array of structured items

## Sensitive Data Handling

Fields marked as sensitive are automatically encrypted:

```toml
[[section.authentication.fields]]
name = "jwt_secret"
type = "password"
sensitive = true
encryption_backend = "age"  # or: sops, secretumvault, aws-kms, gcp-kms
```text

**Supported Encryption Backends**:
- `age` - Modern encryption (recommended)
- `sops` - Mozilla SOPS
- `secretumvault` - SecretumVault integration
- `aws-kms` - AWS KMS
- `gcp-kms` - GCP Cloud KMS
- `azure-kms` - Azure Key Vault

Encrypted fields are:
- Masked in TypeDialog forms
- Decrypted only when needed
- Never logged or stored in plain text

## Configuration Workflow

Typical workflow with generated structure:

```text
1. User runs interactive form
   ↓
   typedialog fragments/*.toml
   ↓
   User input: {http_server: {bind_address: "0.0.0.0:3000"}}

2. Convert to Nickel
   ↓
   ./scripts/json-to-nickel.sh < input.json > config.ncl

3. Validate against schema
   ↓
   ./scripts/validate-nickel.sh < config.ncl
   ✓ Valid configuration

4. Use in application
   ↓
   app.load_config("config.ncl")
   ↓
   Server starts on 0.0.0.0:3000
```text

## Extending Generated Structure

### Add a New Feature

1. **Add schema** (`schemas/my_feature.ncl`):
   ```nickel
   {
     MyFeature = {
       field1 | String,
       field2 | Number | optional,
     },
   }
  1. Add validator (validators/my_feature.ncl):

    {
      validate_field1 = fun value => true,
      validate_field2 = fun value => true,
    }
    
  2. Add defaults (defaults/my_feature.ncl):

    {
      my_feature = {
        field1 = "default",
        field2 = 42,
      },
    }
    
  3. Add fragment (fragments/my_feature-section.toml):

    [section.my_feature]
    [[section.my_feature.fields]]
    name = "field1"
    type = "text"
    
  4. Add constraints (update constraints.toml):

    [my_feature.field1]
    min_length = 1
    max_length = 100
    
  5. Update master config (config.ncl):

    let my_feature_schema = import "schemas/my_feature.ncl"
    # ... include in final config
    

Testing Configuration

# Test entire pipeline
./scripts/config.sh validate

# Test specific feature
typedialog fragments/http_server-section.toml --backend cli --test

# Test with sample data
echo '{"http_server":{"bind_address":"127.0.0.1:8080"}}' | \
  ./scripts/json-to-nickel.sh | \
  ./scripts/validate-nickel.sh
```text

## Documentation and References

- **Nickel Docs**: Type contracts and validation
- **TypeDialog Docs**: Form field types and features
- **Scripts Guide**: Orchestration and conversions (`scripts/README.md`)

## Summary

The 7-layer architecture provides:

✅ **Separation of Concerns**: Each layer has a specific role
✅ **Single Source of Truth**: Constraints defined once, used everywhere
✅ **Type Safety**: Nickel contracts prevent invalid configs
✅ **User-Friendly Forms**: TypeDialog provides intuitive UI
✅ **Automated Validation**: Constraints enforced at multiple layers
✅ **Format Flexibility**: Convert between JSON, TOML, Nickel
✅ **Reusability**: Generic components shared across projects
✅ **Extensibility**: Easy to add features and customize

The generated structure is ready for:
- Production deployment
- CI/CD integration
- Distributed configuration management
- Multi-environment setups