Files
hq/04-ISSUES/092-genesis-publishes-to-a-registry-the-runtime-does-not-trust/00-report.md
T

4.1 KiB

status, opened, located-in, fixed-by, amended-design
status opened located-in fixed-by amended-design
open 2026-09-22

092 — Genesis publishes to a registry the container runtime does not yet trust

What was observed

On the first real genesis, on a machine in use, 2026-09-22.

Genesis raises the mesh's registry, then pushes the control plane's image into it so that the control plane can be reinstalled as an ordinary module pinned to a digest. The push failed:

the container runtime would not push <address>/mesh-controller:genesis:
Get "https://<address>/v2/": http: server gave HTTP response to HTTPS client

The mesh's registry speaks plain HTTP, deliberately: every path to it is inside the private network's encryption (ADR 0082). The container runtime refuses plain HTTP to a registry it has not been told to trust, and the thing that tells it is the networking module, which genesis installs at step 16 — six steps after the push.

So genesis cannot complete on a machine whose runtime was not already told, out of band, to trust the address the mesh is about to serve its own images from.

The lab never sees it: its base image writes that trust into the runtime's configuration before any bed starts. That is the same blind spot issue 084 names from the other side.

Worked around by hand on the machine: the mesh's registry added to the runtime's trusted list, keeping every key already there, and the runtime reloaded rather than restarted, so nothing it was running stopped (ADR 0102). Genesis then continued.

Then it happened twice more, on the same machine, within the hour:

  • By name, not only by address. Once the mesh's builder built a module, it pushed the result to the registry by its mesh name and port. The runtime trusted the numeric address genesis was given and nothing else, so the push failed the same way. The trust has to cover every name the mesh will use for that registry, not the one the operator typed.
  • The mesh's own trust names the wrong port. The networking module writes the registry's trust into the runtime's configuration — correctly written into it, keeping what was there (ADR 0102) — and the value it wrote names the registry's default port while the node was given another. So the mesh trusts an address its registry does not serve. That is the same fault as issue 088: an address with a port in it that does not follow the node's setting.

Why it matters beyond this instance

Genesis is meant to take a machine from nothing to a mesh without anyone editing files on it. It has one step that cannot work unless somebody already did. Every future first node meets this, not only a node adopted beside a predecessor, and the order is what makes it so: the trust the push needs is installed after the push.

It also breaks the rule that each step says what it needs before it changes anything. Preflight checks that the bundle's registries are reachable. It does not check that the runtime will speak to the one the mesh is about to raise.

Open questions

  • Should genesis write the runtime's trust itself, before the publish step, the way it writes everything else the foundation needs — and hand it to the networking module afterwards?
  • Or should the push not need it: a registry served over TLS from the start, or an image loaded rather than pushed?
  • Should preflight refuse a genesis whose runtime does not trust the registry it is being given, rather than letting it fail at step 10?
  • Whatever writes that trust, which names of the registry must it cover: the address given, the mesh name, loopback? The builder used the mesh name without being told to.
  • Should the registry's trust be derived from what the registry module serves on that node, rather than from its default port?