Consistency Constraints
On top of the semantic diff, cfgdrift overlays a constraint-checking layer: after drift is detected, the changed configuration tree is validated against five constraint types, and only violations associated with the current drift are reported — deterministic, explainable, compound alerts.
The five constraint types
| Type | Meaning | Example |
|---|---|---|
range | numeric value must stay in [min, max] | server.port ∈ [1, 65535] |
enum | value must be in a whitelist | log.level ∈ {debug, info, warn, error} |
conditional_required | when the condition holds, the key is required | if tls.enabled then tls.cert required |
correlation | numeric/string relation when the condition holds | replicas ≤ max_replicas |
mutual_exclusion | two keys must not both be present | http.auth ≠ oauth |
Complete schema: examples/constraints.yaml.example.
CLI usage
# diff / scan enable the built-in library by default (20 constraints, four domains: web/db/log/auth)
cfgdrift diff ./config --baseline prod
cfgdrift diff ./config --baseline prod --no-builtin # disable built-ins
cfgdrift diff ./config --baseline prod --constraints extra.yaml # add more (repeatable)
# manage <home>/constraints.yaml
cfgdrift constraint add --rule '{"id":"my_port","type":"range","keys":["server.port"],"min":1,"max":65535,"message":"server.port must be ≤ 65535"}'
cfgdrift constraint list # effective view (builtin + user merged, same id → user wins)
cfgdrift constraint list --source builtin # built-in library only
cfgdrift constraint remove my_port
cfgdrift constraint disable my_port # / enable my_port
How violations escalate
- Escalation:
new = min(CRITICAL, max(item.rank+1, max(violated constraints' rank))), reusingSeverity.rank(NONE=0 / INFO=1 / WARN=2 / CRITICAL=3). - Association (zero noise): per file, violations whose
involved_keys ∩ drifted keys ≠ ∅are attached; missing keys / unmetwhenconditions are skipped. - Five presentation exits: terminal (item line +
constraint <id> [<type>]: <message>), JSON (constraint_violations), HTML report column, Web dashboard badge, alert payloadconstraintfield. - Zero-noise contract: a legal change (e.g.
server.port8080→9090 in range) is byte-identical to pre-constraint output.
Baseline violations report (v0.7.0)
cfgdrift scan PATH --baseline B --report-violations # off by default
Reports pre-existing violations on the baseline itself, deduplicated against drift-associated ones
by (constraint_id, file, frozenset(involved_keys)); severity comes straight from the
constraint.
Constraint auto-mining (v0.7.0)
cfgdrift constraint mine --min-support 5 --source scans
cfgdrift constraint mine --source corpus --corpus instances.jsonl
cfgdrift constraint mine --json
Discovers candidates (enum/range domains, co-occurrence → conditional_required, mutual exclusion)
and writes them to <home>/mined_candidates.yaml with enabled: false /
status: pending. The candidate zone never auto-activates; promote with
constraint add --rule '<JSON>' after review.
Deep-dive semantics: README.en.md — Consistency Constraints.