from __future__ import annotations from pathlib import Path import pytest from fastapi.testclient import TestClient from services.runtime import web, worker class _Monitor: def __init__(self, calls: list[str]) -> None: self.calls = calls def probe(self) -> None: self.calls.append("monitor") def test_worker_readiness_reconciles_and_reads_back_public_surface( monkeypatch: pytest.MonkeyPatch, tmp_path: Path ) -> None: calls: list[str] = [] monkeypatch.setenv("HUB_OIDC_ISSUER", "https://issuer.example.test/") monkeypatch.setattr( worker, "reconcile_runtime_state", lambda client, sessions, catalog_root, issuer: calls.append("runtime"), ) monkeypatch.setattr( worker, "reconcile_gitea_public_surface", lambda client, catalog_root: calls.append("surface") or {"status": "pass"}, ) worker._sync_once(object(), object(), tmp_path, _Monitor(calls)) assert calls == ["runtime", "surface", "monitor"] def test_worker_readiness_fails_closed_when_public_surface_does_not_pass( monkeypatch: pytest.MonkeyPatch, tmp_path: Path ) -> None: monkeypatch.setenv("HUB_OIDC_ISSUER", "https://issuer.example.test/") monkeypatch.setattr(worker, "reconcile_runtime_state", lambda *args: None) monkeypatch.setattr( worker, "reconcile_gitea_public_surface", lambda *args: {"status": "degraded"}, ) with pytest.raises(RuntimeError, match="public surface reconciliation did not pass"): worker._sync_once(object(), object(), tmp_path, _Monitor([])) def test_worker_error_detail_identifies_parity_failure_without_leaking_exception_text() -> None: sensitive_value = "do-not-expose-this-token" error = ValueError( "ContextForge gateway itworx-opencode tool inventory parity failed " f"(missing=1, extra=0, token={sensitive_value})" ) detail = worker._safe_error_detail(error) assert detail == "runtime-reconciliation:tool-inventory-parity" assert sensitive_value not in detail def test_worker_error_detail_is_bounded_for_unknown_failures() -> None: detail = worker._safe_error_detail(RuntimeError("private upstream response")) assert detail == "runtime-reconciliation:RuntimeError" assert "private upstream response" not in detail class _UpstreamResponse: def __init__(self, status_code: int) -> None: self.status_code = status_code class _UpstreamClient: statuses: dict[str, int] = {} def __init__(self, *, base_url: str, timeout: int) -> None: self.base_url = base_url async def get(self, path: str) -> _UpstreamResponse: return _UpstreamResponse(self.statuses[f"{self.base_url}{path}"]) async def aclose(self) -> None: return None @pytest.mark.parametrize( ("worker_status", "expected_status"), ((200, 200), (503, 503)), ) def test_public_readiness_is_gated_by_worker_surface_readback( monkeypatch: pytest.MonkeyPatch, tmp_path: Path, worker_status: int, expected_status: int, ) -> None: (tmp_path / "index.html").write_text("", encoding="utf-8") monkeypatch.setenv("HUB_WEB_ROOT", str(tmp_path)) monkeypatch.setenv("HUB_CONTROL_URL", "http://control.test") monkeypatch.setenv("HUB_WORKER_URL", "http://worker.test") _UpstreamClient.statuses = { "http://control.test/ready": 200, "http://worker.test/health/ready": worker_status, } monkeypatch.setattr(web.httpx, "AsyncClient", _UpstreamClient) with TestClient(web.build_app()) as client: response = client.get("/health/ready") assert response.status_code == expected_status assert response.json()["status"] == ("ready" if expected_status == 200 else "not-ready")