Mode B: Config File Specification

This example shows provisioning generation from a declarative TOML configuration file.

Use Cases

Mode B is ideal when:

  • You don't have a Cargo.toml to analyze (e.g., Python, Go services)
  • You want complete control over feature definitions
  • You're designing configuration before implementation
  • You need custom fields not automatically detected
  • You're configuring existing services with different tech stacks

Configuration Structure

The project-spec.toml file has three main sections:

1. Project Metadata

[project]
name = "service-name"
description = "What this service does"
type = "Microservice"  # WebService, CliTool, Microservice, Library

2. Infrastructure Requirements

[infrastructure]
ssh = true
monitoring = ["prometheus", "grafana"]
cloud_providers = ["aws", "gcp"]

[[infrastructure.databases]]
type = "postgres"
required = true

3. Domain Features

Each feature represents a functional capability:

[features.my_feature]
description = "What this feature does"
enabled = true

[[features.my_feature.fields]]
name = "field_name"
type = "Text"              # Text, Number, Password, Confirm, Select, etc.
prompt = "User prompt"
default = "default_value"
help = "Helpful text"
required = true
sensitive = false          # Set to true for passwords/secrets
encryption_backend = "age" # For sensitive fields
min = 1                    # For numbers/arrays
max = 100
options = ["a", "b"]       # For Select/MultiSelect

4. Constraints (Single Source of Truth)

[constraints.feature_name.field_name]
min = 1
max = 100
min_length = 5
max_length = 255

Running the Example

Generate Provisioning Structure

typedialog-provisioning-gen config \
  --input examples/11-provisioning-generation/mode-b-config/project-spec.toml \
  --output /tmp/microservice-platform

Inspect Generated Files

# View master configuration
cat /tmp/microservice-platform/config.ncl

# View API gateway schema
cat /tmp/microservice-platform/schemas/api_gateway.ncl

# View authentication fragment
cat /tmp/microservice-platform/fragments/authentication-section.toml

# Validate constraints
cat /tmp/microservice-platform/constraints.toml

Test Forms Interactively

# Test API gateway configuration form
typedialog /tmp/microservice-platform/fragments/api_gateway-section.toml --backend cli

# Test authentication configuration form
typedialog /tmp/microservice-platform/fragments/authentication-section.toml --backend cli

Use Generated Scripts

cd /tmp/microservice-platform

# Validate Nickel syntax
./scripts/validate-nickel.sh

# Create Nickel from JSON input
echo '{"api_gateway": {"bind_address": "0.0.0.0:8080"}}' | \
  ./scripts/json-to-nickel.sh

# Convert back to JSON
./scripts/nickel-to-json.sh < config.ncl

Features Defined in This Example

1. API Gateway

  • Purpose: REST API entry point with rate limiting
  • Fields:
    • bind_address - Interface and port
    • rate_limit - Requests per second
    • timeout_seconds - Request timeout

Generated Output:

  • Schema: schemas/api_gateway.ncl - Type contract
  • Validator: validators/api_gateway.ncl - Validation rules
  • Defaults: defaults/api_gateway.ncl - Default values
  • Fragment: fragments/api_gateway-section.toml - UI form

2. Event Streaming

  • Purpose: Message queue for event-driven architecture
  • Fields:
    • broker_url - Message broker connection
    • consumer_group - Kafka consumer group ID
    • max_concurrent_consumers - Parallelism

3. Authentication

  • Purpose: JWT-based access control
  • Fields:
    • jwt_secret - Sensitive signing key (encrypted)
    • jwt_expiry_hours - Token lifetime
    • allow_refresh_tokens - Refresh mechanism

4. Observability

  • Purpose: Logging and distributed tracing
  • Fields:
    • log_level - Trace/Debug/Info/Warn/Error
    • enable_distributed_tracing - Toggle tracing
    • trace_sample_rate - Sampling percentage

5. Database Migrations

  • Purpose: Schema versioning and evolution
  • Fields:
    • migration_directory - Path to SQL files
    • auto_migrate_on_startup - Automatic migrations

Field Types Reference

Type Use Case Example
Text Free-form string domain.example.com
Number Integer or float 8080, 0.5
Password Sensitive text secret key (encrypted)
Confirm Yes/No toggle Enable feature?
Select Single choice Log level: debug, info, warn
MultiSelect Multiple choices Monitoring: prometheus, grafana
Editor Multi-line code SQL migration script
Date Calendar picker Deployment date
RepeatingGroup Array of items Multiple database servers

Sensitive Fields

Mark fields as sensitive for encryption:

[[features.authentication.fields]]
name = "jwt_secret"
type = "Password"
sensitive = true
encryption_backend = "age"  # Default: age

Supported backends:

  • age - Modern encryption (recommended)
  • sops - Mozilla SOPS
  • secretumvault - SecretumVault integration
  • aws-kms - AWS Key Management Service
  • gcp-kms - Google Cloud KMS
  • azure-kms - Azure Key Vault

Constraints System

Constraints provide a single source of truth for validation bounds:

[constraints.api_gateway.bind_address]
min_length = 3
max_length = 50

[constraints.api_gateway.rate_limit]
min = 1
max = 10000

These constraints are:

  • Used in TypeDialog forms (enforced client-side)
  • Referenced in validators (Nickel validation)
  • Available in fragments (UI constraints)
  • Documented in generated schema

Extending This Example

Add a New Feature

  1. Add to project-spec.toml:

    [features.caching]
    description = "Redis caching layer"
    
    [[features.caching.fields]]
    name = "redis_url"
    type = "Text"
    prompt = "Redis connection string"
    
  2. Regenerate:

    typedialog-provisioning-gen config --input project-spec.toml --output ./output
    
  3. Generated files appear:

    • schemas/caching.ncl
    • validators/caching.ncl
    • defaults/caching.ncl
    • fragments/caching-section.toml

Customize a Field

  1. Modify the field definition
  2. Update constraints if needed
  3. Regenerate

The regeneration merges with existing configuration, making it safe to iterate.

What This Demonstrates

Complete feature definition without code Type safety through Nickel contracts Constraint interpolation (single source of truth) Multi-language field options (Select, MultiSelect) Sensitive data encryption configuration Infrastructure requirements specification Full 7-layer validation stack generation

Next Steps

  1. Copy and Customize: Use this as a template for your service
  2. Add Your Features: Define the capabilities your service provides
  3. Generate: Run provisioning-gen to create artifacts
  4. Test: Use TypeDialog forms to validate configuration
  5. Deploy: Use generated scripts for orchestration
  6. Iterate: Modify spec and regenerate as needed

Integration with Application

Once generated, import Nickel schemas in your app:

# config.ncl
let infrastructure = import "schemas/database.ncl"
let auth = import "schemas/authentication.ncl"

{
  database = {
    %host% = "localhost",
    port = 5432,
  } | infrastructure.Database,

  authentication = auth.Authentication,
}

Or deserialize from JSON:

# Load configuration from TypeDialog form output
./scripts/json-to-nickel.sh < form-output.json > config.ncl

# Validate against schema
nickel eval config.ncl

# Export to application
./scripts/nickel-to-json.sh < config.ncl > config.json