Files
hq/02-DECISIONS/0002-managed-files-are-generated-never-edited.md
T
jschoubben e1febe8e0f Renumber the records 1 to 23
The consolidation left a sparse sequence -- 1, 4, 6, 7, 9, 10, 12, 15, 16, 18,
19, 25, 34, 35, 36, 37, 40, 42, 44, 45, 48, 49, 58 -- where the gaps were only
the archaeology of what used to be there.

Renumbered contiguously. Renames run in ascending order, so every target number
is already free and no two files ever collide.

The reference rewrite is one simultaneous pass rather than a sequence of
replacements. Numbers moved into slots other numbers were vacating -- the node
host went 37 to 16 while the lab went 16 to 9 -- so replacing one at a time
would have cascaded and silently pointed things at the wrong record.

Seven plain-text references survived the merges as prose rather than links,
naming records that no longer existed: the enrolment token, the link boundary,
what a declaration is, reachability, the repository structure. Each mapped to
the consolidated record that now holds it.

Verified rather than assumed: every [ADR NNNN](path) link now has matching text
and target, checked across the whole repository, and the checker passes.

Frontmatter `consolidates:` lists dropped -- they named records that are gone,
and each consolidated record already says in prose what it absorbed.
2026-08-28 23:28:34 +02:00

3.0 KiB

status, date, deciders, reconstructed
status date deciders reconstructed
accepted 2026-04-03 jochen true

2. Managed files are generated onto nodes and never edited there

Reconstructed after the fact from the evidence cited below.

Context

ADR 0021 put every binding in the mesh database. But the things that consume those bindings — environment files, service definitions, daemon configuration, firewall rules — are files on a node's disk, because that is what the software reading them requires.

So the same value exists twice: authoritatively in the database, and materialised in a file. Any edit to the file is a change to a copy. Before this decision, environment values could be pushed from a node back into the database, which made the direction ambiguous in both directions at once.

Considered options

  1. Bidirectional sync — a node's edits flow back to the database. Rejected, and removed. Two writers and no arbiter: whichever synced last wins, and neither is authority.
  2. Files are authoritative; the database is a cache of them. Rejected — it inverts ADR 0003 and returns to state that cannot be reconciled across nodes.
  3. Strictly one-directional: the database is written, files are generated. Chosen.

Decision

Every managed file is derived. A synchroniser regenerates it from the mesh database whenever the underlying values change. The write path is the mesh tool that owns the value; the file is an output.

This applies to generated environment files, service definitions, managed configuration, and anything else a synchroniser lists as its own.

An edit to a managed file survives until the next synchronisation and is then overwritten, without a warning, taking whatever it was fixing with it.

Consequences

  • A file edited on a node is a bug with a delay on it. This is now one of the mesh's core values, and it is a consequence of this decision rather than a stance taken independently.
  • To change a value you must know which tool owns it. That is a real cost, paid every time, and the reason the mesh provides a way to ask whether a given file is managed.
  • Debugging by editing a file no longer works, and fails in the most confusing way available: it works, and then stops working later for no locally visible reason.
  • Recovery is cheap. A node's entire managed surface can be regenerated from the database.
  • Values resolve by precedence — database override, then existing file value, then generated, then manifest default — which means an unset override does not clobber a generated password. The subtlety is real and has caused its own confusion.

References

  • Extract hal/env-sync module, remove syncEnvToDb, 2026-04-03 — the commit that removed the node-to-database direction.
  • Knowledge base: conventions/no-direct-file-mutation, provisioning (resolution priority).
  • Regeneration gaps: troubleshooting/changed-manifest-default-not-rerendered, troubleshooting/config-removed-from-manifest-not-pruned.