Files
hq/02-DECISIONS/0200-genesis-pivots-to-the-controller-as-a-container-and-the-first-push-hands-it-to-a-process.md
T

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

  1. 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.
  2. 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.
  3. 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.

References

  • Issue 213, issue 223
  • mesh-host#86 (the handover), mesh-controller#252 (two controllers safe together), mesh-controller#253 (the controller's manifest as a process)