Files
mesh-controller/internal/inventory/migrations/0016-the-mesh-assigns-the-port.sql
jschoubben 1f5b70a995 The mesh assigns the port, and a module says it once
novox/hq ADR 0038. A module cannot choose a port: it is written once and
assigned anywhere, so any number it picks is a guess about a machine it
has never seen. A database module met the mesh's own store on 5432 and
was told, by a container runtime three layers down, that the port was
already allocated.

The number used to appear three times in every module — the rule set,
what a consumer is told, and what the runtime publishes — agreeing only
because one person wrote all three. Now it appears once, in `listens`,
and the other two are derived: the container publishes `20000:5432`, the
consumer is told 20000, and the rule set opens 20000.

An assignment is made once and kept, as a credential is. A port that
moved on every declaration would restart both ends each time and hand a
consumer a number that was true when it was read.

Ports the protocol fixes — mail on 25, submission on 587, DNS on 53 —
say so, and are then claims: one holder per machine, and the second is
refused by name at assignment. That is the mechanism the mesh already
has for what is singular on a machine, pointed at ports.

A mapping written the long way is left exactly as it is. Some things
must be pinned by hand, and quietly overruling somebody who wrote both
halves would be worse than not offering the short form.

Still open, and known: the substrate is not a module, so the mesh has
never heard of its own store and cannot yet assign around it. That is
what 028 will still be about after this.
2026-09-01 17:52:53 +02:00

34 lines
1.6 KiB
SQL

-- Which port a machine uses for what a module needs reachable.
--
-- novox/hq ADR 0038. A module cannot choose this: it is written once and assigned anywhere, so any
-- number it picks is a guess about a machine it has never seen. Two modules guessing the same one
-- is not a mistake either of them made -- it is a database module meeting the mesh's own store and
-- being told, by a container runtime three layers down, that the port is already allocated.
--
-- **Made once and kept**, exactly as a credential is. A port that moved on every declaration would
-- restart both ends each time, and would hand a consumer a number that was true when it was read.
create table port_assignment (
node uuid not null references node(id) on delete cascade,
module text not null references module(name) on delete cascade,
-- The port the software itself uses -- what a module writes down, and the only part it knows.
wanted integer not null,
-- What the machine publishes it on. The same as `wanted` when the protocol fixes it.
machine integer not null,
-- Whether the protocol fixed it. Kept rather than derived: *this is 25 because it must be*
-- and *this is 25 because it was free* are different facts, and only the first refuses a
-- second holder.
fixed boolean not null default false,
assigned_at timestamptz not null default now(),
primary key (node, module, wanted),
-- **One machine port, one holder.** The constraint is the point: a second module cannot be
-- given a port the first has, and finding that out here is finding it out at assignment
-- rather than at apply.
unique (node, machine)
);