fix: execute local reins through the sandbox owner
Some checks failed
ci / validate (push) Has been cancelled
Some checks failed
ci / validate (push) Has been cancelled
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0726e-5232-73f2-aaca-2c05ceb62efb
This commit is contained in:
parent
92392f75f1
commit
63a7f9f160
14 changed files with 463 additions and 81 deletions
|
|
@ -1,6 +1,8 @@
|
|||
from datetime import UTC, datetime
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from sandboxer.models import Reachability, SandboxState, SandboxStatus
|
||||
|
||||
from glas_harness.contract import (
|
||||
|
|
@ -14,6 +16,7 @@ from glas_harness.contract import (
|
|||
)
|
||||
from glas_harness.gateway import run_execution, run_task_through_rein
|
||||
from glas_harness.profiles import ProfileCatalog
|
||||
from glas_harness.transport import transport_from_sandbox
|
||||
|
||||
|
||||
PROFILE = "harness.agent-dev-local@1.0.0"
|
||||
|
|
@ -127,6 +130,81 @@ def test_run_execution_creates_and_destroys_sandbox() -> None:
|
|||
assert result.tool_output == "sensitive direct output"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("request_id", ["exact-request", None])
|
||||
def test_owner_commands_preserve_create_identity_routes_and_timeout(request_id):
|
||||
manager = MagicMock()
|
||||
manager.create.return_value = _fake_status()
|
||||
manager.execute.return_value = MagicMock(
|
||||
timed_out=False, output_truncated=False, exit_code=0, stdout="", stderr=""
|
||||
)
|
||||
catalog = _catalog_with_readiness()
|
||||
profile, _ = catalog.resolve(PROFILE)
|
||||
refs = ["proof-route-a", "proof-route-b"]
|
||||
catalog.profiles()[(profile.id, profile.version)] = profile.model_copy(update={
|
||||
"credential_route_refs": refs,
|
||||
"limits": profile.limits.model_copy(update={"timeout_seconds": 7}),
|
||||
})
|
||||
|
||||
class OwnerRein(_FakeRein):
|
||||
def start_session(self, profile, inputs, sandbox):
|
||||
assert "_owner_execute" not in sandbox.model_dump()
|
||||
transport = transport_from_sandbox(sandbox)
|
||||
transport.run(["printf", "%s", "non-secret"], timeout=30)
|
||||
path = transport.write_task_file({"title": "private prompt"})
|
||||
transport.remove_file(path)
|
||||
return super().start_session(profile, inputs, sandbox)
|
||||
|
||||
request = _request().model_copy(update={
|
||||
"request_id": request_id, "actor": "atm", "project": "exact-project"
|
||||
})
|
||||
result = run_execution(request, catalog=catalog, rein=OwnerRein(), manager=manager)
|
||||
assert result.ok
|
||||
create_consumer = manager.create.call_args.args[0].consumer
|
||||
assert create_consumer.actor.value == "atm"
|
||||
assert create_consumer.project == "exact-project"
|
||||
assert create_consumer.run_id == result.evidence.request_id
|
||||
assert create_consumer.session_id is None
|
||||
assert manager.execute.call_count == 3
|
||||
for call in manager.execute.call_args_list:
|
||||
sandbox_id, command = call.args
|
||||
assert sandbox_id == "sbx1"
|
||||
assert command.consumer == create_consumer
|
||||
assert command.credential_route_refs == refs
|
||||
assert command.timeout_seconds == 7
|
||||
writer = manager.execute.call_args_list[1].args[1]
|
||||
assert writer.stdin_text == '{"title": "private prompt"}'
|
||||
assert "private prompt" not in str(writer.command)
|
||||
manager.destroy.assert_called_once_with("sbx1")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("failure", ["refused", "timeout", "truncated", "write"])
|
||||
def test_owner_session_failure_still_destroys_sandbox(failure):
|
||||
from glas_harness.reins.rein_aharness import ReinAharness
|
||||
|
||||
manager = MagicMock()
|
||||
manager.create.return_value = _fake_status()
|
||||
good = MagicMock(timed_out=False, output_truncated=False, exit_code=0,
|
||||
stdout="head-before", stderr="")
|
||||
if failure == "refused":
|
||||
manager.execute.side_effect = PermissionError("owner denied execution")
|
||||
elif failure == "write":
|
||||
manager.execute.side_effect = [good, MagicMock(
|
||||
timed_out=False, output_truncated=False, exit_code=1,
|
||||
stdout="", stderr="task write refused",
|
||||
)]
|
||||
else:
|
||||
manager.execute.return_value = MagicMock(
|
||||
timed_out=failure == "timeout", output_truncated=failure == "truncated"
|
||||
)
|
||||
with patch("glas_harness.transport.subprocess.run") as host_run:
|
||||
result = run_execution(_request(), catalog=_catalog_with_readiness(),
|
||||
rein=ReinAharness(), manager=manager)
|
||||
assert not result.ok
|
||||
assert result.evidence.failure_stage == "session_start"
|
||||
manager.destroy.assert_called_once_with("sbx1")
|
||||
host_run.assert_not_called()
|
||||
|
||||
|
||||
def test_run_execution_normalizes_execution_failure_and_tears_down() -> None:
|
||||
manager = MagicMock()
|
||||
manager.create.return_value = _fake_status()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue