hermes-agent/tests/gateway/relay
Ben Barclay f4df260f26
fix(relay): attach metadata.user_id on guild replies for egress fallback (#68320)
The relay adapter re-attaches an egress discriminator on outbound replies
so the connector can resolve the owning tenant. It captured scope_id for
scoped (guild) messages and user_id for DMs, but as MUTUALLY EXCLUSIVE:
a scoped inbound hit an early return, so the author's user_id was never
recorded, and _with_scope only attached user_id when there was no
scope_id. Guild replies therefore went out with scope_id only.

That's fine while the guild has a provision-time route row. But a MANAGED
Discord agent joins guilds dynamically (the shared bot is added to /
removed from servers at runtime), and GATEWAY_RELAY_ROUTE_KEYS — the only
thing that writes guild route rows — is a self-hosted, static field never
stamped for managed agents. So their guild has no route row, the
connector's guild-route lookup misses, and with no user_id on the frame
there's nothing to fall back to → every guild reply is declined
"discord egress declined: target not routed to an onboarded tenant"
even though INBOUND resolved the same guild fine (via the author-first
SharedSocketRouter.targets() fallback).

Fix: capture the authentic author user_id for EVERY inbound (DM and
scoped alike) and re-attach it on the outbound reply alongside scope_id.
The connector consults it only on a route/scope miss, so carrying both
never overrides routing-table resolution. This is the gateway half of the
paired gateway-gateway change (makeDiscordTenantOf guild-route-miss
author-binding fallback); together they make guild replies resolve the
same observed-author way inbound already does.

Tests (tests/gateway/relay/test_relay_adapter.py): a guild reply now
carries both scope_id AND user_id; a scoped inbound with no author still
yields scope_id only (never invents one). Verified fail-without /
pass-with.
2026-07-21 17:04:34 +10:00
..
__init__.py
stub_connector.py
test_auth.py
test_channel_context_consume.py
test_contract_doc_conformance.py
test_descriptor.py
test_descriptor_from_entry.py
test_identity_token_resolver.py
test_no_stub_leak.py
test_relay_adapter.py fix(relay): attach metadata.user_id on guild replies for egress fallback (#68320) 2026-07-21 17:04:34 +10:00
test_relay_follow_up.py
test_relay_going_idle.py
test_relay_interrupt.py
test_relay_multiplatform.py
test_relay_passthrough.py
test_relay_policy_send.py
test_relay_registration.py
test_relay_roundtrip.py
test_relay_roundtrip_telegram.py
test_relay_sheds_crypto.py
test_self_provision.py
test_ws_transport.py