diff --git a/04-ISSUES/140-an-endpoints-reach-is-not-declared/00-report.md b/04-ISSUES/140-an-endpoints-reach-is-not-declared/00-report.md index 0706b36..2192642 100644 --- a/04-ISSUES/140-an-endpoints-reach-is-not-declared/00-report.md +++ b/04-ISSUES/140-an-endpoints-reach-is-not-declared/00-report.md @@ -1,5 +1,5 @@ --- -status: located +status: resolved opened: 2026-09-28 located-in: - mesh-controller internal/catalogue/manifest.go @@ -7,7 +7,7 @@ located-in: - mesh-controller internal/catalogue/declaration.go - mesh-controller examples/route-proxy - mesh-catalog (every routed module manifest) -fixed-by: +fixed-by: mesh-controller bdf965d (a module names its endpoints) and c68d3a7 (an assignment configures an endpoint as one thing) — the filter, the proxy's names and both authorities now read one statement amended-design: 03-DESIGN/01-to-be/08-connectivity.md --- diff --git a/04-ISSUES/140-an-endpoints-reach-is-not-declared/01-resolution.md b/04-ISSUES/140-an-endpoints-reach-is-not-declared/01-resolution.md new file mode 100644 index 0000000..0472ada --- /dev/null +++ b/04-ISSUES/140-an-endpoints-reach-is-not-declared/01-resolution.md @@ -0,0 +1,47 @@ +# Resolution + +*2026-09-29.* + +**Built, and this record did not say so.** The issue was written on 2026-09-28 and answered the same +week by two commits in `mesh-controller`; nothing came back to close it, so the mesh's own account of +itself said for a day that reach was declared nowhere while the code read it in three places. + +- `bdf965d` — *a module names its endpoints, and a route names the one it serves*. `listens[].name` + is the endpoint; a route contribution names the endpoint rather than repeating a port. +- `c68d3a7` — *an assignment configures an endpoint as one thing*. The `endpoints` settings key, per + node, by endpoint name: `{"endpoints": {"ssh": {"port": 20134, "reach": "public"}}}` — port, label + and reach in one block, which is what [ADR 0138](../../02-DECISIONS/0138-an-assignment-binds-an-endpoint-and-says-how-far-it-reaches.md) + asked for and what [ADR 0046](../../02-DECISIONS/0046-a-module-configuration-is-its-assignments-not-its-manifest.md) + said configuration is. + +## The three readers, which is what the issue was about + +The complaint was that the per-node source override had exactly one caller. It now has three, and +they are the three mechanisms reach was decided to settle at once: + +| reader | what it does with it | +|---|---| +| the filter | `Reaches` turns each endpoint's reach into the rule for its machine port | +| the proxy's names | `composeName` composes the public name, the internal name, or both — and a name nobody asked for is not composed | +| the authorities | the proxy certifies only names it was actually given, each from its own authority, through two host policies rather than one | + +**A routed endpoint keeps the manifest's port**, which is ADR 0138's own insight and older than it +([ADR 0045](../../02-DECISIONS/0045-a-machine-firewall-is-the-sum-of-what-it-listens-on.md)): the +proxy is how it is reached, so `public` there asks for a public *name*, not an open port. + +**An endpoint that is not routed is reached and never named.** Git over ssh is that case — the one +the issue said the model could not express — and it is now the ordinary one. + +## How it is checked + +`internal/catalogue/endpoints_setting_test.go`: a block says port, label and reach; a block may say +only a reach; a name the module does not declare is refused; a reach outside the four values is +refused; and saying the same thing twice — once in the block, once through the older per-port keys — +is refused rather than resolved by whichever is read last. The proxy's half is `policy_test.go` and +`authority_test.go`: a name the mesh did not send is not certified, by either authority. + +## What is left, and it is not this + +The older keys (`ports`, `expose`, and reach keyed by port) still work beside the block. They are +what the block replaces, and retiring them is its own small change — not a gap in what reach can +say.