fix(gateway): enforce chat_id isolation for all DM sessions
This commit is contained in:
parent
779f8df6a6
commit
34e120bcbb
2 changed files with 21 additions and 14 deletions
|
|
@ -321,25 +321,32 @@ def build_session_key(source: SessionSource) -> str:
|
||||||
This is the single source of truth for session key construction.
|
This is the single source of truth for session key construction.
|
||||||
|
|
||||||
DM rules:
|
DM rules:
|
||||||
- WhatsApp DMs include chat_id (multi-user support).
|
- DMs include chat_id when present, so each private conversation is isolated.
|
||||||
- Other DMs include thread_id when present (e.g. Slack threaded DMs),
|
- thread_id further differentiates threaded DMs within the same DM chat.
|
||||||
so each DM thread gets its own session while top-level DMs share one.
|
- Without chat_id, thread_id is used as a best-effort fallback.
|
||||||
- Without thread_id or chat_id, all DMs share a single session.
|
- Without thread_id or chat_id, DMs share a single session.
|
||||||
|
|
||||||
Group/channel rules:
|
Group/channel rules:
|
||||||
- thread_id differentiates threads within a channel.
|
- chat_id identifies the parent group/channel.
|
||||||
- Without thread_id, all messages in a channel share one session.
|
- thread_id differentiates threads within that parent chat.
|
||||||
|
- Without identifiers, messages fall back to one session per platform/chat_type.
|
||||||
"""
|
"""
|
||||||
platform = source.platform.value
|
platform = source.platform.value
|
||||||
if source.chat_type == "dm":
|
if source.chat_type == "dm":
|
||||||
|
if source.chat_id:
|
||||||
|
if source.thread_id:
|
||||||
|
return f"agent:main:{platform}:dm:{source.chat_id}:{source.thread_id}"
|
||||||
|
return f"agent:main:{platform}:dm:{source.chat_id}"
|
||||||
if source.thread_id:
|
if source.thread_id:
|
||||||
return f"agent:main:{platform}:dm:{source.thread_id}"
|
return f"agent:main:{platform}:dm:{source.thread_id}"
|
||||||
if platform == "whatsapp" and source.chat_id:
|
|
||||||
return f"agent:main:{platform}:dm:{source.chat_id}"
|
|
||||||
return f"agent:main:{platform}:dm"
|
return f"agent:main:{platform}:dm"
|
||||||
|
if source.chat_id:
|
||||||
|
if source.thread_id:
|
||||||
|
return f"agent:main:{platform}:{source.chat_type}:{source.chat_id}:{source.thread_id}"
|
||||||
|
return f"agent:main:{platform}:{source.chat_type}:{source.chat_id}"
|
||||||
if source.thread_id:
|
if source.thread_id:
|
||||||
return f"agent:main:{platform}:{source.chat_type}:{source.chat_id}:{source.thread_id}"
|
return f"agent:main:{platform}:{source.chat_type}:{source.thread_id}"
|
||||||
return f"agent:main:{platform}:{source.chat_type}:{source.chat_id}"
|
return f"agent:main:{platform}:{source.chat_type}"
|
||||||
|
|
||||||
|
|
||||||
class SessionStore:
|
class SessionStore:
|
||||||
|
|
|
||||||
|
|
@ -338,7 +338,7 @@ class TestSessionStoreRewriteTranscript:
|
||||||
|
|
||||||
class TestWhatsAppDMSessionKeyConsistency:
|
class TestWhatsAppDMSessionKeyConsistency:
|
||||||
"""Regression: all session-key construction must go through build_session_key
|
"""Regression: all session-key construction must go through build_session_key
|
||||||
so WhatsApp DMs include chat_id while other DMs do not."""
|
so DMs are isolated by chat_id across platforms."""
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def store(self, tmp_path):
|
def store(self, tmp_path):
|
||||||
|
|
@ -369,15 +369,15 @@ class TestWhatsAppDMSessionKeyConsistency:
|
||||||
)
|
)
|
||||||
assert store._generate_session_key(source) == build_session_key(source)
|
assert store._generate_session_key(source) == build_session_key(source)
|
||||||
|
|
||||||
def test_telegram_dm_omits_chat_id(self):
|
def test_telegram_dm_includes_chat_id(self):
|
||||||
"""Non-WhatsApp DMs should still omit chat_id (single owner DM)."""
|
"""Non-WhatsApp DMs should also include chat_id to separate users."""
|
||||||
source = SessionSource(
|
source = SessionSource(
|
||||||
platform=Platform.TELEGRAM,
|
platform=Platform.TELEGRAM,
|
||||||
chat_id="99",
|
chat_id="99",
|
||||||
chat_type="dm",
|
chat_type="dm",
|
||||||
)
|
)
|
||||||
key = build_session_key(source)
|
key = build_session_key(source)
|
||||||
assert key == "agent:main:telegram:dm"
|
assert key == "agent:main:telegram:dm:99"
|
||||||
|
|
||||||
def test_discord_group_includes_chat_id(self):
|
def test_discord_group_includes_chat_id(self):
|
||||||
"""Group/channel keys include chat_type and chat_id."""
|
"""Group/channel keys include chat_type and chat_id."""
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue