From d1b5210d83a969397c5fcfedf573f473ded4f3a2 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 17 Sep 2026 22:29:25 +0200 Subject: [PATCH] =?UTF-8?q?Issue=20059=20=E2=80=94=20the=20broker=20creden?= =?UTF-8?q?tial=20names=20the=20hub,=20not=20the=20broker's=20node?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Findings of an adversarial review of the 055 fix: hub!=broker conflated, membership tested as has-address, silent staleness, portless silent fallback, two hubs unrefused. One review claim recorded as disputed against live wire measurements. https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx --- .../00-report.md | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 04-ISSUES/059-the-broker-credential-names-the-hub-not-the-broker/00-report.md diff --git a/04-ISSUES/059-the-broker-credential-names-the-hub-not-the-broker/00-report.md b/04-ISSUES/059-the-broker-credential-names-the-hub-not-the-broker/00-report.md new file mode 100644 index 0000000..e10cefb --- /dev/null +++ b/04-ISSUES/059-the-broker-credential-names-the-hub-not-the-broker/00-report.md @@ -0,0 +1,58 @@ +--- +status: located +opened: 2026-09-17 +located-in: + - mesh-controller +fixed-by: +amended-design: +--- + +# 059 — The broker credential names the hub, not the node holding the broker + +## Symptom + +An adversarial review of the issue-055 fix (`brokerReachableAt`) found the cross-node broker +address is computed from the wrong facts. No live failure yet — every current mesh has the broker +on the hub — but each is a wrong invariant that fails exactly when the topology stops being the +simple one: + +1. **The helper returns the hub's overlay name for any on-overlay node, but nothing ties the + broker to the hub.** The broker lives wherever the module holding the `mesh-broker` seat is + assigned; hub-ness is a separate operator declaration — and the overlay design actively pushes + them apart (the hub must be publicly dialable; a natural topology is hub-on-a-relay, + foundation at home). In that mesh every issued credential dials a relay where no broker + listens. +2. **"On the overlay" is tested as "has an overlay address."** The codebase itself defines + membership as *resolved the networking module* — "not 'has an address'… it is what resolved + the module" — and excludes address-only nodes from every peer list. A node placed but not yet + given networking is sealed an overlay URL it cannot route. +3. **A credential issued before `overlay place` keeps the public URL for ever**, and nothing says + so; the remedy (re-issue + push) works but is undocumented. The sibling of issue 057's + ordering gap. +4. **A portless `MESH_BROKER_ADDRESS` silently disables the fix** — `SplitHostPort` fails and the + helper falls back to the public address without a word. The port should default to 5671, or + the address should be refused at genesis. +5. **Two hubs are never refused.** A second `overlay place --hub` leaves both flagged; the pick is + then order-dependent. `ErrNotOneHub` exists and nothing returns it. + +One review claim is recorded here as **disputed**: that the from-mesh forward rule could not have +been the 055 failure because the broker port is opened from anywhere. The live measurements during +055 (nftables counters; a cross-node probe of the amqps port flipping CLOSED→OPEN exactly when the +broker module's `listens` gained the port) say the forward chain was the gate for published +container ports. The code-reading and the wire disagree; the wire was measured. + +## Why it matters + +The 055 fix is correct for every mesh that exists, and wrong by construction for the first mesh +whose hub is not its control-node — which the overlay design itself recommends for a home mesh +behind NAT. Credentials are sealed and long-lived, so the failure arrives long after the decision +that caused it, on the first module pushed to a node that joined the reshaped mesh. + +## Open questions + +- Should the broker address resolve from the `mesh-broker` seat's assignment (falling back to the + hub only when nothing holds the seat — genesis), and should membership use the same + resolved-networking test the peer graph uses? +- Where does the stale-credential remedy live: a warning from `overlay place`, an automatic + re-issue at the next push, or documentation? +- Should a second `--hub` be refused outright (`ErrNotOneHub` finally thrown)?