Files
hq/04-ISSUES/161-an-assignment-does-not-record-which-provider-answers-it/00-report.md
T
jschoubben 39340fcd76 Issue 161: an assignment does not record which provider answers it
ADR 0110 decided each assignment records where its requirements are answered
from; the control plane keeps only a per-machine pin (none recorded) and
resolves every requirement implicitly. Harmless with one provider; a second
one silently moves consumers' data.
2026-09-30 11:54:31 +02:00

3.0 KiB

status, opened, located-in, fixed-by, amended-design
status opened located-in fixed-by amended-design
open 2026-09-30
mesh-controller cmd/mesh-controller/modules.go (assign takes no provider; pin is a separate, per-machine command)
mesh-controller internal/inventory (provision_pin keyed by (node, name))

161 — An assignment does not record which provider answers it

What was observed

Planning ace's modules that need a database (baserow, letta, n8n, and the apps using ace's predecessor postgres). The operator's model — and ADR 0110's — is that an assignment states where each of its requirements is answered from: gitea's assignment on novox says its postgres-database comes from novox; an app assigned to ace says whether its database comes from ace or from novox.

The mesh holds no such statement for any assignment. Read on novox (2026-09-30):

select … from provision_pin;   -- 0 rows

Every requirement in the mesh resolves implicitly, each time, by ADR 0084's order (a pin, then the provider on the consumer's own node, then the only provider).

What was decided, and what exists

ADR 0110:

Where several remain and none is local, a person chooses when the module is assigned. Assignment lists the candidates, with the holder of a seat that delivers the provision suggested first, and records the answer on the assignment as its pin. Without an answer the module is not assigned.

What the control plane implements:

decided implemented
the answer is recorded on the assignment provision_pin is keyed (node, name) — one answer per machine per provision, shared by every module on it
chosen at assignment assign <node> <module> takes no provider; pin <node> <provision> <from-node> is a separate command
an assignment may be answered from its own machine (gitea ← novox) pin refuses a machine pinning to itself ("does not need saying")
every assignment has an answer none recorded; resolution guesses the same answer every time

Consequence

Nothing is wrong today — with one postgres provider, every guess is the intended answer. But the answer is not a fact anyone stated, so:

  • it changes silently the day a second provider appears (e.g. a postgres assigned on ace): every unpinned consumer re-resolves — a consumer on ace moves from novox's database to an empty one on ace at the next push, which is data a module stops seeing without anything saying so;
  • two modules on one machine cannot take one provision from different providers;
  • a person reading an assignment cannot see where its data lives.

What would be right

ADR 0110 as written: assign records, per requirement, the node that answers it (its own node included), offering the candidates and refusing an assignment without an answer where several exist; the per-machine provision_pin becomes a per-assignment record, with existing assignments backfilled from what they resolve to now so nothing moves.