From 4600634a6150f37f51ca2b3f085048bcf571fcea Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Sat, 24 Oct 2026 03:55:43 +0400 Subject: [PATCH] =?UTF-8?q?=D0=90=D0=B3=D0=B5=D0=BD=D1=82=20=D0=BD=D0=B5?= =?UTF-8?q?=20=D1=87=D0=B8=D1=82=D0=B0=D0=B5=D1=82=20=D0=B8=20=D0=BD=D0=B5?= =?UTF-8?q?=20=D0=B7=D0=B0=D0=BA=D1=80=D1=8B=D0=B2=D0=B0=D0=B5=D1=82=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=BC=D0=B0=D0=BD=D0=B4=D1=8B=20=D1=87=D1=83=D0=B6?= =?UTF-8?q?=D0=BE=D0=B3=D0=BE=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D1=8F=20(I-?= =?UTF-8?q?1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- src/jira_hub/core/api.py | 11 ++++++++++- tests/test_agents.py | 25 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/jira_hub/core/api.py b/src/jira_hub/core/api.py index 4170ca1..a4238db 100644 --- a/src/jira_hub/core/api.py +++ b/src/jira_hub/core/api.py @@ -162,13 +162,22 @@ def h_agent_settings(hub, conn, m, q, body): return 200, settings.for_agent(conn, http.agent_of(q)) +def _own_command(conn, cmd_id, agent): + """Команда по id, но только своего модуля: чужой тип — тот же 404, что и несуществующая команда (I-1 финального ревью).""" + cmd = not_found(queue.get_command(conn, cmd_id), "command") + if cmd["type"] not in queue._own_types(agent): + raise ApiError(404, "not_found", "command") + return cmd + + def h_agent_command(hub, conn, m, q, body): """Команда по id для восстановления из журнала агента: параметры — как при выдаче (с size у команд с файлом).""" - cmd = not_found(queue.get_command(conn, int_group(m)), "command") + cmd = _own_command(conn, int_group(m), http.agent_of(q)) return 200, {**cmd, "params": queue.deliver_params(conn, cmd, hub.files_dir)} def h_agent_result(hub, conn, m, q, body): + _own_command(conn, int_group(m), http.agent_of(q)) try: cmd = queue.report_result(conn, int_group(m), body.get("status"), body.get("result"), body.get("error"), body.get("jira_calls", 0), body.get("rate_limited", 0), files_dir=hub.files_dir) diff --git a/tests/test_agents.py b/tests/test_agents.py index e83c6aa..f7f4370 100644 --- a/tests/test_agents.py +++ b/tests/test_agents.py @@ -260,3 +260,28 @@ def test_wiki_agent_token_after_upgrade(tmp_path): assert names == {"jira", "wiki"} finally: conn.close() + + +def test_agent_cannot_touch_foreign_command(hub_server_two_modules): + """I-1: токен модуля не читает и не закрывает команды чужого модуля.""" + h = hub_server_two_modules + jira, stub = h["agents"]["jira"], h["agents"]["stub"] + conn = h["hub"].conn() + try: + queue.create_batch(conn, "w", "t", [{"type": "stub_cmd", "params": {}}]) + queue.create_batch(conn, "j", "t", [{"type": "ensure_issue", + "params": {"temp_key": "new:1", "issue_type": "task", "summary": "Тема"}}]) + finally: + conn.close() + jc = jira.post("/agent/claim", {})["command"] + sc = stub.post("/agent/claim", {})["command"] + assert jc["type"] == "ensure_issue" and sc["type"] == "stub_cmd" + for call in (lambda: stub.get(f"/agent/commands/{jc['id']}"), + lambda: stub.post(f"/agent/commands/{jc['id']}/result", {"status": "failed"}), + lambda: jira.get(f"/agent/commands/{sc['id']}"), + lambda: jira.post(f"/agent/commands/{sc['id']}/result", {"status": "failed"})): + with pytest.raises(HubError) as e: + call() + assert e.value.status == 404 + assert jira.get(f"/agent/commands/{jc['id']}")["id"] == jc["id"] + assert stub.post(f"/agent/commands/{sc['id']}/result", {"status": "done", "result": {}})["status"] == "done"