I2410 — A trusted machine on the tailnet is found through Tailscale, with no address written by hand
Add a Tailscale discovery provider beside multicast, broadcast and rendezvous: it reads the local tailnet's peers and offers each one's tailnet address on the declared port as a candidate, which the link then admits or refuses under the trust list.
READY wave 0 · p0 · implementation profile · parallel safe
Ready. Every dependency is done, so majordomus plan start I2410 will be accepted.
Objective
Add a Tailscale discovery provider beside multicast, broadcast and rendezvous: it reads the local tailnet's peers and offers each one's tailnet address on the declared port as a candidate, which the link then admits or refuses under the trust list.
Why
No provider reads the tailnet (apps/majordomus-cli/src/mesh/manager.rs:436-450 wires multicast, broadcast and rendezvous only; the only mention of Tailscale is a ranking test in mesh/address.rs:186). Machines on the owner's tailnet are linked today only because .ai/repo/mesh/majordomus.yaml:41-50 lists their 100.x addresses by hand, so a machine added to the tailnet is invisible until somebody edits that file.
Current state
Tailnet peers are dialed only through hand-written rendezvous endpoints.
Desired state
A `tailscale:` section of the mesh declaration (enabled by default when the tailscale CLI is present) whose provider lists online peers from `tailscale status --json` and hands their addresses to the cooperation dialer; absent or failing tailscale is reported in mesh doctor, never fatal.
Scope
- apps/majordomus-cli/src/mesh
- apps/majordomus-cli/src/mesh/manager.rs
- apps/majordomus-cli/src/mesh/config.rs
- share/schemas/majordomus/mesh-declaration
- docs/MESH.md
- test/cases
Dependencies
None. This issue is a root of the graph.
What waits on this
- I3176BLOCKED The committed mesh declaration names its hubs by node, and no private address is tracked or published
- I3187BLOCKED A link names the endpoint candidates it tried, the one it chose and why
- I3837BLOCKED A case that enables the mesh declares its tailnet provider off, so it stays hermetic on a machine that runs Tailscale
Acceptance criteria
- With a stubbed `tailscale status --json` naming two online peers, the provider offers exactly their tailnet addresses on the declared port
- An offline peer, a peer without a tailnet IP and a missing tailscale CLI each produce no candidate and a doctor line
- A candidate the trust list does not name is refused by the link, as any other candidate is
Validation
- bin/majordomus plan validate
- cargo test --lib mesh::tailscale
Evidence required
- tailscale_provider_stubbed_test
Evidence
None recorded. Every token above needs a command or an artifact behind it before this issue can be completed; narrative is refused.
Timeline
- started
- —
- verified
- —
- completed
- —
Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.
Canonical record: .ai/repo/project/issues/I2410.yaml. Read it back with majordomus plan show I2410.