--- status: accepted date: 2026-04-03 deciders: jochen reconstructed: true --- # 4. Managed files are generated onto nodes and never edited there > Reconstructed after the fact from the evidence cited below. ## Context [ADR 0003](0003-the-mesh-database-is-the-source-of-truth.md) 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`.