fix(slack): resolve a cold channel's workspace from the sole authenticated team

scope_id_for_chat only consulted the channel→team map, which is empty right after boot (and
after a reconnect) until an inbound event from that channel arrives. A /handoff into a Slack home
without a stored scope_id (SLACK_HOME_CHANNEL env homes, or config homes never re-set via
/sethome) therefore built a key without the team while every thread reply carries it — the
handed-off thread was still orphaned across a restart (#111896).

When the map has no entry and the channel is not known to be shared across workspaces, fall back
to the single authenticated workspace (filled by auth.test at connect); multi-workspace installs
keep returning None.
This commit is contained in:
teknium1
2026-09-15 14:23:45 -07:00
committed by Teknium
parent 1f3f45e87b
commit 79bf0be53b
2 changed files with 30 additions and 10 deletions

View File

@@ -1909,8 +1909,14 @@ class SlackAdapter(BasePlatformAdapter):
def scope_id_for_chat(self, chat_id: str) -> Optional[str]:
"""Return the workspace id owning ``chat_id``.
``None`` for unknown channels and for channels claimed by several workspaces (dropped from
the map) — no scope beats a wrong one."""
the map) — no scope beats a wrong one. A channel unseen since boot (the map only fills from
inbound events) still resolves when exactly one workspace is authenticated: every inbound
reply will carry that team_id, so a caller keying a session on it must match (#111896)."""
team_id = chat_id and (getattr(self, "_channel_team", None) or {}).get(str(chat_id))
if not team_id and chat_id and str(chat_id) not in (getattr(self, "_channel_teams", None) or {}):
team_clients = getattr(self, "_team_clients", None) or {}
if len(team_clients) == 1:
team_id = next(iter(team_clients))
return str(team_id) if team_id else None
def _get_client(self, chat_id: str, team_id: Optional[str] = None) -> Any: