Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
743051efe7 | ||
|
|
e8470057aa | ||
|
|
39340fcd76 |
@@ -0,0 +1,63 @@
|
||||
---
|
||||
status: open
|
||||
opened: 2026-09-30
|
||||
located-in:
|
||||
- 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))
|
||||
fixed-by:
|
||||
amended-design:
|
||||
---
|
||||
|
||||
# 163 — 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](../../02-DECISIONS/0110-a-seat-is-a-module-assignment-from-a-closed-set.md):
|
||||
|
||||
> 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.
|
||||
Reference in New Issue
Block a user