Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions gateway/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -11311,6 +11311,12 @@ def _clear_session_boundary_security_state(self, session_key: str) -> None:
if not session_key:
return

pending_skills_reload_notes = getattr(
self, "_pending_skills_reload_notes", None
)
if isinstance(pending_skills_reload_notes, dict):
pending_skills_reload_notes.pop(session_key, None)

pending_approvals = getattr(self, "_pending_approvals", None)
if isinstance(pending_approvals, dict):
pending_approvals.pop(session_key, None)
Expand Down
22 changes: 22 additions & 0 deletions tests/gateway/test_session_boundary_security_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ async def test_resume_clears_session_scoped_approval_and_yolo_state():
runner, session_key = _make_resume_runner()
other_key = "agent:main:telegram:dm:other-chat"

runner._pending_skills_reload_notes = {
session_key: "[USER INITIATED SKILLS RELOAD: target]",
other_key: "[USER INITIATED SKILLS RELOAD: other]",
}
approve_session(session_key, "recursive delete")
approve_session(other_key, "recursive delete")
enable_session_yolo(session_key)
Expand All @@ -140,17 +144,23 @@ async def test_resume_clears_session_scoped_approval_and_yolo_state():
assert is_session_yolo_enabled(session_key) is False
assert session_key not in runner._pending_approvals
assert session_key not in runner._update_prompt_pending
assert session_key not in runner._pending_skills_reload_notes
assert is_approved(other_key, "recursive delete") is True
assert is_session_yolo_enabled(other_key) is True
assert other_key in runner._pending_approvals
assert other_key in runner._update_prompt_pending
assert other_key in runner._pending_skills_reload_notes


@pytest.mark.asyncio
async def test_branch_clears_session_scoped_approval_and_yolo_state():
runner, session_key = _make_branch_runner()
other_key = "agent:main:telegram:dm:other-chat"

runner._pending_skills_reload_notes = {
session_key: "[USER INITIATED SKILLS RELOAD: target]",
other_key: "[USER INITIATED SKILLS RELOAD: other]",
}
approve_session(session_key, "recursive delete")
approve_session(other_key, "recursive delete")
enable_session_yolo(session_key)
Expand All @@ -167,10 +177,12 @@ async def test_branch_clears_session_scoped_approval_and_yolo_state():
assert is_session_yolo_enabled(session_key) is False
assert session_key not in runner._pending_approvals
assert session_key not in runner._update_prompt_pending
assert session_key not in runner._pending_skills_reload_notes
assert is_approved(other_key, "recursive delete") is True
assert is_session_yolo_enabled(other_key) is True
assert other_key in runner._pending_approvals
assert other_key in runner._update_prompt_pending
assert other_key in runner._pending_skills_reload_notes


@pytest.mark.asyncio
Expand Down Expand Up @@ -216,6 +228,7 @@ def test_clear_session_boundary_security_state_is_scoped():
runner = object.__new__(GatewayRunner)
runner._pending_approvals = {}
runner._update_prompt_pending = {}
runner._pending_skills_reload_notes = {}

source = _make_source()
session_key = build_session_key(source)
Expand All @@ -229,6 +242,12 @@ def test_clear_session_boundary_security_state_is_scoped():
runner._pending_approvals[other_key] = {"command": "rm -rf /tmp/other"}
runner._update_prompt_pending[session_key] = True
runner._update_prompt_pending[other_key] = True
runner._pending_skills_reload_notes[session_key] = (
"[USER INITIATED SKILLS RELOAD: target]"
)
runner._pending_skills_reload_notes[other_key] = (
"[USER INITIATED SKILLS RELOAD: other]"
)

runner._clear_session_boundary_security_state(session_key)

Expand All @@ -237,16 +256,19 @@ def test_clear_session_boundary_security_state_is_scoped():
assert is_session_yolo_enabled(session_key) is False
assert session_key not in runner._pending_approvals
assert session_key not in runner._update_prompt_pending
assert session_key not in runner._pending_skills_reload_notes
# Other session untouched
assert is_approved(other_key, "recursive delete") is True
assert is_session_yolo_enabled(other_key) is True
assert other_key in runner._pending_approvals
assert other_key in runner._update_prompt_pending
assert other_key in runner._pending_skills_reload_notes

# Empty session_key is a no-op
runner._clear_session_boundary_security_state("")
assert is_approved(other_key, "recursive delete") is True
assert other_key in runner._update_prompt_pending
assert other_key in runner._pending_skills_reload_notes


def test_clear_session_boundary_security_state_wakes_blocked_approvals():
Expand Down