"""Focused tests for the extension sidecar proxy contract.""" from types import SimpleNamespace import io import json import urllib.request import pytest class FakeHandler: def __init__(self, body: bytes = b""): self.status = None self.headers = {} self.sent_headers = [] self.body = bytearray() self.wfile = self self.rfile = io.BytesIO(body) def send_response(self, status): self.status = status def send_header(self, name, value): self.sent_headers.append((name, value)) def end_headers(self): pass def write(self, data): self.body.extend(data) def header(self, name): for key, value in self.sent_headers: if key.lower() == name.lower(): return value return None @pytest.fixture(autouse=True) def _clear_extension_env(monkeypatch): from api import auth as auth_mod for name in ( "HERMES_WEBUI_EXTENSION_DIR", "HERMES_WEBUI_EXTENSION_MANIFEST", "HERMES_WEBUI_PASSWORD", ): monkeypatch.delenv(name, raising=False) auth_mod._invalidate_password_hash_cache() yield auth_mod._invalidate_password_hash_cache() def _use_extension_state_dir(monkeypatch, tmp_path): tmp_path.mkdir(parents=True, exist_ok=True) state_dir = tmp_path / "webui-state" state_dir.mkdir() monkeypatch.setenv("HERMES_WEBUI_STATE_DIR", str(state_dir)) import api.extensions as extensions monkeypatch.setattr(extensions, "_extension_state_dir", lambda: state_dir) return state_dir def _write_manifest(root, payload): (root / "extensions.json").write_text(json.dumps(payload), encoding="utf-8") def _configure_manifest_extension(monkeypatch, tmp_path, payload): state_dir = _use_extension_state_dir(monkeypatch, tmp_path) root = tmp_path / "extensions" root.mkdir(parents=True, exist_ok=True) _write_manifest(root, payload) monkeypatch.setenv("HERMES_WEBUI_EXTENSION_DIR", str(root)) monkeypatch.setenv("HERMES_WEBUI_EXTENSION_MANIFEST", "extensions.json") return state_dir, root def test_extension_sidecar_proxy_requires_webui_auth(monkeypatch): monkeypatch.setenv("HERMES_WEBUI_PASSWORD", "test-password") from api.auth import check_auth handler = FakeHandler() assert check_auth( handler, SimpleNamespace(path="/api/extensions/templates/sidecar/health", query=""), ) is False assert handler.status == 401 assert handler.header("Location") is None def test_extension_sidecar_proxy_requires_consent_and_reconfirms_after_origin_change( tmp_path, monkeypatch ): state_dir, root = _configure_manifest_extension( monkeypatch, tmp_path, { "extensions": [ { "id": "templates", "sidecar": { "type": "loopback", "origin": "http://127.0.0.1:17787", }, } ] }, ) from api.extensions import ( ExtensionSidecarProxyError, resolve_extension_sidecar_proxy_target, set_extension_sidecar_proxy_consent, ) with pytest.raises(ExtensionSidecarProxyError) as unapproved: resolve_extension_sidecar_proxy_target("templates", "v1/ping", "debug=1") assert unapproved.value.status == 403 approved = set_extension_sidecar_proxy_consent("templates", True) assert approved["sidecars"][0]["proxy"]["consented"] is True assert json.loads((state_dir / "extension-overrides.json").read_text(encoding="utf-8")) == { "version": 1, "disabled_extensions": [], "sidecar_proxy_consents": { "templates": "http://127.0.0.1:17787", }, } target = resolve_extension_sidecar_proxy_target("templates", "v1/ping", "debug=1") assert target == { "extension_id": "templates", "origin": "http://127.0.0.1:17787", "proxy_path": "/api/extensions/templates/sidecar/", "upstream_url": "http://127.0.0.1:17787/v1/ping?debug=1", } encoded_target = resolve_extension_sidecar_proxy_target("templates", "v1%2Fprivate") assert encoded_target["upstream_url"] == "http://127.0.0.1:17787/v1%2Fprivate" _write_manifest( root, { "extensions": [ { "id": "templates", "sidecar": { "type": "loopback", "origin": "http://127.0.0.1:17788", }, } ] }, ) changed = set_extension_sidecar_proxy_consent("templates", False) assert changed["sidecars"][0]["proxy"]["origin_changed"] is False with pytest.raises(ExtensionSidecarProxyError) as changed_origin: resolve_extension_sidecar_proxy_target("templates", "v1/ping") assert changed_origin.value.status == 403 def test_extension_sidecar_proxy_rejects_unavailable_surfaces(tmp_path, monkeypatch): from api.extensions import ExtensionSidecarProxyError, resolve_extension_sidecar_proxy_target _configure_manifest_extension( monkeypatch, tmp_path / "duplicate", { "extensions": [ { "id": "templates", "sidecar": { "type": "loopback", "origin": "http://127.0.0.1:17787", }, }, { "id": "templates", "sidecar": { "type": "loopback", "origin": "http://127.0.0.1:17788", }, }, ] }, ) with pytest.raises(ExtensionSidecarProxyError) as duplicate: resolve_extension_sidecar_proxy_target("templates", "v1/ping") assert duplicate.value.status == 409 _configure_manifest_extension( monkeypatch, tmp_path / "manifest_disabled", { "extensions": [ { "id": "templates", "enabled": False, "sidecar": { "type": "loopback", "origin": "http://127.0.0.1:17787", }, } ] }, ) with pytest.raises(ExtensionSidecarProxyError) as manifest_disabled: resolve_extension_sidecar_proxy_target("templates", "v1/ping") assert manifest_disabled.value.status == 409 state_dir, _root = _configure_manifest_extension( monkeypatch, tmp_path / "user_disabled", { "extensions": [ { "id": "templates", "sidecar": { "type": "loopback", "origin": "http://127.0.0.1:17787", }, } ] }, ) (state_dir / "extension-overrides.json").write_text( json.dumps( { "version": 1, "disabled_extensions": ["templates"], "sidecar_proxy_consents": { "templates": "http://127.0.0.1:17787", }, } ), encoding="utf-8", ) with pytest.raises(ExtensionSidecarProxyError) as user_disabled: resolve_extension_sidecar_proxy_target("templates", "v1/ping") assert user_disabled.value.status == 409 _configure_manifest_extension( monkeypatch, tmp_path / "unsupported", { "extensions": [ { "id": "templates", "sidecar": { "type": "unix-socket", "origin": "http://127.0.0.1:17787", }, } ] }, ) with pytest.raises(ExtensionSidecarProxyError) as unsupported: resolve_extension_sidecar_proxy_target("templates", "v1/ping") assert unsupported.value.status == 409 def test_extension_sidecar_proxy_malformed_consents_fail_closed(tmp_path, monkeypatch): from api.extensions import ExtensionSidecarProxyError, resolve_extension_sidecar_proxy_target state_dir, _root = _configure_manifest_extension( monkeypatch, tmp_path / "malformed_consents", { "extensions": [ { "id": "templates", "sidecar": { "type": "loopback", "origin": "http://127.0.0.1:17787", }, } ] }, ) (state_dir / "extension-overrides.json").write_text( json.dumps( { "version": 1, "disabled_extensions": [], "sidecar_proxy_consents": { "templates": "http://127.0.0.1:17787", "../bad": "http://127.0.0.1:17788", }, } ), encoding="utf-8", ) with pytest.raises(ExtensionSidecarProxyError) as exc: resolve_extension_sidecar_proxy_target("templates", "v1/ping") assert exc.value.status == 403 def test_extension_sidecar_proxy_route_uses_shared_resolver_and_strips_headers(monkeypatch): from api import routes captured = {} class FakeResponse: def __init__(self): self.status = 202 self.headers = { "Content-Type": "application/json", "Set-Cookie": "sidecar=1", "Connection": "close, X-Upstream-Hop", "X-Sidecar": "ok", "X-Upstream-Hop": "strip-me", } def read(self, *_args): return b'{"ok":true}' def __enter__(self): return self def __exit__(self, exc_type, exc, tb): return False class FakeOpener: def open(self, request, timeout=10): captured["url"] = request.full_url captured["method"] = request.get_method() captured["data"] = request.data captured["headers"] = {k.lower(): v for k, v in request.header_items()} captured["timeout"] = timeout return FakeResponse() monkeypatch.setattr(routes, "_check_csrf", lambda handler: True) monkeypatch.setattr( "api.extensions.resolve_extension_sidecar_proxy_target", lambda extension_id, proxy_path, query="": { "extension_id": extension_id, "origin": "http://127.0.0.1:17787", "proxy_path": "/api/extensions/templates/sidecar/", "upstream_url": f"http://127.0.0.1:17787/{proxy_path}?{query}", }, ) monkeypatch.setattr( routes, "_extension_sidecar_proxy_same_origin_opener", lambda allowed_origin: FakeOpener(), ) raw_body = b'{"ping":"pong"}' handler = FakeHandler(raw_body) handler.headers = { "Accept": "application/json", "If-None-Match": '"abc123"', "Range": "bytes=0-64", "Content-Type": "application/json", "Content-Length": str(len(raw_body)), "Cookie": "webui=secret", "Authorization": "Bearer secret", "Host": "webui.local", "Origin": "http://webui.local", "Referer": "http://webui.local/settings", "X-CSRF-Token": "secret", "X-Sidecar-Auth": "local-token", "Connection": "keep-alive, X-Client-Hop", "X-Client-Hop": "strip-me", } result = routes.handle_post( handler, SimpleNamespace(path="/api/extensions/templates/sidecar/v1/ping", query="debug=1"), ) assert result is True assert captured == { "url": "http://127.0.0.1:17787/v1/ping?debug=1", "method": "POST", "data": raw_body, "headers": { "accept": "application/json", "content-type": "application/json", "if-none-match": '"abc123"', "range": "bytes=0-64", "x-sidecar-auth": "local-token", }, "timeout": 10, } assert handler.status == 202 assert handler.body == b'{"ok":true}' assert handler.header("Content-Type") == "application/json" assert handler.header("X-Sidecar") == "ok" assert handler.header("Set-Cookie") is None assert handler.header("Connection") is None assert handler.header("X-Upstream-Hop") is None def test_extension_sidecar_proxy_get_rejects_cross_site_browser_request(monkeypatch): from api import routes monkeypatch.setattr( "api.extensions.resolve_extension_sidecar_proxy_target", lambda extension_id, proxy_path, query="": { "extension_id": extension_id, "origin": "http://127.0.0.1:17787", "proxy_path": "/api/extensions/templates/sidecar/", "upstream_url": "http://127.0.0.1:17787/v1/ping", }, ) handler = FakeHandler() handler.headers = { "Origin": "https://evil.example", "Host": "webui.local", "Sec-Fetch-Site": "cross-site", } result = routes.handle_get( handler, SimpleNamespace(path="/api/extensions/templates/sidecar/v1/ping", query=""), ) assert result is None assert handler.status == 403 assert json.loads(handler.body.decode("utf-8")) == { "error": "Cross-origin mismatch - check reverse proxy headers" } def test_extension_sidecar_proxy_get_requires_browser_provenance(monkeypatch): from api import routes monkeypatch.setattr( "api.extensions.resolve_extension_sidecar_proxy_target", lambda extension_id, proxy_path, query="": { "extension_id": extension_id, "origin": "http://127.0.0.1:17787", "proxy_path": "/api/extensions/templates/sidecar/", "upstream_url": "http://127.0.0.1:17787/v1/ping", }, ) handler = FakeHandler() result = routes.handle_get( handler, SimpleNamespace(path="/api/extensions/templates/sidecar/v1/ping", query=""), ) assert result is None assert handler.status == 403 assert json.loads(handler.body.decode("utf-8")) == { "error": "Cross-origin mismatch - check reverse proxy headers" } def test_extension_sidecar_proxy_post_requires_browser_provenance(monkeypatch): """Regression (#5228 gate): unsafe methods must require the same browser provenance as GET. Before the fix only GET enforced require_provenance, so a headerless (non-browser) POST fell through the CSRF compatibility path that intentionally admits Origin/Referer-less clients — giving POST/PATCH/PUT/ DELETE weaker provenance than GET on the loopback proxy route.""" from api import routes # If provenance were NOT enforced, the resolver/opener would be reached; make # them explode so any regression that lets a headerless POST through fails # loudly instead of silently proxying. def _boom(*_args, **_kwargs): raise AssertionError("headerless POST must be rejected before proxying") monkeypatch.setattr("api.extensions.resolve_extension_sidecar_proxy_target", _boom) monkeypatch.setattr( routes, "_extension_sidecar_proxy_same_origin_opener", _boom ) handler = FakeHandler(b'{"ping":"pong"}') # No Origin / Referer / Sec-Fetch-Site — a non-browser client. handler.headers = {"Content-Type": "application/json", "Content-Length": "15"} result = routes.handle_post( handler, SimpleNamespace(path="/api/extensions/templates/sidecar/v1/ping", query=""), ) assert result is None assert handler.status == 403 assert json.loads(handler.body.decode("utf-8")) == { "error": "Cross-origin mismatch - check reverse proxy headers" } def test_extension_sidecar_proxy_get_allows_same_origin_browser_request_without_csrf_token(monkeypatch): from api import routes class FakeResponse: def __init__(self): self.status = 200 self.headers = {"Content-Type": "application/json"} def read(self, *_args): return b'{"ok":true}' def __enter__(self): return self def __exit__(self, exc_type, exc, tb): return False class FakeOpener: def open(self, request, timeout=10): return FakeResponse() monkeypatch.setattr( "api.extensions.resolve_extension_sidecar_proxy_target", lambda extension_id, proxy_path, query="": { "extension_id": extension_id, "origin": "http://127.0.0.1:17787", "proxy_path": "/api/extensions/templates/sidecar/", "upstream_url": "http://127.0.0.1:17787/v1/ping", }, ) monkeypatch.setattr( routes, "_extension_sidecar_proxy_same_origin_opener", lambda allowed_origin: FakeOpener(), ) handler = FakeHandler() handler.headers = { "Origin": "http://webui.local", "Host": "webui.local", "Sec-Fetch-Site": "same-origin", } result = routes.handle_get( handler, SimpleNamespace(path="/api/extensions/templates/sidecar/v1/ping", query=""), ) assert result is True assert handler.status == 200 assert json.loads(handler.body.decode("utf-8")) == {"ok": True} def test_extension_sidecar_proxy_route_preserves_upstream_http_errors(monkeypatch): from api import routes from urllib.error import HTTPError monkeypatch.setattr( "api.extensions.resolve_extension_sidecar_proxy_target", lambda extension_id, proxy_path, query="": { "extension_id": extension_id, "origin": "http://127.0.0.1:17787", "proxy_path": "/api/extensions/templates/sidecar/", "upstream_url": "http://127.0.0.1:17787/v1/ping", }, ) class ErrorHeaders(dict): pass error = HTTPError( "http://127.0.0.1:17787/v1/ping", 418, "teapot", ErrorHeaders({"Content-Type": "text/plain", "Set-Cookie": "drop=1"}), io.BytesIO(b"sidecar said no"), ) class FakeOpener: def open(self, request, timeout=10): raise error monkeypatch.setattr( routes, "_extension_sidecar_proxy_same_origin_opener", lambda allowed_origin: FakeOpener(), ) handler = FakeHandler() handler.headers = { "Origin": "http://webui.local", "Host": "webui.local", "Sec-Fetch-Site": "same-origin", } result = routes.handle_get( handler, SimpleNamespace(path="/api/extensions/templates/sidecar/v1/ping", query=""), ) assert result is True assert handler.status == 418 assert handler.body == b"sidecar said no" assert handler.header("Content-Type") == "text/plain" assert handler.header("Set-Cookie") is None def test_extension_sidecar_proxy_get_rejects_sec_fetch_same_origin_without_origin(monkeypatch): from api import routes monkeypatch.setattr( "api.extensions.resolve_extension_sidecar_proxy_target", lambda extension_id, proxy_path, query="": { "extension_id": extension_id, "origin": "http://127.0.0.1:17787", "proxy_path": "/api/extensions/templates/sidecar/", "upstream_url": "http://127.0.0.1:17787/v1/ping", }, ) handler = FakeHandler() handler.headers = { "Host": "webui.local", "Sec-Fetch-Site": "same-origin", } result = routes.handle_get( handler, SimpleNamespace(path="/api/extensions/templates/sidecar/v1/ping", query=""), ) assert result is None assert handler.status == 403 assert json.loads(handler.body.decode("utf-8")) == { "error": "Cross-origin mismatch - check reverse proxy headers" } def test_extension_sidecar_proxy_get_allows_top_level_navigation_provenance(monkeypatch): from api import routes class FakeResponse: def __init__(self): self.status = 200 self.headers = {"Content-Type": "application/json"} def read(self, *_args): return b'{"ok":true}' def __enter__(self): return self def __exit__(self, exc_type, exc, tb): return False class FakeOpener: def open(self, request, timeout=10): return FakeResponse() monkeypatch.setattr( "api.extensions.resolve_extension_sidecar_proxy_target", lambda extension_id, proxy_path, query="": { "extension_id": extension_id, "origin": "http://127.0.0.1:17787", "proxy_path": "/api/extensions/templates/sidecar/", "upstream_url": "http://127.0.0.1:17787/v1/ping", }, ) monkeypatch.setattr( routes, "_extension_sidecar_proxy_same_origin_opener", lambda allowed_origin: FakeOpener(), ) handler = FakeHandler() handler.headers = { "Host": "webui.local", "Sec-Fetch-Site": "none", } result = routes.handle_get( handler, SimpleNamespace(path="/api/extensions/templates/sidecar/v1/ping", query=""), ) assert result is True assert handler.status == 200 assert json.loads(handler.body.decode("utf-8")) == {"ok": True} def test_extension_sidecar_proxy_route_rejects_oversized_upstream_response(monkeypatch): from api import routes monkeypatch.setattr( "api.extensions.resolve_extension_sidecar_proxy_target", lambda extension_id, proxy_path, query="": { "extension_id": extension_id, "origin": "http://127.0.0.1:17787", "proxy_path": "/api/extensions/templates/sidecar/", "upstream_url": "http://127.0.0.1:17787/v1/ping", }, ) class FakeResponse: def __init__(self): self.status = 200 self.headers = {"Content-Type": "application/octet-stream"} def read(self, size=-1): assert size == routes._EXTENSION_SIDECAR_PROXY_MAX_RESPONSE_BYTES + 1 return b"x" * size def __enter__(self): return self def __exit__(self, exc_type, exc, tb): return False class FakeOpener: def open(self, request, timeout=10): return FakeResponse() monkeypatch.setattr( routes, "_extension_sidecar_proxy_same_origin_opener", lambda allowed_origin: FakeOpener(), ) handler = FakeHandler() handler.headers = { "Origin": "http://webui.local", "Host": "webui.local", "Sec-Fetch-Site": "same-origin", } result = routes.handle_get( handler, SimpleNamespace(path="/api/extensions/templates/sidecar/v1/ping", query=""), ) assert result is None assert handler.status == 502 assert json.loads(handler.body.decode("utf-8")) == { "error": "Extension sidecar response too large" } def test_extension_sidecar_proxy_route_rejects_oversized_upstream_http_error(monkeypatch): from api import routes from urllib.error import HTTPError monkeypatch.setattr( "api.extensions.resolve_extension_sidecar_proxy_target", lambda extension_id, proxy_path, query="": { "extension_id": extension_id, "origin": "http://127.0.0.1:17787", "proxy_path": "/api/extensions/templates/sidecar/", "upstream_url": "http://127.0.0.1:17787/v1/ping", }, ) class OversizedBody(io.BytesIO): def read(self, size=-1): assert size == routes._EXTENSION_SIDECAR_PROXY_MAX_RESPONSE_BYTES + 1 return b"x" * size error = HTTPError( "http://127.0.0.1:17787/v1/ping", 502, "bad gateway", {}, OversizedBody(), ) class FakeOpener: def open(self, request, timeout=10): raise error monkeypatch.setattr( routes, "_extension_sidecar_proxy_same_origin_opener", lambda allowed_origin: FakeOpener(), ) handler = FakeHandler() handler.headers = { "Origin": "http://webui.local", "Host": "webui.local", "Sec-Fetch-Site": "same-origin", } result = routes.handle_get( handler, SimpleNamespace(path="/api/extensions/templates/sidecar/v1/ping", query=""), ) assert result is None assert handler.status == 502 assert json.loads(handler.body.decode("utf-8")) == { "error": "Extension sidecar response too large" } def test_extension_sidecar_proxy_route_returns_sanitized_502(monkeypatch): from api import routes monkeypatch.setattr( "api.extensions.resolve_extension_sidecar_proxy_target", lambda extension_id, proxy_path, query="": { "extension_id": extension_id, "origin": "http://127.0.0.1:17787", "proxy_path": "/api/extensions/templates/sidecar/", "upstream_url": "http://127.0.0.1:17787/v1/ping", }, ) class FakeOpener: def open(self, request, timeout=10): raise OSError("no route") monkeypatch.setattr( routes, "_extension_sidecar_proxy_same_origin_opener", lambda allowed_origin: FakeOpener(), ) handler = FakeHandler() handler.headers = { "Origin": "http://webui.local", "Host": "webui.local", "Sec-Fetch-Site": "same-origin", } result = routes.handle_get( handler, SimpleNamespace(path="/api/extensions/templates/sidecar/v1/ping", query=""), ) assert result is None assert handler.status == 502 assert json.loads(handler.body.decode("utf-8")) == { "error": "Failed to reach extension sidecar" } def test_extension_sidecar_proxy_redirect_guard_preserves_origin_only(): from api import routes assert routes._extension_sidecar_proxy_redirect_url( "http://127.0.0.1:17787", "http://127.0.0.1:17787/v1/ping", "/v1/next?debug=1", ) == "http://127.0.0.1:17787/v1/next?debug=1" assert routes._extension_sidecar_proxy_redirect_url( "http://127.0.0.1:17787", "http://127.0.0.1:17787/v1/ping", "http://evil.example/steal", ) is None assert routes._extension_sidecar_proxy_redirect_url( "http://127.0.0.1:17787", "http://127.0.0.1:17787/v1/ping", "http://127.0.0.1:17788/other-port", ) is None assert routes._extension_sidecar_proxy_redirect_url( "http://localhost", "http://localhost/v1/ping", "http://LOCALHOST:80/v1/next", ) == "http://LOCALHOST:80/v1/next" assert routes._extension_sidecar_proxy_redirect_url( "https://localhost:443", "https://localhost/v1/ping", "https://localhost/v1/next", ) == "https://localhost/v1/next" def test_extension_sidecar_proxy_route_uses_same_origin_redirect_opener(monkeypatch): from api import routes captured = {} class FakeResponse: status = 200 headers = {"Content-Type": "application/json"} def read(self, *_args): return b'{"ok":true}' def __enter__(self): return self def __exit__(self, exc_type, exc, tb): return False class FakeOpener: def open(self, request, timeout=10): captured["url"] = request.full_url captured["timeout"] = timeout return FakeResponse() monkeypatch.setattr( "api.extensions.resolve_extension_sidecar_proxy_target", lambda extension_id, proxy_path, query="": { "extension_id": extension_id, "origin": "http://127.0.0.1:17787", "proxy_path": "/api/extensions/templates/sidecar/", "upstream_url": "http://127.0.0.1:17787/v1/ping", }, ) monkeypatch.setattr( routes, "_extension_sidecar_proxy_same_origin_opener", lambda allowed_origin: ( captured.__setitem__("allowed_origin", allowed_origin), FakeOpener(), )[1], ) handler = FakeHandler() handler.headers = { "Origin": "http://webui.local", "Host": "webui.local", "Sec-Fetch-Site": "same-origin", } result = routes.handle_get( handler, SimpleNamespace(path="/api/extensions/templates/sidecar/v1/ping", query=""), ) assert result is True assert captured == { "allowed_origin": "http://127.0.0.1:17787", "url": "http://127.0.0.1:17787/v1/ping", "timeout": 10, } assert handler.status == 200 assert handler.body == b'{"ok":true}' def test_extension_sidecar_proxy_opener_disables_ambient_proxies(monkeypatch): from api import routes captured = {} def fake_build_opener(*handlers): captured["handlers"] = handlers return object() monkeypatch.setattr(routes, "build_opener", fake_build_opener) opener = routes._extension_sidecar_proxy_same_origin_opener("http://127.0.0.1:17787") assert opener is not None proxy_handlers = [ handler for handler in captured["handlers"] if isinstance(handler, urllib.request.ProxyHandler) ] assert len(proxy_handlers) == 1 assert proxy_handlers[0].proxies == {} def test_extension_sidecar_proxy_consent_route_is_wired(monkeypatch): from api import routes captured = {} def fake_j(handler, data, status=200, headers=None): captured["data"] = data captured["status"] = status return True monkeypatch.setattr(routes, "_check_csrf", lambda handler: True) monkeypatch.setattr(routes, "read_body", lambda handler: {"id": "templates", "approved": True}) monkeypatch.setattr(routes, "j", fake_j) monkeypatch.setattr( "api.extensions.set_extension_sidecar_proxy_consent", lambda extension_id, approved: { "ok": True, "id": extension_id, "approved": approved, }, ) handler = FakeHandler() assert routes.handle_post( handler, SimpleNamespace(path="/api/extensions/sidecar-proxy-consent"), ) is True assert captured == { "status": 200, "data": {"ok": True, "id": "templates", "approved": True}, }