fix(approval): wake blocked gateway approvals on session cleanup
This commit is contained in:
parent
f4ba97ad9a
commit
5f3f456784
@ -173,6 +173,23 @@ class TestBlockingGatewayApproval:
|
||||
assert e1.event.is_set()
|
||||
assert e2.event.is_set()
|
||||
|
||||
def test_clear_session_denies_and_signals_all_entries(self):
|
||||
"""clear_session must wake blocked entries during boundary cleanup."""
|
||||
from tools.approval import clear_session, _ApprovalEntry, _gateway_queues
|
||||
|
||||
session_key = "test-boundary-cleanup"
|
||||
e1 = _ApprovalEntry({"command": "cmd1"})
|
||||
e2 = _ApprovalEntry({"command": "cmd2"})
|
||||
_gateway_queues[session_key] = [e1, e2]
|
||||
|
||||
clear_session(session_key)
|
||||
|
||||
assert e1.event.is_set()
|
||||
assert e2.event.is_set()
|
||||
assert e1.result == "deny"
|
||||
assert e2.result == "deny"
|
||||
assert session_key not in _gateway_queues
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# /approve command
|
||||
|
||||
@ -10,6 +10,7 @@ from gateway.platforms.base import MessageEvent
|
||||
from gateway.session import SessionEntry, SessionSource, build_session_key
|
||||
from tools import approval as approval_mod
|
||||
from tools.approval import (
|
||||
_ApprovalEntry,
|
||||
approve_session,
|
||||
enable_session_yolo,
|
||||
is_approved,
|
||||
@ -214,3 +215,30 @@ def test_clear_session_boundary_security_state_is_scoped():
|
||||
runner._clear_session_boundary_security_state("")
|
||||
assert is_approved(other_key, "recursive delete") is True
|
||||
assert other_key in runner._update_prompt_pending
|
||||
|
||||
|
||||
def test_clear_session_boundary_security_state_wakes_blocked_approvals():
|
||||
"""Boundary cleanup must cancel blocked approval waiters immediately."""
|
||||
from gateway.run import GatewayRunner
|
||||
|
||||
runner = object.__new__(GatewayRunner)
|
||||
runner._pending_approvals = {}
|
||||
runner._update_prompt_pending = {}
|
||||
|
||||
source = _make_source()
|
||||
session_key = build_session_key(source)
|
||||
other_key = "agent:main:telegram:dm:other-chat"
|
||||
|
||||
target_entry = _ApprovalEntry({"command": "rm -rf /tmp/demo"})
|
||||
other_entry = _ApprovalEntry({"command": "rm -rf /tmp/other"})
|
||||
approval_mod._gateway_queues[session_key] = [target_entry]
|
||||
approval_mod._gateway_queues[other_key] = [other_entry]
|
||||
|
||||
runner._clear_session_boundary_security_state(session_key)
|
||||
|
||||
assert target_entry.event.is_set()
|
||||
assert target_entry.result == "deny"
|
||||
assert other_entry.event.is_set() is False
|
||||
assert other_entry.result is None
|
||||
assert session_key not in approval_mod._gateway_queues
|
||||
assert other_key in approval_mod._gateway_queues
|
||||
|
||||
@ -400,8 +400,8 @@ def unregister_gateway_notify(session_key: str) -> None:
|
||||
with _lock:
|
||||
_gateway_notify_cbs.pop(session_key, None)
|
||||
entries = _gateway_queues.pop(session_key, [])
|
||||
for entry in entries:
|
||||
entry.event.set()
|
||||
for entry in entries:
|
||||
entry.event.set()
|
||||
|
||||
|
||||
def resolve_gateway_approval(session_key: str, choice: str,
|
||||
@ -475,7 +475,12 @@ def clear_session(session_key: str) -> None:
|
||||
_session_approved.pop(session_key, None)
|
||||
_session_yolo.discard(session_key)
|
||||
_pending.pop(session_key, None)
|
||||
_gateway_queues.pop(session_key, None)
|
||||
entries = _gateway_queues.pop(session_key, [])
|
||||
for entry in entries:
|
||||
# Session-boundary cleanup should cancel any blocked approval waits
|
||||
# immediately so the old run can unwind instead of idling until timeout.
|
||||
entry.result = "deny"
|
||||
entry.event.set()
|
||||
|
||||
|
||||
def is_session_yolo_enabled(session_key: str) -> bool:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user