Reconcile: adopt initialization's consolidated HQ as canonical, re-home this session's new work #24
@@ -96,6 +96,43 @@ grants clients, a mail server grants mailboxes. It is a facet, not a kind.
|
||||
**A module may also declare what it claims**, because some things cannot coexist and that is a
|
||||
fact about the module rather than about a particular node. What that means precisely is below.
|
||||
|
||||
### An edge has two directions, and only one of them is built
|
||||
|
||||
*Written 2026-08-29, from building it. The row above already says a consumer **supplies a target
|
||||
and receives a name**; what it did not say is that those are two separate mechanisms, and that
|
||||
having one without the other is what forced two modules outside the system entirely.*
|
||||
|
||||
| direction | the consumer says | who needs it |
|
||||
|---|---|---|
|
||||
| **contribution** | *publish me at this name, on this port* | the proxy, the DNS server, a firewall |
|
||||
| **binding** | *and give me back a credential to it* | the database, the object store, the identity provider |
|
||||
|
||||
**Contribution is built.** A module declares what it contributes to a requirement; the control
|
||||
plane collects every contribution on a node and writes them to a path the provider named, as a
|
||||
file, in the mesh's own shape. **Contributing to something is requiring it** — asking to be
|
||||
published means a publisher must exist, and a module that had to say both would eventually say
|
||||
one, with the failure appearing as a machine where nothing serves the route.
|
||||
|
||||
**The control plane does not know what a reverse proxy is**, and does not write one's
|
||||
configuration. It delivers the facts; the module turns them into whatever it runs. That boundary
|
||||
is what makes swapping the proxy cost nothing in any module that publishes through it, and it is
|
||||
[the same separation](0001-mesh-brokers-nodes-host-agents-think.md) that keeps third-party
|
||||
software *on* the mesh rather than *of* it. It also costs the host nothing: a received file is a
|
||||
file, which was checked by putting the control plane's output through the host's own parser rather
|
||||
than by asserting it.
|
||||
|
||||
**Binding is not built**, and it is the larger half. It needs a secret to exist, be stored, be
|
||||
delivered to one node and not the others, and be rotated with every holder informed — which is
|
||||
[the invariant set](0001-mesh-brokers-nodes-host-agents-think.md) that was found violated three
|
||||
ways at once, and the reason it is not something to add in passing.
|
||||
|
||||
**What the absence cost, measured.** Exactly two modules opened a direct connection to the control
|
||||
plane's database — the proxy and the VPN — and they are the reason every node permanently holds a
|
||||
credential to it. Both were doing by hand what this edge is for. The VPN's half is closed by being
|
||||
[a module whose files are computed](../03-DESIGN/01-to-be/08-connectivity.md); the proxy's is
|
||||
closed by contribution. **Neither needed a new kind of thing, and both had been outside the model
|
||||
for as long as there was one.**
|
||||
|
||||
### Why the build edge is a different kind
|
||||
|
||||
It is fixed inside an artifact rather than negotiated when something runs, and **its only remedy
|
||||
|
||||
@@ -99,6 +99,18 @@ back in by the names, which needed addresses only WireGuard hands out — and no
|
||||
Running two VPNs is not always wrong; being *the* one the mesh runs over is singular. So it is a
|
||||
claim, and the collision is refused by name.
|
||||
|
||||
**And the proxy's half, which was the other module reaching into the database.** A web application
|
||||
requiring a reverse proxy has to say *which name, which port*, and there was nowhere to put it —
|
||||
`requires` says a thing must exist and never said what to do with it. A module now contributes to
|
||||
a requirement, the control plane collects every contribution on a node, and the provider is given
|
||||
them as a file at a path it named. It reloads when that file changes, by the same `restart-on` the
|
||||
private network needed when a peer list changed under a running interface.
|
||||
|
||||
**The proxy's configuration is not written by the mesh.** It is given the facts and turns them
|
||||
into whatever it runs, which is why swapping Traefik for something else touches nothing that
|
||||
publishes through it. See [ADR 0009](../../02-DECISIONS/0009-modules-and-the-graph.md) for the
|
||||
other direction — handing a credential *back* — which is the larger half and is not built.
|
||||
|
||||
**What is still not a module, and why that is correct.** The host needs none of this. It has an
|
||||
address and a route before the mesh exists — that is the machine's own networking — and the
|
||||
broker's address is carried in the token rather than resolved
|
||||
|
||||
Reference in New Issue
Block a user