--- status: open opened: 2026-09-23 located-in: [] fixed-by: amended-design: --- # 098 — Taking a module replaces a configuration nobody compared, and the part that was the installation's is gone ## What was observed Preparing the second module's cutover on the control-node, 2026-09-23. Found by reading, before anything was taken — which is the only reason it is a report and not an incident. The module declares the service's whole configuration file, at the same path the machine already has one. On an adopted node that file is *found*, so it is held until the module is taken, and the host records the original first — all exactly as [ADR 0100](../../02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md) says. The two files are not the same. The machine's says, in its own words, that packages under one private scope are **stored locally and never proxied upstream**; every other package is proxied. The catalogue's file has the second rule and not the first. Taking the module would therefore replace a policy statement with its absence: the private packages would start resolving through a public upstream that has never heard of them. Nothing in the cutover says so. `take` replaces the held file and reports that it did. There is no step between "held" and "replaced" at which the two contents are put side by side, and the operator is not asked. The whole-node preview names *which* held files a flip will replace; it does not say **how they differ**, and the per-module cutover — the step that actually does it — previews nothing at all. The original is kept, so this is recoverable. It is not detectable: the service starts, answers, and serves the wrong thing. ## Why it matters beyond this instance A configuration file is where an installation keeps what is true about *it* — which packages are private, which realm is trusted, which paths are exceptions. A catalogue module is, correctly, the same for every mesh. Declaring the file whole makes the second overwrite the first, and the migration is precisely when every such file changes hands. There is no mechanism to carry the difference. A module's file content is a fixed string: no setting is substituted into it, and the mesh's way of writing *into* a file it does not own whole ([ADR 0102](../../02-DECISIONS/0102-the-mesh-writes-into-a-shared-file-never-over-it.md)) reads and writes JSON, so a service configured in any other language cannot use it. The two remaining options are both wrong: put one installation's private scope into a catalogue every mesh shares, or accept the loss. The silence is the worse half. The mesh's rule is that each step says what it changes before it changes it; here a step changes the meaning of a running service and says only that a file was written. ## Open questions - Should `take` refuse, or ask, when the held file it would replace differs from what it declares — and show the difference? What makes a difference acceptable enough to pass silently? - Should a module be able to declare a configuration **partially**, in the service's own language, and if so which languages must the host speak — or should such a file never be declared whole, and always merged? - Where does an installation's own policy live, if not in the catalogue and not in the file the catalogue overwrites? A settings layer substituted into content would answer it; nothing substitutes settings into content today. - Is the kept original enough of an answer, given nothing restores it and nothing points at it when the service starts behaving differently?