Skip to content

Commit 5f3f456

Browse files
Yukipukii1teknium1
authored andcommitted
fix(approval): wake blocked gateway approvals on session cleanup
1 parent f4ba97a commit 5f3f456

3 files changed

Lines changed: 53 additions & 3 deletions

File tree

tests/gateway/test_approve_deny_commands.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,23 @@ def test_unregister_signals_all_entries(self):
173173
assert e1.event.is_set()
174174
assert e2.event.is_set()
175175

176+
def test_clear_session_denies_and_signals_all_entries(self):
177+
"""clear_session must wake blocked entries during boundary cleanup."""
178+
from tools.approval import clear_session, _ApprovalEntry, _gateway_queues
179+
180+
session_key = "test-boundary-cleanup"
181+
e1 = _ApprovalEntry({"command": "cmd1"})
182+
e2 = _ApprovalEntry({"command": "cmd2"})
183+
_gateway_queues[session_key] = [e1, e2]
184+
185+
clear_session(session_key)
186+
187+
assert e1.event.is_set()
188+
assert e2.event.is_set()
189+
assert e1.result == "deny"
190+
assert e2.result == "deny"
191+
assert session_key not in _gateway_queues
192+
176193

177194
# ------------------------------------------------------------------
178195
# /approve command

tests/gateway/test_session_boundary_security_state.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from gateway.session import SessionEntry, SessionSource, build_session_key
1111
from tools import approval as approval_mod
1212
from tools.approval import (
13+
_ApprovalEntry,
1314
approve_session,
1415
enable_session_yolo,
1516
is_approved,
@@ -214,3 +215,30 @@ def test_clear_session_boundary_security_state_is_scoped():
214215
runner._clear_session_boundary_security_state("")
215216
assert is_approved(other_key, "recursive delete") is True
216217
assert other_key in runner._update_prompt_pending
218+
219+
220+
def test_clear_session_boundary_security_state_wakes_blocked_approvals():
221+
"""Boundary cleanup must cancel blocked approval waiters immediately."""
222+
from gateway.run import GatewayRunner
223+
224+
runner = object.__new__(GatewayRunner)
225+
runner._pending_approvals = {}
226+
runner._update_prompt_pending = {}
227+
228+
source = _make_source()
229+
session_key = build_session_key(source)
230+
other_key = "agent:main:telegram:dm:other-chat"
231+
232+
target_entry = _ApprovalEntry({"command": "rm -rf /tmp/demo"})
233+
other_entry = _ApprovalEntry({"command": "rm -rf /tmp/other"})
234+
approval_mod._gateway_queues[session_key] = [target_entry]
235+
approval_mod._gateway_queues[other_key] = [other_entry]
236+
237+
runner._clear_session_boundary_security_state(session_key)
238+
239+
assert target_entry.event.is_set()
240+
assert target_entry.result == "deny"
241+
assert other_entry.event.is_set() is False
242+
assert other_entry.result is None
243+
assert session_key not in approval_mod._gateway_queues
244+
assert other_key in approval_mod._gateway_queues

tools/approval.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,8 @@ def unregister_gateway_notify(session_key: str) -> None:
400400
with _lock:
401401
_gateway_notify_cbs.pop(session_key, None)
402402
entries = _gateway_queues.pop(session_key, [])
403-
for entry in entries:
404-
entry.event.set()
403+
for entry in entries:
404+
entry.event.set()
405405

406406

407407
def resolve_gateway_approval(session_key: str, choice: str,
@@ -475,7 +475,12 @@ def clear_session(session_key: str) -> None:
475475
_session_approved.pop(session_key, None)
476476
_session_yolo.discard(session_key)
477477
_pending.pop(session_key, None)
478-
_gateway_queues.pop(session_key, None)
478+
entries = _gateway_queues.pop(session_key, [])
479+
for entry in entries:
480+
# Session-boundary cleanup should cancel any blocked approval waits
481+
# immediately so the old run can unwind instead of idling until timeout.
482+
entry.result = "deny"
483+
entry.event.set()
479484

480485

481486
def is_session_yolo_enabled(session_key: str) -> bool:

0 commit comments

Comments
 (0)