ADR 0200: genesis pivots to the controller as a container, and the first push hands it to a process #346
+78
@@ -0,0 +1,78 @@
|
|||||||
|
---
|
||||||
|
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)
|
||||||
@@ -320,6 +320,7 @@ python3 00-META/checks/index.py fail if stale
|
|||||||
- **0111** — [A build source is on the mesh's git seat, or it is an external repository](0111-a-build-source-is-on-the-git-seat-or-external.md)
|
- **0111** — [A build source is on the mesh's git seat, or it is an external repository](0111-a-build-source-is-on-the-git-seat-or-external.md)
|
||||||
- **0149** — [The live mesh is the test bed](0149-the-live-mesh-is-the-test-bed.md)
|
- **0149** — [The live mesh is the test bed](0149-the-live-mesh-is-the-test-bed.md)
|
||||||
- **0174** — [A node varies a module through settings and kept regions, never through an edit](0174-a-node-varies-a-module-through-settings-and-kept-regions-never-an-edit.md)
|
- **0174** — [A node varies a module through settings and kept regions, never through an edit](0174-a-node-varies-a-module-through-settings-and-kept-regions-never-an-edit.md)
|
||||||
|
- **0200** — [Genesis pivots to the controller as a container, and the first push hands it to a process](0200-genesis-pivots-to-the-controller-as-a-container-and-the-first-push-hands-it-to-a-process.md)
|
||||||
|
|
||||||
### How it is checked
|
### How it is checked
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
status: open
|
status: located
|
||||||
opened: 2026-10-04
|
opened: 2026-10-04
|
||||||
located-in:
|
located-in:
|
||||||
- mesh-host
|
- mesh-host
|
||||||
@@ -40,3 +40,9 @@ Until it is settled, the change of the controller's manifest (mesh-controller#25
|
|||||||
handover itself is built and merged (mesh-host#86); the controller's half (mesh-controller#252) waits
|
handover itself is built and merged (mesh-host#86); the controller's half (mesh-controller#252) waits
|
||||||
on the operator. **How it is checked:** the installer's test raises a mesh whose controller manifest
|
on the operator. **How it is checked:** the installer's test raises a mesh whose controller manifest
|
||||||
is the process form, and the controller answers its seat's verbs at the end.
|
is the process form, and the controller answers its seat's verbs at the end.
|
||||||
|
|
||||||
|
## Decided (2026-10-04)
|
||||||
|
|
||||||
|
Option 2, [ADR 0200](../../02-DECISIONS/0200-genesis-pivots-to-the-controller-as-a-container-and-the-first-push-hands-it-to-a-process.md):
|
||||||
|
genesis pivots to the controller as a container recorded under the name the process `replaces`, and
|
||||||
|
the first push hands it over.
|
||||||
|
|||||||
Reference in New Issue
Block a user