ADR-009. How a managed field is compared, and who decides
Status: accepted, 7 September 2026. Still in force.
Context
A managing module reads the resource, compares, and writes only the difference (ADR-003). The comparison was strict equality, and the runtime said so about itself:
the comparison is strict. A field the API reorders or normalises will report
changedon every run.
requested returned by the API
tags: tags:
- production - web
- web - production
strict equality -> changed, every run
set comparison -> unchanged
A module that reports changed on every run is not idempotent, whatever
changed displays, and it cannot be used in a handler. The fault is worse than
noise: it teaches the reader to ignore changed.
Decision
Every managed parameter carries a comparison strategy, computed in the Ansible model and applied by the runtime.
The type decides what it can. An override decides the rest. Nothing is
guessed. Measured on both vendored contracts: no array declares uniqueItems,
and no array description mentions ordering. Deducing set from the shape of an
array would therefore be a guess, and rule 3 of this repository forbids it.
source |
strategies |
|---|---|
the IR type |
|
an override, with its reason |
|
ordered_list is a fallback, not a decision. Adopting set by default
would silence a changed that may be right, and a module that hides a real
change is worse than one that announces an extra.
An override may not restate what the type already decides: two sources for one decision diverge, and nothing would say so.
The runtime fails on a strategy it does not know rather than falling back to strict equality. A silent fallback would give a module that believes it compares one way and compares another, which is the original fault made invisible.
Consequences
The generation summary publishes how many parameters fall under each strategy.
That is what makes the fallback visible: until someone counts them, nobody
wonders whether one of them deserves set.
No set override is posed on the real contracts yet, and that is deliberate.
Nothing has been observed that would justify one: Scaleway’s tags come from a
protobuf repeated field, which preserves order, so posing set would be a guess
in the other direction. mise run example:reel against the real account is what
would settle it, and the mechanism is ready for the day it does.
A set comparison sorts rather than building a real set. A real set would call
[a, a, b] and [a, b] equal, and they are not: one carries two tags, the
other one.
What this record does not decide
Whether the write actually produced the requested state. Comparing before writing says what to send; checking afterwards is a different question, and it needs this one answered first.