11. Capstone: schema a real config
Put it all together — vocabulary, constraints, document root, and instances for a deployment config.
After this lesson you can
- Design a closed vocabulary with symbol_set - Declare block kinds with labels, defaults, and list fields - Validate instances against the schema and evaluate the result
Before you start: Tooling day-to-day
The capstone is the workflow you'll actually use: pick a config your project needs (deployments, pipelines, fixtures), declare its vocabulary as types, point a @document at them, and author real instances. A symbol_set closes an enum-like field — wcl check rejects any symbol not in the set — which is usually the first constraint worth adding.
Work schema-first: get one instance validating, then tighten (defaults for the common case, @min/@max where numbers have bounds, optionals where absence is legal). When the schema stops surprising you, the config is done.
§ 1Exercise: A deployment config from scratch
Model apps deployed to environments: a closed Env vocabulary, an app block with defaults, and two instances.
// A tiny deployment config — schema and data in one file.
symbol_set Env { dev staging prod }
@block("app")
type App {
@inline(0) name: identifier
env: Env
@default(1) replicas: u32
@default([]) domains: list<utf8>
}
@document
type Deploy {
@children("app") apps: list<App>
}
app web {
env = :prod
replicas = 3u32
domains = ["example.com", "www.example.com"]
}
app worker { env = :staging }
Expected result
wcl check prints OK, and wcl eval deploy.wcl apps.web.replicas prints 3u32; worker picked up replicas = 1 and domains = [] from the defaults.
Hint
Set env = :production on an app — the check fails because production isn't in the Env symbol_set. Closed vocabularies catch typos schemas otherwise miss.
§ 2Exercise: Make it yours
Extend the schema with one thing your real config needs — a nested block (@child), a numeric bound (@min), or an optional field — and keep the document validating.
Expected result
wcl check still prints OK after the extension, and at least one instance exercises the new declaration.
Hint
Add the constraint first and watch check fail, then fix the data — the error message names the file, field, and rule, which is the debugging loop you'll live in.