Appearance
Schema: Advanced Features
Advanced schema features provide fine-grained control over configuration processing, including immutable fields, input/output schema validation, and complex processing patterns.
Immutable Fields
The immutable directive protects configuration paths from being overwritten during merging. Once set by an earlier source, immutable paths cannot be modified by later sources.
Structure
yaml
immutable:
- "path.to.protected.field"
- "another.immutable.path"Behavior
- Source Order Matters: First source to set an immutable path wins
- Complete Protection: Later sources cannot override immutable values
- Environment Override:
KONFIGO_KEY_*environment variables can still override immutable paths - Deep Path Protection: Protects specific nested paths, not entire objects
Examples from Tests
Schema with Immutable Paths:
yaml
immutable:
- "service.name"
- "database.port"
- "security.apiKey"
# Rest of schema...
generators:
- type: "concat"
targetPath: "service.url"
format: "https://{name}.example.com"
sources:
name: "service.name"Source Files:
01-base.yaml (loaded first):
yaml
service:
name: "user-service"
version: "1.0.0"
database:
host: "localhost"
port: 5432
security:
apiKey: "base-secret-key"02-override.yaml (loaded second):
yaml
service:
name: "overridden-service" # ← Will be IGNORED (immutable)
version: "2.0.0" # ← Will be applied (not immutable)
database:
host: "prod-db.example.com"
port: 9999 # ← Will be IGNORED (immutable)
security:
apiKey: "new-secret" # ← Will be IGNORED (immutable)
protocol: "https" # ← Will be applied (not immutable)Final Result:
yaml
service:
name: "user-service" # ← Protected by immutable
version: "2.0.0" # ← Updated by second source
url: "https://user-service.example.com" # ← Generated using protected name
database:
host: "prod-db.example.com"
port: 5432 # ← Protected by immutable
security:
apiKey: "base-secret-key" # ← Protected by immutable
protocol: "https" # ← Added by second sourceEnvironment Variable Override
Even immutable fields can be overridden by environment variables:
bash
# This WILL override the immutable service.name
export KONFIGO_KEY_service__name=env-override-service
konfigo -s 01-base.yaml -s 02-override.yaml -S schema.yamlResult:
yaml
service:
name: "env-override-service" # ← Environment variable wins
# ... rest unchangedInput Schema Validation
The inputSchema directive validates merged configuration structure before any schema processing (variables, generators, transformations).
Structure
yaml
inputSchema:
path: "path/to/input-schema.yaml"
strict: false # Optional, default: falseFields
path(Required): Path to external schema file defining expected input structurestrict(Optional, default:false):false: Extra keys allowed in inputtrue: Input must contain only keys defined in schema
Example
Input Schema Definition (input-structure.yaml):
yaml
# Defines expected structure after merging sources
service:
name: ""
port: 0
database:
host: ""
credentials:
username: ""Main Schema (schema.yaml):
yaml
inputSchema:
path: "./input-structure.yaml"
strict: false
# Continue with normal processing
vars:
- name: "DB_PASSWORD"
fromEnv: "DATABASE_PASSWORD"
defaultValue: "default-pass"
generators:
- type: "concat"
targetPath: "database.connectionString"
format: "postgresql://{user}:${DB_PASSWORD}@{host}:5432/app"
sources:
user: "database.credentials.username"
host: "database.host"Valid Input (passes validation):
yaml
service:
name: "api-service"
port: 8080
# Extra field allowed when strict: false
environment: "production"
database:
host: "db.example.com"
credentials:
username: "api_user"Invalid Input (fails validation):
yaml
service:
# Missing required port field
name: "api-service"
database:
# Missing host field
credentials:
username: "api_user"Output Schema Filtering
The outputSchema directive filters final configuration to include only specified keys, creating clean, controlled output.
Structure
yaml
outputSchema:
path: "path/to/output-schema.yaml"
strict: false # Optional, default: falseFields
path(Required): Path to external schema file defining output structurestrict(Optional, default:false):false: Include only keys present in output schema, ignore extrastrue: Final output must exactly match output schema structure
Example
Output Schema Definition (public-api.yaml):
yaml
# Define what should be included in final output
api:
endpoint: ""
version: ""
database:
host: ""
# Note: credentials intentionally excludedMain Schema (schema.yaml):
yaml
outputSchema:
path: "./public-api.yaml"
strict: false
# Processing that creates more data than we want to expose
vars:
- name: "API_VERSION"
value: "v1.2.3"
generators:
- type: "concat"
targetPath: "api.endpoint"
format: "https://{host}/api/{version}"
sources:
host: "service.host"
version: "api.version"
# Generate internal fields that won't appear in output
- type: "concat"
targetPath: "internal.buildId"
format: "build-{timestamp}"
sources:
timestamp: "build.timestamp"Full Processed Configuration (before output filtering):
yaml
api:
endpoint: "https://api.example.com/api/v1.2.3"
version: "v1.2.3"
host: "api.example.com" # Extra field
database:
host: "db.example.com"
credentials:
username: "secret_user" # Sensitive data
password: "secret_pass"
service:
host: "api.example.com"
internal:
buildId: "build-2024-06-26T10:30:00Z"
debug: trueFinal Filtered Output:
yaml
api:
endpoint: "https://api.example.com/api/v1.2.3"
version: "v1.2.3"
# api.host excluded (not in output schema)
database:
host: "db.example.com"
# credentials excluded (not in output schema)
# service and internal sections completely excludedStrict Mode Behavior
When strict: true is used with input or output schemas:
Input Schema Strict Mode
yaml
inputSchema:
path: "./strict-input.yaml"
strict: trueStrict Input Schema (strict-input.yaml):
yaml
service:
name: ""
port: 0Valid Input:
yaml
service:
name: "api"
port: 8080
# No extra keys allowedInvalid Input:
yaml
service:
name: "api"
port: 8080
environment: "prod" # ← ERROR: Extra key not in schemaOutput Schema Strict Mode
yaml
outputSchema:
path: "./strict-output.yaml"
strict: trueRequires processed configuration to exactly match output schema structure - no missing keys, no extra keys.
Combined Advanced Features
Complete Advanced Schema Example:
yaml
# Protect critical configuration
immutable:
- "service.name"
- "database.credentials.username"
# Validate input structure
inputSchema:
path: "./schemas/input-validation.yaml"
strict: false
# Define clean output
outputSchema:
path: "./schemas/public-output.yaml"
strict: false
# Standard processing
vars:
- name: "ENVIRONMENT"
fromEnv: "NODE_ENV"
defaultValue: "development"
generators:
- type: "concat"
targetPath: "service.url"
format: "https://{name}-${ENVIRONMENT}.example.com"
sources:
name: "service.name" # Protected by immutable
transform:
- type: "setValue"
path: "metadata.processed"
value: true
validate:
- path: "service.url"
rules:
required: true
type: "string"
regex: "^https://"This provides comprehensive control over configuration processing with validation, protection, and filtering.
Best Practices
- Immutable Core Values: Protect essential configuration that shouldn't change
- Input Validation: Verify merged configuration meets expectations before processing
- Output Filtering: Create clean, secure output by excluding internal/sensitive data
- Gradual Adoption: Start with basic features and add advanced controls as needed
- Schema Evolution: Use separate schema files for input/output validation to enable independent evolution