Resolve the ingress gap: a route is a grant
ADR 0048 named ingress as an unclosed hole -- nothing said what terminates TLS, how a public name reaches a container, or which tier owned it. Resolving it needed no new concepts, which is why it survived: nobody had applied the rules already written to it. Ingress is not substrate. The control plane does not need a route to start, and no node needs one to reach it -- the node dials out and has no listening control surface. It grants itself a route afterwards, like a bucket. A route is an instantiation edge under ADR 0044. The direction mirrors a database -- the consumer supplies a target and receives a name rather than credentials -- but it is the same edge. The substantive finding is that exposure is three facts at two scopes: name resolution and certificate issuance need to know which node is publicly reachable, and only the proxy mapping is a single machine's business. That is why it belongs to the connectivity context, and why Traefik doing all three on the node is wrong. Which matters beyond tidiness: research 006 counted traefik as one of two modules opening a direct Postgres connection, reading nodes and mesh_ca. That violates 0037, 0045 and 0039 at once, and is why every node permanently holds a credential to the control plane's database. Deriving the config centrally and delivering it as `file` resources removes it, costs zero new host vocabulary, and closes the set 0039 identified -- wireguard was the other. Left open deliberately: the mesh's internal CA is the other thing traefik reads, and it belongs to the link's mutual authority, not to exposure. Conflating the two is what made the gap hard to see. Also fixes an inconsistency from the previous commit: 06 still claimed the virtual host was raised from the bundle. Proposed, not accepted -- for review.
This commit is contained in:
@@ -49,7 +49,7 @@ Ten contexts and one interface, from the skeleton
|
||||
| **record** | the event log every other context integrates through |
|
||||
| **inventory** | nodes, modules, assignments, versions |
|
||||
| **config** | settings, secrets, and deriving them onto nodes |
|
||||
| **connectivity** | overlay, resolution, exposure, filtering, certificates |
|
||||
| **connectivity** | overlay, resolution, exposure, filtering, certificates — it *decides* routes; the proxy on a node applies them ([ADR 0049](../../02-DECISIONS/0049-a-route-is-a-grant.md)) |
|
||||
| **provisioning** | resource grants between modules |
|
||||
| **delivery** | source to artifact to node |
|
||||
| **observability** | health, logs, metrics, alerts |
|
||||
@@ -84,11 +84,16 @@ own.** It needs a PostgreSQL database, an AMQP virtual host, and a bucket — th
|
||||
module needs, granted the same way.
|
||||
|
||||
That is the circularity the tiers exist to resolve rather than hide: the control plane cannot
|
||||
provision its own database, because it is not running yet. So its store and its virtual host are
|
||||
raised from the bundle the host carries, before there is a control plane to ask
|
||||
provision its own database, because it is not running yet. So its **store** is raised from the
|
||||
bundle the host carries, before there is a control plane to ask
|
||||
([ADR 0038](../../02-DECISIONS/0038-a-node-joins-by-linking-first.md),
|
||||
[research 011](../../01-RESEARCH/011-the-module-graph/worked-provider.md)).
|
||||
|
||||
Its virtual host and its bucket are **not** in the bundle — by the time they are wanted there is
|
||||
a control plane to grant them. Whether the bus must come first is
|
||||
[open](07-the-substrate.md#open), and it turns on whether these contexts talk to each other over
|
||||
it.
|
||||
|
||||
## Where it runs
|
||||
|
||||
**On nodes, like anything else.** It is not a place outside the mesh; it is modules the mesh
|
||||
|
||||
@@ -10,6 +10,7 @@ decisions:
|
||||
- 02-DECISIONS/0046-the-installer-fetches-what-it-pins.md
|
||||
- 02-DECISIONS/0047-the-bundle-may-carry-actions-the-link-may-not.md
|
||||
- 02-DECISIONS/0048-the-substrate-is-named.md
|
||||
- 02-DECISIONS/0049-a-route-is-a-grant.md
|
||||
---
|
||||
|
||||
# The substrate
|
||||
@@ -36,6 +37,7 @@ The test, applied:
|
||||
| an object store — **MinIO** | artifacts and blobs it delivers | no — it needs a bucket to hold them | **substrate** |
|
||||
| an image registry — **the OCI registry** | images it delivers to nodes | no — it needs a repository | **substrate** |
|
||||
| an identity provider | only if it delegates authentication | — | **conditional, below** |
|
||||
| ingress — **Traefik** | not to start; only to be reached by name | — it grants itself one afterwards | **not substrate** ([ADR 0049](../../02-DECISIONS/0049-a-route-is-a-grant.md)) |
|
||||
| anything else the mesh hosts | no | — | not substrate |
|
||||
|
||||
**The role and the product are both written**, here and everywhere
|
||||
|
||||
Reference in New Issue
Block a user