Expand description
Multi-endpoint routing for v0.5.17 (dual-slot sessions).
Each wire session can hold up to TWO slots:
- Federation — on a public relay (default
https://wireup.net), listed in the phonebook, reachable across machines. - Local — on a loopback relay (default
http://127.0.0.1:8771, started withwire relay-server --local-only), invisible from off-box, sub-millisecond round-trip for same-machine sister-Claude traffic.
Both slots are advertised to paired peers via the pair_drop body’s
endpoints[] array (additive — v0.5.16-and-earlier peers see only
the federation endpoint at the top-level legacy fields, unchanged).
Routing decision lives in cmd_push: walk a peer’s pinned endpoints
in priority order (local first if we also have a local slot), POST
the event, fall back to the next endpoint on failure. Pulling: the
daemon reads from BOTH slots, dedupes by event_id.
Storage shape in relay_state.json:
{
"self": {
// Self-slot still carries the flat triple (the #263 daemon-survival
// fix synthesizes a sister's flat fields; self-collapse is Part A /
// a separate slice — see RFC-006).
"relay_url": "https://wireup.net",
"slot_id": "abc...",
"slot_token":"...",
"endpoints": [
{"relay_url": "https://wireup.net", "slot_id": "abc...", "slot_token": "...", "scope": "federation"},
{"relay_url": "http://127.0.0.1:8771", "slot_id": "loop...", "slot_token": "...", "scope": "local"}
]
},
"peers": {
"wire-mesh": {
// RFC-006 Part B (#268): peers carry `endpoints[]` ONLY — the single
// peer-routing source. The flat relay_url/slot_id/slot_token triple
// is no longer written (it was the "stale flat beats fresh array"
// routing hazard). All peer-pin readers resolve through
// `peer_endpoints_in_priority_order` / `peer_primary_endpoint`.
"endpoints": [...]
}
}
}Structs§
- Endpoint
- One reachable address for a wire identity. Includes the bearer
slot_tokenbecause endpoints flow through the pair_drop body, which is encrypted at protocol level (signed envelope + bilateral pin gate from v0.5.14). Token is the slot’s bearer credential; it MUST stay private to the pair and is never published in the agent card or phonebook.
Enums§
- Endpoint
Scope - Where this endpoint sits in the reachability graph.
Functions§
- endpoints_
are_ local_ only - True iff this endpoint set is reachable ONLY from the same box — every
endpoint resolves (by URL) to a loopback/
LocalorUdsaddress, with no off-boxFederation/LAN host. A peer pinned this way can’t complete a bilateral reply path with a remote peer: the reply has nowhere off-box to land. This is the #277 honesty signal —wire acceptreportedbilateral_acceptedeven when the resulting pin advertised only loopback endpoints. Inferred from the URL (not the advertisedscope) so a loopback address mislabeledfederation(exactly the #277 case) is still caught. Empty set → false (no pin to judge). - infer_
scope_ from_ url - Infer an endpoint scope from a relay URL:
unix://-> Uds, a loopback host -> Local, otherwise Federation. LAN is never inferred (a private- range IP is indistinguishable from a federation host by URL alone) and must be requested explicitly. - is_
loopback_ host - True iff
host(no scheme, no port) is a loopback address the E4 trust-path gates treat asLocalscope:infer_scope_from_url, the handle validator + URL builder (pair_profile::is_valid_domain/relay_url_for_domain), and theis_known_relay_domainphishing-warning suppression all key off THIS one predicate so scheme + scope can never disagree. Keeping one predicate is load-bearing: if these gates disagreed on “loopback”, a handle could parse + get anhttp://URL while being classifiedFederation(advertised off-box). - peer_
endpoints_ in_ priority_ order - Read all of a peer’s pinned endpoints from
relay_state.json, sorted in routing priority order: - peer_
federation_ token - The
slot_tokenof a peer’s pinned federation endpoint onrelay_url, or""if there’s no such endpoint (or it hasn’t acked yet). - peer_
nostr_ transport - Read a peer’s Nostr transport coords
(npub_hex, relay_url), orNoneif the peer has no Nostr transport recorded. - peer_
primary_ endpoint - The single best (highest-priority) endpoint to reach
peer_handle, orNoneif the peer has no pinned endpoints. RFC-006 Part B: the canonical replacement for reading the old flatrelay_url/slot_id/slot_tokenpeer fields — every peer-pin reader resolves through this (orpeer_endpoints_in_priority_orderwhen it needs failover). - pin_
peer_ endpoints - Pin a peer’s full set of endpoints into
relay_state.jsonunderpeers[handle]. RFC-006 Part B (#268): writesendpoints[]ONLY — the single peer-routing source. The flatrelay_url/slot_id/slot_tokentriple is no longer written. Durable non-routing fields (bilateral_completed_at,persona,profile,first_seen_at,nostr_transport) are preserved across re-pins (see below). - pin_
peer_ nostr_ transport - RFC-007 D3.4: record a peer’s Nostr transport reachability — their
x-only npub (hex) + a
wss://relay to reach them on — underpeers[handle].nostr_transport. Read-modify-write so it composes withpin_peer_endpoints(which preserves this field). Reachability only; trust is a separate pin. Idempotent. - pin_
self_ nostr_ relay - RFC-007 D3: record a Nostr relay this session is reachable on — one we’ve
paired/fetched over (
wire nostr pair/accept/fetch --relay X). Persisted as the distinct setself.nostr_relays[]. The daemon pull-loop reads this as the authoritative “where do peers publish my inbound” set: a peer sends to me by publishing to a relay I’m reachable on, which isn’t necessarily a relay I reach them on (the asymmetric case the peer-transport set misses). Read-modify-write, idempotent (dedups). - self_
endpoints - All of OUR own endpoints from
relay_state.json. Used bycmd_pushto find the local slot when routing local-first, and by the daemon’s pull loop to iterate every slot we should be reading from. - self_
nostr_ relays - The distinct Nostr relays this session is reachable on (
self.nostr_relays[]). Empty when never paired over Nostr. - self_
primary_ endpoint - v0.9 canonical single-reader for “my best inbound slot.” Returns
the first endpoint from
self_endpoints()— which is already priority-ordered (UDS → Local-with-matching-self → LAN → Federation) AND back-compat-falls-back to legacy top-level fields. - upsert_
self_ endpoint - Insert-or-replace one of OUR OWN endpoints in
relay_state["self"], keyed byrelay_url(re-binding the same relay updates it in place). ADDITIVE: every other existing self endpoint is preserved, so an agent can hold a local relay AND a federation relay at once. Rebuilds the legacy top-level fields. Single source of truth for the self-slot write shape — used bycmd_bind_relayandinit_self_idempotent.