mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
fix(release): close the 0.19.0 scan findings — sandbox mongo tag, flow-verb timeout walls, video hardening (#329)
- mongo:8-alpine → mongo:8 (tag never existed; a mongo-opted project could spawn no agents) + a Docker Hub tag-existence e2e guard for every sandbox engine - flow-verb timeouts at both walls: shared SLOW_VERBS policy (i_am_done / submit_up / submit_root / open_pr / i_will_work_on get the 900s server budget); the MCP client now outlasts the server budget (+10s headroom, orchestrator-injected env) so agents receive the middleware's clean 504 envelope instead of dying at the old flat 30s client timeout - cancellation safety: the quality gate kills+reaps its child on CancelledError; create_pr records the PR via a shield-with-wait-out helper so the write can neither be skipped nor race get_db's rollback - video engine: renderer sidecar isolated on a render-only network, 2g/2cpu caps, 570s render watchdog with exit-on-hang, 512MB tar decompression cap, CEO notification on terminal render failure, reject under the approve mutex (fail-closed on Redis-down) - dead python-jose dependency removed (drops ecdsa and its unfixable Minerva advisory PYSEC-2026-1325); panel --font-mono now a real monospace stack Co-authored-by: Renn F <rennf93@users.noreply.github.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from http import HTTPStatus
|
||||
from typing import Any
|
||||
|
||||
@@ -18,6 +19,7 @@ from roboco.api.middleware import (
|
||||
get_status_code,
|
||||
setup_middleware,
|
||||
)
|
||||
from roboco.config import settings
|
||||
from roboco.exceptions import (
|
||||
AuthenticationError,
|
||||
InvalidStateError,
|
||||
@@ -417,3 +419,53 @@ def test_request_validation_handler_log_preserves_non_secret_fields() -> None:
|
||||
assert logged_body["title"] == "visible-title" # non-secret preserved
|
||||
assert logged_body["git_token"] == "***REDACTED***" # secret redacted
|
||||
assert "ghp_secret_xyz" not in str(logged_body)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# FlowVerbTimeoutMiddleware — per-verb budget selection
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _make_flow_app() -> FastAPI:
|
||||
"""Two /api/v1/flow/* routes that each sleep past the fast budget but
|
||||
under the slow one, so the picked timeout is observable by outcome."""
|
||||
app = FastAPI()
|
||||
|
||||
@app.post("/api/v1/flow/developer/give_me_work")
|
||||
async def _normal_verb() -> Any:
|
||||
await asyncio.sleep(0.3)
|
||||
return {"status": "ok"}
|
||||
|
||||
@app.post("/api/v1/flow/developer/i_am_done")
|
||||
async def _slow_verb() -> Any:
|
||||
await asyncio.sleep(0.3)
|
||||
return {"status": "ok"}
|
||||
|
||||
setup_middleware(app)
|
||||
return app
|
||||
|
||||
|
||||
def test_flow_verb_timeout_normal_verb_uses_default_budget(
|
||||
monkeypatch: Any,
|
||||
) -> None:
|
||||
"""A verb outside _SLOW_VERBS keeps the short default budget — a 0.3s
|
||||
handler exceeds a 0.05s budget and comes back as a 504."""
|
||||
monkeypatch.setattr(settings, "flow_verb_timeout_seconds", 0.05)
|
||||
monkeypatch.setattr(settings, "flow_verb_slow_timeout_seconds", 5)
|
||||
|
||||
client = TestClient(_make_flow_app())
|
||||
response = client.post("/api/v1/flow/developer/give_me_work")
|
||||
assert response.status_code == HTTPStatus.GATEWAY_TIMEOUT
|
||||
assert response.json()["error"] == "gateway_timeout"
|
||||
|
||||
|
||||
def test_flow_verb_timeout_slow_verb_uses_slow_budget(monkeypatch: Any) -> None:
|
||||
"""A _SLOW_VERBS verb gets the longer budget — the same 0.3s handler that
|
||||
times out on the default budget completes fine under the slow one."""
|
||||
monkeypatch.setattr(settings, "flow_verb_timeout_seconds", 0.05)
|
||||
monkeypatch.setattr(settings, "flow_verb_slow_timeout_seconds", 5)
|
||||
|
||||
client = TestClient(_make_flow_app())
|
||||
response = client.post("/api/v1/flow/developer/i_am_done")
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert response.json() == {"status": "ok"}
|
||||
|
||||
Reference in New Issue
Block a user