fix(gateway): fingerprint Teams client_id and WeCom bot_id for the multiplex credential guard

Same class as the Feishu _app_id gap (#76793): Teams and WeCom authenticate
with an id/secret pair and store no token attribute, so
_adapter_credential_fingerprint returned None and cloned profiles started
competing adapters against one app. Add both ids to the attr tuple.
This commit is contained in:
Teknium
2026-09-02 03:30:11 -07:00
parent 97b8a97861
commit 5b4cff976d
2 changed files with 17 additions and 0 deletions
+4
View File
@@ -17691,6 +17691,10 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew
# _app_lock_identity, so including it lets the multiplex guard
# refuse cloned profiles competing for the same Feishu app.
"_app_id",
# Same class: Teams (client_id/client_secret) and WeCom
# (bot_id/secret) authenticate with an app-style id pair too.
"_client_id",
"_bot_id",
):
val = getattr(adapter, attr, None)
if isinstance(val, str) and val.strip():
@@ -1,6 +1,7 @@
"""Phase 3: secondary-profile adapter registry + same-token conflict detection."""
import logging
import asyncio
import types
from contextlib import contextmanager
from pathlib import Path
from unittest.mock import AsyncMock, MagicMock
@@ -72,6 +73,18 @@ class TestCredentialFingerprint:
assert fp_a is not None and fp_b is not None
assert fp_a != fp_b
@pytest.mark.parametrize("attr", ["_client_id", "_bot_id"])
def test_reads_app_style_ids_teams_wecom(self, attr):
"""Teams (_client_id) and WeCom (_bot_id) are the same class as Feishu:
id/secret pairs, no token — cloned profiles must collide."""
a = types.SimpleNamespace(**{attr: "app-1"})
b = types.SimpleNamespace(**{attr: "app-1"})
c = types.SimpleNamespace(**{attr: "app-2"})
fp = GatewayRunner._adapter_credential_fingerprint
assert fp(a) is not None and fp(a) == fp(b)
assert fp(a) != fp(c)
assert "app-1" not in fp(a)
def test_reads_config_token(self):
"""Adapters like Discord store token on `config`, not on self.