Compare commits

..
2 Commits
Author SHA1 Message Date
jschoubben 2344bfb69b ADR 0191: domains are a node's — one internal, one or more public; the roster is the machines 2026-10-03 16:10:38 +02:00
jschoubben ca8a865e73 ADR 0191: the mesh's names are known by where they were composed, not by their suffix
A progressive insight: the rule and its check were stated as a suffix test; the mesh composes both
names of a route and publishes its internal one. The decision is unchanged.
2026-10-03 15:39:07 +02:00
3 changed files with 18 additions and 17 deletions
@@ -11,6 +11,16 @@ supersedes-in-part:
# 191. The mesh's resolver holds only the mesh's own names; a public name resolves publicly # 191. The mesh's resolver holds only the mesh's own names; a public name resolves publicly
> **Progressive insight — 2026-10-03.** The first implementation told the mesh's names from public
> ones by their spelling — a name ending in the mesh suffix — and this record said so: the Decision
> read *"only names under its own suffix"*, and the roster check *"every name the roster carries ends
> in the mesh suffix"*. The mesh needs no such test, nor any per-route name: domains are a node's. A
> node has **one internal domain**, `<node>.internal`, and every route on it is a name under that domain
> (ADR 0151), answered by one wildcard per node; a node has **one or more public domains**, which public
> DNS answers. So the mesh's resolver holds the nodes' internal domains and nothing else, and the roster
> carries the machines and no routed name. Both sentences now say that; what was decided — a public
> name is never given a private answer — is unchanged.
## Context ## Context
**[ADR 0066](0066-public-routing-is-name-agnostic.md) published every routed name into internal **[ADR 0066](0066-public-routing-is-name-agnostic.md) published every routed name into internal
@@ -63,7 +73,8 @@ every public name the mesh serves, is forwarded and resolves publicly. Chosen.
## Decision ## Decision
**The mesh publishes into internal resolution only names under its own suffix.** A machine's name, **The mesh's resolver holds each node's internal domain and nothing else** — `<node>.internal` and
everything under it, at that node's private address. A machine's name,
and through it every `<label>.<node>.internal`, resolve to that machine's private address. **A public and through it every `<label>.<node>.internal`, resolve to that machine's private address. **A public
name is never given a private answer by the mesh**: it resolves through public DNS to the public name is never given a private answer by the mesh**: it resolves through public DNS to the public
address, from members and non-members alike. address, from members and non-members alike.
@@ -93,8 +104,8 @@ reachability — the lab — certifies its internal names and has no public name
**How each is checked:** **How each is checked:**
- **The roster:** the controller's catalogue tests assert that every name the roster carries ends in - **The roster:** the controller's tests assert that the roster names the machines and nothing
the mesh suffix — a routed public name in it fails the build. else — a routed name in it, public or internal, fails the build.
- **On a machine:** asking the machine's resolver for a public name the mesh serves returns the - **On a machine:** asking the machine's resolver for a public name the mesh serves returns the
public address, and asking it for that route's internal name returns the private one. Asked from a public address, and asking it for that route's internal name returns the private one. Asked from a
non-member on a LAN the resolver answers, the first must hold as well. non-member on a LAN the resolver answers, the first must hold as well.
+4 -7
View File
@@ -425,15 +425,15 @@ the cost of not seeing it is inventing a mechanism that already exists.
### The mesh resolves only its own names; a public name resolves publicly ### The mesh resolves only its own names; a public name resolves publicly
**The mesh's resolver holds names under the mesh suffix and nothing else** — every machine, and through **The mesh's resolver holds each node's internal domain and nothing else** — `<node>.internal` and
it every route's internal name `<label>.<node>.internal` everything under it, so every route's internal name `<label>.<node>.internal` with no line of its own
([ADR 0151](../../02-DECISIONS/0151-a-routes-internal-name-is-composed-under-the-node-that-serves-it.md)). ([ADR 0151](../../02-DECISIONS/0151-a-routes-internal-name-is-composed-under-the-node-that-serves-it.md)).
**A public name the mesh serves is never given a private answer**: it is forwarded and resolves to the **A node's public domains — one or more — are never given a private answer**: it is forwarded and resolves to the
public address, from a member and from anything else the resolver answers — a resolver may serve a public address, from a member and from anything else the resolver answers — a resolver may serve a
machine's LAN, and a phone on that LAN must get the address it can reach machine's LAN, and a phone on that LAN must get the address it can reach
([ADR 0191](../../02-DECISIONS/0191-the-meshs-resolver-holds-only-the-meshs-own-names.md)). Inside the ([ADR 0191](../../02-DECISIONS/0191-the-meshs-resolver-holds-only-the-meshs-own-names.md)). Inside the
mesh, a routed service is reached, and certified by the internal authority, under its internal name. mesh, a routed service is reached, and certified by the internal authority, under its internal name.
*Checked by the controller's catalogue tests — every name the roster carries ends in the mesh suffix — *Checked by the controller's tests — the roster names the machines and no routed name —
and on a machine by asking its resolver for a public name the mesh serves: the answer is the public and on a machine by asking its resolver for a public name the mesh serves: the answer is the public
address.* address.*
@@ -1009,9 +1009,6 @@ The list is worth having in one place, because it is most of the argument:
operator's to move between meshes, but the manifest layer still stores it as a literal — so today operator's to move between meshes, but the manifest layer still stores it as a literal — so today
the composition is a per-node override rather than the design. The interpolation that would let a the composition is a per-node override rather than the design. The interpolation that would let a
module carry a label and a node carry the domain, and the mesh join them, does not yet exist. module carry a label and a node carry the domain, and the mesh join them, does not yet exist.
- **Withdrawing public names from internal resolution.** The roster still publishes every routed
public name at its serving node's private address, which ADR 0191 forbids; until the controller
stops, a resolver that answers a LAN hands that LAN's non-members addresses they cannot reach.
## The hub adopts the predecessor's tunnel ## The hub adopts the predecessor's tunnel
@@ -253,13 +253,6 @@ sockets — so seven move here. *Built 2026-10-03:* mesh-sdk #12 (`collectToolsE
(each bundle its own environment), mesh-controller #236 and #237 (the words composed, made the (each bundle its own environment), mesh-controller #236 and #237 (the words composed, made the
account's to read, and named files restarting the runtime), and the seven modules in one change. account's to read, and named files restarting the runtime), and the seven modules in one change.
Building it found issue [211](../../04-ISSUES/211-a-bundle-is-built-before-the-toolchain-it-is-compiled-in/00-report.md). Building it found issue [211](../../04-ISSUES/211-a-bundle-is-built-before-the-toolchain-it-is-compiled-in/00-report.md).
*Proven live 2026-10-03* (mesh-catalog #242, #243): on the one machine that runs them, baserow,
letta, searxng and unifi answer from the runtime with no tool container — each reading its
configuration file as the operator's account — and the runtime serves seventeen tools for six
modules there. confluence, gitlab and jira are assigned nowhere and retire with the predecessor.
Two traps met on the way: a tools bundle whose module declares no `tools` list must say `loads`, or
the composer delivers it nowhere while the build reports success; and a module whose builds are
pinned to an old commit is left out of a merge's plan and must be built from `main` by hand.
## WP4c — The module's own long-running code moves ## WP4c — The module's own long-running code moves