diff --git a/tests/tools/test_discord_tool.py b/tests/tools/test_discord_tool.py index 70b43903ec..51226f0702 100644 --- a/tests/tools/test_discord_tool.py +++ b/tests/tools/test_discord_tool.py @@ -696,6 +696,38 @@ class TestCapabilityDetection: _detect_capabilities("tok", force=True) assert mock_req.call_count == 2 + @patch("tools.discord_tool._discord_request") + def test_cache_is_keyed_by_token(self, mock_req): + """Regression: token A's capabilities must not leak to token B. + + Before the fix, the cache was a single module-global dict. The first + call populated it and every subsequent call — regardless of token — + returned the same cached value, producing wrong schema gating for + rotated or multi-token deployments. + """ + def _per_token_flags(method, path, token, **_kwargs): + # token A: both intents; token B: neither. + if token == "tok_a": + return {"flags": (1 << 14) | (1 << 18)} + return {"flags": 0} + + mock_req.side_effect = _per_token_flags + + caps_a = _detect_capabilities("tok_a") + caps_b = _detect_capabilities("tok_b") + + assert caps_a["has_members_intent"] is True + assert caps_a["has_message_content"] is True + assert caps_b["has_members_intent"] is False + assert caps_b["has_message_content"] is False + # Each token should hit the endpoint exactly once. + assert mock_req.call_count == 2 + + # Re-requesting either token serves from its own cache entry. + _detect_capabilities("tok_a") + _detect_capabilities("tok_b") + assert mock_req.call_count == 2 + # --------------------------------------------------------------------------- # Config allowlist