Files
hq/04-ISSUES/104-reconcile-applies-a-stale-declaration-and-refuses-nothing/00-report.md

52 lines
2.8 KiB
Markdown

---
status: resolved
opened: 2026-09-23
located-in: [mesh-host cmd/mesh-host]
fixed-by: mesh-host — a declaration for the other mode is refused, every file is refused once the mesh has spoken, and an apply previews what it would change
amended-design:
---
# 104 — `reconcile` applies the declaration the host was installed with, and refuses nothing
## What was observed
The control-node, 2026-09-23, adopted, twelve modules assigned, two services already cut over.
Chasing why an assignment had not finished, an operator ran the host's own `reconcile` command by
hand.
It did not reconcile the node against the controller's declaration. It applied **the declaration
the host carries** — the genesis bundle: foundation only, *converged*. In order: it recreated the
store, tried to recreate the broker and failed on a held port, wrote the converged base filter to
disk, enabled and started its service, and stopped at the first failing action with "nothing after
it was attempted".
The base filter is the ruleset [ADR 0100](../../02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md)
exists to keep off an adopted node: input policy drop, three ports allowed. It closed the machine
to the internet for about forty-five minutes — every site, the forge's path to its database — and
was removed by hand.
Nothing about the command said any of this would happen. It printed what it did after it did it.
The node's mode was known to the host — it reports "adopted" in every report — and the
declaration it applied said "converged", and no comparison was made.
## Why it matters beyond this instance
The host has two declarations and one command that does not say which it means. The bundle is
right at genesis and stale a minute later; on an adopted node it is actively dangerous, because it
is a converged declaration for a machine that is not converged. A command an operator would
reasonably reach for under pressure — "make the machine match" — is the one that must not be run.
The operator error here was real and is recorded as such. But a design that turns "I ran the
obvious command" into a closed machine has a hole of its own, and the runbook's line "never bypass
the controller" was standing in for a refusal the host should make itself.
## Open questions
- Should `reconcile` refuse outright when the declaration it carries is older than the one the
controller last sent, or says a different mode than the node reports — naming both?
- Should a converged declaration be refused on an adopted node at the point of application,
whatever command delivered it, since the mode is a fact the host already knows?
- Should the host preview before applying from a file — the way `converge` previews — and stop at
the first action *before* running it rather than after?
- Does the bundle need to remain applicable after genesis at all, or should genesis consume it?