79 lines
4.4 KiB
Markdown
79 lines
4.4 KiB
Markdown
---
|
|
topic: building it
|
|
status: accepted
|
|
date: 2026-10-04
|
|
deciders: jochen
|
|
reconstructed: false
|
|
extends: 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](../04-ISSUES/213-the-controller-is-a-go-program-run-in-a-container/00-report.md)).
|
|
[ADR 0188](0188-a-modules-own-code-is-bundles-in-any-language-and-a-tools-bundle-speaks-mcp-to-the-runtime.md)
|
|
§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](0067-genesis-is-a-pivot.md)), which
|
|
[issue 223](../04-ISSUES/223-a-new-mesh-installs-its-controller-as-a-container/00-report.md) 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](../04-ISSUES/213-the-controller-is-a-go-program-run-in-a-container/00-report.md),
|
|
[issue 223](../04-ISSUES/223-a-new-mesh-installs-its-controller-as-a-container/00-report.md)
|
|
- mesh-host#86 (the handover), mesh-controller#252 (two controllers safe together),
|
|
mesh-controller#253 (the controller's manifest as a process)
|