4.4 KiB
topic, status, date, deciders, reconstructed, extends
| topic | status | date | deciders | reconstructed | extends |
|---|---|---|---|---|---|
| building it | accepted | 2026-10-04 | jochen | false | 02-DECISIONS/0067-genesis-is-a-pivot.md |
200. Genesis pivots to the controller as a container, and the first push hands it to a process
Context
The controller is Go, compiled to one static binary, and is the last of the mesh's own programs a
machine runs from an image (issue 213).
ADR 0188
§1 says a module's own code is bundles, never an image, and §3 that a service bundle is a process the
host runs. The handover exists: a process may name the container it replaces, and the host removes
that container only after the process has stayed up across two checks; two controllers are safe
together for that moment, the second standing by on the controller's consumers and every plan held by
one lock.
What stands in the way is genesis (ADR 0067), which issue 223 found assumes an image and a container at every step from its third: it builds the controller's image, starts a temporary controller from it, publishes it, finds the controller's container in the pivot declaration, and from then on talks to the controller through it. A process's bundle is fetched from the artifact store, and genesis raises the artifact store only after the pivot.
Considered Options
- Raise the artifact store before the pivot, publish the controller's bundle to it, and talk to the controller from the host's side. Rejected for now: it reorders genesis around a store that is itself a module the controller deploys, and rewrites the steps that talk to the controller — a larger change to the one path that is exercised least, to remove a container that exists for minutes.
- Pivot to the controller as a container, as today, and let the first push hand it over to the process, through the handover that already exists. Chosen.
- Keep the controller a container. Rejected: it is the exception to ADR 0188 that every other module's code has now left, and it costs a container runtime on the control machine and a container recreation in the middle of a plan.
Decision
Genesis raises the controller as a container, under the resource the controller's process
replaces, and the first declaration the controller composes for its own machine hands it over.
The container is genesis's own shape, built from the controller's repository, and is recorded on the
control machine exactly as the manifest's replaces names it, so the first apply after the pivot
finds a replacement for it and removes it once the process is up. The controller's manifest declares
only the process; the image form exists for genesis alone and is not a second way to run the
controller on a live mesh.
This is the one bounded exception to ADR 0188 §1: a module's own code in an image, for the minutes between the pivot and the first push, on a mesh being created.
Consequences
- A new mesh ends where a running one is: the controller a process, no controller container.
- Genesis keeps its steps; what changes is that it no longer reads the controller's container from the manifest, and that it records the container under the name the handover expects.
- The controller's repository keeps its image build for genesis and the lab.
- The handover is now on genesis's path too: a process that fails to stay up leaves the genesis container serving, and the apply says so — the same rule as on a live mesh.
How it is checked
The installer's test raises a mesh whose controller manifest is the process form, and asserts that the
container genesis recorded is exactly what the process replaces, so the first apply hands over and
leaves one controller. Live, on the running mesh: after the manifest change is pushed, the control
machine runs the controller as a process and no controller container, and the controller's seat
answers throughout.