Files
jschoubben 402b798ab6 Accept ADR 0038; close issue 091
The decision (the mesh assigns a container's machine-side port; a module
says only what it needs) was proposed 2026-09-01, and the machinery
already implements it in full -- internal/inventory/ports.go's PortFor,
declaration.go's publishedOn. What was missing was the catalogue actually
complying: 14 of 46 modules baked a machine-side number into their own
manifest anyway. mesh-catalog PR fixes 11 of them (the two defensible
kinds -- foundation, protocol-fixed -- are left alone, per the issue's own
categories). Accepting the decision now that it's actually enforced, and
closing the issue it was blocking.

Checks pass.
2026-09-24 15:52:45 +02:00

3.0 KiB

status, opened, located-in, fixed-by, amended-design
status opened located-in fixed-by amended-design
resolved 2026-09-22
mesh-catalog
mesh-catalog — the 11 not-defensible modules (de-spiegel, gitea, hello-web, mailu, mssql, n8n, novox.be, only-office, photos, photos-eef, photos-filip) had their hardcoded machine-side port mapping stripped to the bare software port, letting ADR 0038's existing assignment machinery (internal/inventory/ports.go's PortFor, declaration.go's publishedOn) assign it as designed. postgres, lavinmq, distribution (foundation, genesis-rewritten) and unifi (protocol-fixed) were left as-is — the two defensible kinds this report names.

091 — A module definition carries a machine port

What was observed

Measured across the catalogue, 2026-09-22, while planning the migration of a control-node: 14 of 46 modules with containers fix the machine side of a published port in the module definition; 32 leave it to the node.

Four kinds turned up, and only two of them are defensible:

  • The foundation's own — the store, the bus, the broker's management port, the registry. These are rewritten at genesis and are now per-node settings (ADR 0100), so the number in the manifest is a default, not a claim.
  • Ports a protocol fixes — device discovery and relay ports that clients find by number. The machine has no freedom here, and the manifest is the right place to say so.
  • A predecessor's host ports, copied in during conversion — a site on one number, a document editor on another, an object browser on a third. These are facts about one machine that were written into a definition meant for any machine.
  • A demonstration module serving on a memorable number.

Why it matters beyond this instance

The mesh's rule is that a module says what it listens on and the node decides what the machine publishes; that is what lets the same module run on two machines, and what lets a node adopted beside a predecessor move a port out of the way. A machine port in a definition is that rule broken quietly: it works until two nodes want the module, or until one node already has something on that number.

It is not fatal today — a node's ports setting overrides the mapping's machine side — but the default is in the wrong place, and nothing says so when a module is written or converted.

The conversion backlog is the moment this gets decided for the rest of the modules, so it is worth answering before the remaining ones are written.

Open questions

  • Should a module be refused when it fixes a machine port without saying why — with an explicit "this protocol needs this number" — so the two defensible cases stay and the copied ones do not?
  • Is the right default that every published port is machine-assigned unless the module declares the number is part of the protocol?
  • What should a converted module do with the predecessor's host port: drop it, or record it as the node's setting on the machine being migrated, which is where it is actually true?