mesh-connectivity — Trusted nodes connect across NAT through proven transports, and every surface says which path
A connectivity decision record, a relayed path through a trusted hub, a signed bootstrap manifest on Pages, and a NAT matrix in the mesh lab.
BLOCKED 0 of 4 issues done
- ready
- 0
- blocked
- 4
- active
- 0
- verify
- 0
- done
- 0
- cancelled
- 0
Problem
Master links nodes over multicast on one segment and through rendezvous hubs that must be directly reachable; docs/MESH.md states 'no NAT traversal'. The owner asked four times (10-12, 10-16 twice, 10-18) for NAT traversal, relays, WebRTC and a serverless bootstrap; Operation Convergence defers it past v1.0.0-alpha.1. Proposed in ADR 0202 (The mesh routes work to an identity, never an address, and selects among proven transports instead of implementing NAT traversal); ADR 0203 (GitHub Pages is a signed bootstrap anchor for the mesh, never its signalling channel) (proposed; it carries no authority until the owner accepts it). Sources: chatgpt-majordomus:c237#2, chatgpt-majordomus:c237#4, chatgpt-majordomus:c275#19, chatgpt-majordomus:c279#5.
Outcome
A connectivity decision record, a relayed path through a trusted hub, a signed bootstrap manifest on Pages, and a NAT matrix in the mesh lab.
Current state
Verified: apps/majordomus-cli/src/mesh/{multicast,broadcast,rendezvous}.rs; rendezvous hubs register but do not relay; seeds: none; no WebRTC/STUN/TURN anywhere in apps/; test/mesh-lab/run has ten scenarios, none behind NAT. Tailscale and Bonjour providers are on branches (I2410).
Desired state
Endpoint candidates are expiring observations; a link names its path; a node behind NAT cooperates through a relay; a cold node bootstraps from Pages.
Scope
- apps/majordomus-cli/src/mesh
- test/mesh-lab
- scripts/pages
- docs/MESH.md
Out of scope
- WebRTC data channels for browsers: after the browser-authentication question (proposed on an unlanded branch, no ADR on master) is decided
- Route learning from telemetry: only after the relay is measured
- DHT, coordinator election, multi-region gossip
Acceptance criteria
- A relayed link and a direct link are both proved in the lab
- Pages unavailable leaves every existing link up
Validation
- majordomus plan validate
Risks
- A relay is a hub that carries traffic: bandwidth and trust both grow; relayed frames stay authenticated by the existing link signatures but are not encrypted, so a relay hub is private, overlay or behind an encrypted ingress (case 491)
- Tailnet users may never need it (open question)
- It follows the-mesh-works-out-of-the-box in practice; the edge is kept off the milestone so two milestones of one order are not reordered.
Issues
Each one is an execution contract with its own acceptance criteria, validation command and required evidence. The wave column is the layer of the dependency graph it sits in.
| issue | status | wave | depends on | title |
|---|---|---|---|---|
| I3187 | BLOCKED | 1 | I2410 | A link names the endpoint candidates it tried, the one it chose and why |
| I3188 | BLOCKED | 2 | I3176 | A cold node finds the mesh from a signed manifest on Pages, and refuses a stale, rolled-back or unsigned one |
| I3189 | BLOCKED | 2 | I3187 | Two nodes with no direct path cooperate through a trusted hub that relays their authenticated frames |
| I3190 | BLOCKED | 3 | I3189 | The mesh lab proves links behind NAT, with the relay, a hub outage and an address change |
The graph
flowchart LR
I3187["I3187<br/>A link names the endpoint candidates it tried, the one it chose and why"]:::blocked
I3188["I3188<br/>A cold node finds the mesh from a signed manifest on Pages, and refuses a stale, rolled-back or unsigned one"]:::blocked
I3189["I3189<br/>Two nodes with no direct path cooperate through a trusted hub that relays their authenticated frames"]:::blocked
I3190["I3190<br/>The mesh lab proves links behind NAT, with the relay, a hub outage and an address change"]:::blocked
I3187 --> I3189
I3189 --> I3190
classDef done stroke:#16a34a,fill:#dcfce7,color:#14532d,stroke-width:2px
classDef active stroke:#2563eb,fill:#eff6ff,color:#1e3a8a,stroke-width:2px
classDef verify stroke:#7c3aed,fill:#f5f3ff,color:#4c1d95,stroke-width:2px
classDef ready stroke:#0891b2,fill:#ecfeff,color:#164e63,stroke-width:2px
classDef planned stroke:#0891b2,fill:#ecfeff,color:#164e63,stroke-width:2px
classDef blocked stroke:#b45309,fill:#fffbeb,color:#78350f,stroke-width:2px
classDef cancelled stroke:#6b7280,fill:#f9fafb,color:#374151,stroke-width:2px
classDef superseded stroke:#6b7280,fill:#f9fafb,color:#374151,stroke-width:2pxLinked from this diagram (4)
- I3187 A link names the endpoint candidates it tried, the one it chose and why
- I3188 A cold node finds the mesh from a signed manifest on Pages, and refuses a stale, rolled-back or unsigned one
- I3189 Two nodes with no direct path cooperate through a trusted hub that relays their authenticated frames
- I3190 The mesh lab proves links behind NAT, with the relay, a hub outage and an address change
Canonical record: .ai/repo/project/milestones/mesh-connectivity.yaml. Read it back with majordomus plan show mesh-connectivity.