> Section: [2. The model](https://jaque.sh/docs/concepts/architecture.md)
> Next: concepts/business-processes
> Index: https://jaque.sh/llms.txt


Anyone who has maintained a Nagios estate past a few hundred hosts knows
the failure this page is about: `use` chains four templates deep, a
directive misspelled in a way Nagios accepts and silently ignores, and no
way to know a config is broken until `-v` catches it, or does not. jaque's
config is CUE: a typed language whose values unify instead of inheriting,
with the schema in the language rather than beside it. This page states
the problem, what CUE replaces it with, and the two distinct points at
which a jaque config can fail.

## 1. The problem: template inheritance without a type system

Nagios configuration is templates (`use`) resolved by an ad hoc positional
algorithm: ordered multiple inheritance, `+value` to append, `null` to
unset, `register 0` for abstract templates. It works, and it is untyped.
A misspelled directive is either ignored or a runtime surprise, and there
is no way to ask whether a config is valid without loading it into the
daemon that will act on it.

## 2. What CUE gives instead

CUE is built around unification rather than inheritance. Two partial
definitions of the same value merge; they do not override each other in a
resolution order you have to remember. For "shared defaults, per-host
overrides" that is a closer fit than `use` chains ever were, and it brings
three things with it.

A real schema. jaque defines `#Host`, `#Service`, `#Check` and the rest as
closed structs, so an unknown field such as `chekc_interval` is a build
error naming the field, not a directive quietly dropped.

Validation as part of the language. Type constraints (`string & !=""`),
enumerations (disjunctions shaped like
`"OK" | "WARNING" | "CRITICAL" | "UNKNOWN"`) and numeric ranges live in
the schema itself, not in a linter bolted on after the fact.

Diffable, GitOps-friendly text. A CUE file is text you `git diff`, review
and merge. Nothing is generated by a UI that only the UI can read back.

## 3. Two validation phases

A config fails in two different places, and the errors differ.

### 3.1 Constraints, at build

CUE evaluates the object graph against `#Schema`: types, required fields,
closed-struct field names, and disjunction shape, where a check's `type`
selects which of `#TCPCheck`, `#HTTPCheck` and the rest applies. A typo or
a missing `address` is caught here, before the graph is fully concrete.

### 3.2 Concretion, at load

A config that satisfies every constraint can still be incomplete: CUE lets
a value remain an open disjunction or an unresolved reference. Running
`jaque -config x.cue` forces full concretion at load; anything still
ambiguous fails there, with the field's path in the error.

In practice: run `jaque -config yourfile.cue` and read the error. It names
the field, never only "config invalid".

## 4. What this replaces, concretely

The Nagios idiom of a `generic-host` template three levels of `use` deep
becomes a CUE template you anchor structs on:

```cue
#CastDevice: #Host & {
	parents: ["router"]
	check: type: "tcp"
}

hosts: chromecast: #CastDevice & {
	address: "192.168.1.200"
	check: address: "192.168.1.200:8009"
}
```

`#CastDevice` is not inherited from; it is unified with. Two devices on
that template cannot drift into "which one applied the override" the way
a `use` chain can. Anchoring on `#Host` matters: a bare
`#CastDevice: {...}` is implicitly closed and would reject `address` and
`check` as unknown fields at the use site, while anchoring on the schema
keeps it open exactly as the schema is.
[CUE in practice](https://jaque.sh/docs/config/cue-in-practice.md) is the full walkthrough.

## 5. The decision, and its reversal criterion

CUE was not a settled bet. ADR-003 set an explicit reversal criterion: the
Phase 0 spike had to model three hosts and ten services with a shared
template and one override, loaded and validated in-process, or the decision
reverted to YAML plus JSON Schema. It passed, and CUE is what runs today.
A config language that could not clear that bar would have been replaced,
not defended.
