Skip to content

relay send: contact_unauthorised when recipient alias has no relay identity binding (local peer is fine) #81

Description

@XertroV

Summary

Cross-host / relay delivery to a peer that is alive on the local broker fails with:

c2c relay failed (exit 1): { "ok": false, "error_code": "contact_unauthorised", "error": "contact unauthorised"… }

Same-machine bare-alias send/receive to that peer works. This is easy to misread as “agent is unauthorized / offline” when the real problem is relay registration / contact-grant path, not local registration.

Observed while coordinating dreamwork co-agents on one host (pi-dcd88egrok-sugar-vesi-x6tv).

Environment (repro host)

Item Value
Recipient alias grok-sugar-vesi-x6tv
Recipient session 019f9c94-945a-7221-b920-e1a3b7732bab (Grok)
Local broker recipient alive (c2c find / c2c status)
Relay URL https://relay.c2c.im (configured in ~/.config/c2c/relay.json)
Relay registration no identity binding for the recipient alias
Relay connector none (no c2c relay connect state)
Identity fingerprint SHA256:NEstCw_c5DCM3pJ3CGtl1bN02rPPPd18IVERVF3ciUU (from c2c relay identity show)

c2c whoami --relay / c2c status --relay report:

hint: the relay has no identity binding for alias "grok-sugar-vesi-x6tv".
  Your local Ed25519 identity is not registered under that alias yet.
  Fix:  c2c relay register --alias grok-sugar-vesi-x6tv

and

state: configured_unverified — relay query failed (alias "…" has no identity binding) …
connector: none
lease: (relay unreachable: alias "…" has no identity binding)

What works

# local broker — OK both directions on the same machine
c2c send pi-dcd88e "probe"
c2c send grok-sugar-vesi-x6tv "probe"
# recipient inbox monitor receives; recipient can reply

What fails

Sender (or tool) path that goes through relay to the recipient alias returns contact_unauthorised even though:

  1. Recipient is registered and alive locally.
  2. Alias is known / discoverable on the local swarm.
  3. Failure surface says “contact unauthorised”, not “alias not registered on relay” / “no relay lease”.

Exact sender tool trace (Pi agent):

c2c.send · failed · c2c relay failed (exit 1): {
  "ok": false,
  "error_code": "contact_unauthorised",
  "error": "contact unauthorised"…
}

Expected

Prefer one or more of:

  1. Local-first routing when the target alias resolves to a live peer on a shared/local broker — do not fall through to relay and fail closed as “unauthorised”.
  2. If relay is required: clearer error distinguishing:
    • recipient not registered on relay (no identity binding)
    • missing / expired recipient-owned contact grant (c2c relay contact)
    • no connector / no lease
  3. Docs / doctor surface that maps contact_unauthorised → concrete fix steps (relay register, relay connect, relay contact issue).

Actual

Relay returns contact_unauthorised, which operators/agents interpret as an ACL / peer block, while whoami --relay already knows the alias has no relay identity binding at all.

Related surfaces

  • c2c relay contact — recipient-owned contact grants (private reachability)
  • c2c relay register --alias …
  • c2c relay connect / connector state
  • Addressing: bare <alias> = local; <alias>@<host_id> = cross-host via relay

Impact

Coordinator agents attempt “contact peer via c2c” and treat contact_unauthorised as fatal peer rejection, even when the peer is healthy on the local broker. Wastes coordination turns and blocks work fan-out.

Suggested acceptance checks

  • Live local peer + no relay registration: send by bare alias succeeds (local path) and does not emit contact_unauthorised from a relay hop that was never needed.
  • Explicit remote address (alias@host_id) without registration: error code/message names missing relay registration (or missing grant), not only contact_unauthorised.
  • c2c doctor (or send failure text) lists the three distinct failure classes above.

Non-goals for this report

Not asking to weaken contact grants. Only to route correctly when local delivery is available, and to make the relay failure class legible.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions