From def6d6fe1b7b1a214bb385500646ffde8fe82019 Mon Sep 17 00:00:00 2001 From: kshitijk4poor <82637225+kshitijk4poor@users.noreply.github.com> Date: Fri, 3 Jul 2026 18:34:23 +0530 Subject: [PATCH] test(cron): regression test for run_one_job secret scope Asserts the behavior contract that run_one_job installs a profile secret scope around run_job under multiplexing (so resolve_runtime_provider's get_secret does not fail-close with UnscopedSecretError) and tears it down afterward. Mutation-verified: fails on unmodified main with the exact UnscopedSecretError, passes with the fix. --- tests/cron/test_run_one_job.py | 43 ++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/tests/cron/test_run_one_job.py b/tests/cron/test_run_one_job.py index 7da6b1c14f4..c8528109d9a 100644 --- a/tests/cron/test_run_one_job.py +++ b/tests/cron/test_run_one_job.py @@ -117,3 +117,46 @@ def test_run_one_job_exception_marks_failure(monkeypatch): assert ok is False assert marks == [("j6", False)] + + +def test_run_one_job_installs_secret_scope_under_multiplex(monkeypatch, tmp_path): + """Regression: under profile isolation (multiplex active), run_one_job must + execute run_job inside a profile secret scope so credential reads + (resolve_runtime_provider -> get_secret) don't fail-close with + UnscopedSecretError, and must tear the scope down afterward. + + Behavior contract: a scope is present during run_job and absent after, + regardless of the concrete secret values. + """ + from agent import secret_scope as ss + + # Point cron's home resolution at a profile whose .env carries a secret. + (tmp_path / ".env").write_text("OPENROUTER_BASE_URL=https://openrouter.ai/api/v1\n") + monkeypatch.setattr(s, "_get_hermes_home", lambda: tmp_path) + + scope_during_run = {} + + def fake_run_job(job): + # This is where resolve_runtime_provider() would read a secret. Prove a + # scope is installed and the profile's secret resolves without raising. + scope_during_run["scope"] = ss.current_secret_scope() + scope_during_run["base_url"] = ss.get_secret("OPENROUTER_BASE_URL") + return (True, "out", "final", None) + + monkeypatch.setattr(s, "run_job", fake_run_job) + monkeypatch.setattr(s, "save_job_output", lambda jid, out: f"/tmp/{jid}.txt") + monkeypatch.setattr(s, "_deliver_result", lambda *a, **k: None) + monkeypatch.setattr(s, "mark_job_run", lambda *a, **k: None) + + ss.set_multiplex_active(True) + try: + ok = s.run_one_job({"id": "j7", "name": "t"}) + finally: + ss.set_multiplex_active(False) + + assert ok is True + # Scope was installed during run_job and the profile secret resolved. + assert scope_during_run["scope"] is not None + assert scope_during_run["base_url"] == "https://openrouter.ai/api/v1" + # And it was torn down after run_one_job returned (no leak). + assert ss.current_secret_scope() is None