#5153: MoA gateway fail-closed routing

This commit is contained in:
nesquena-hermes 2026-07-01 23:24:38 +00:00
parent 651c45614e
commit 36643867f4
2 changed files with 81 additions and 11 deletions

View file

@ -19367,11 +19367,15 @@ def _handle_chat_start(handler, body, diag=None):
if "model_provider" in body
else getattr(s, "model_provider", None)
)
<<<<<<< ours
_pp_provider, _pp_default, _pp_cfg = _read_profile_model_config(s, requested_provider)
=======
>>>>>>> theirs
explicit_model_pick = bool(body.get("explicit_model_pick"))
moa_config = None
gateway_chat_enabled = webui_gateway_chat_enabled(get_config())
if body.get("moa_config"):
if webui_gateway_chat_enabled(get_config()):
if gateway_chat_enabled:
return bad(handler, "MoA override is unavailable on gateway-backed sessions", 409)
from api.commands import resolve_moa_config
@ -19379,6 +19383,7 @@ def _handle_chat_start(handler, body, diag=None):
moa_config = resolve_moa_config()
except RuntimeError as e:
return bad(handler, str(e), 503)
_pp_provider, _pp_default = _read_profile_model_config(s, requested_provider)
diag.stage("resolve_model_provider") if diag else None
model, model_provider, normalized_model = _resolve_compatible_session_model_state(
requested_model,
@ -19401,18 +19406,22 @@ def _handle_chat_start(handler, body, diag=None):
# with start_session_turn so both entry points behave identically
# under runtime_adapter_enabled() / runtime_adapter_runner_enabled()
# — Q-2979-A2 / Copilot discussion_r3305864087/r3305864173).
start_run_kwargs = {
"msg": msg,
"attachments": attachments,
"workspace": workspace,
"model": model,
"model_provider": model_provider,
"normalized_model": normalized_model,
"source": "webui",
"route": "/api/chat/start",
"diag": diag,
}
if not gateway_chat_enabled and moa_config is not None:
start_run_kwargs["moa_config"] = moa_config
response = _start_run(
s,
msg=msg,
attachments=attachments,
workspace=workspace,
model=model,
model_provider=model_provider,
normalized_model=normalized_model,
source="webui",
route="/api/chat/start",
diag=diag,
moa_config=moa_config,
**start_run_kwargs,
)
# Map adapter-selection NotImplementedError (501) onto the legacy
# bad-request response shape that this route exposed historically

View file

@ -127,3 +127,64 @@ def test_moa_config_is_per_turn_not_persisted():
js_source = js_path.read_text(encoding="utf-8")
assert "moa_config:_pendingMoaConfig?true:undefined" in js_source
assert "_pendingMoaConfig=null" in js_source
def test_moa_gateway_chat_start_fails_closed(monkeypatch, tmp_path):
"""Gateway-backed WebUI sessions must reject /moa until the gateway consumes runtime overrides."""
import api.commands as commands
import api.routes as routes
class _Handler:
def __init__(self):
import io
self.status = None
self.response_headers = []
self.wfile = io.BytesIO()
def send_response(self, status):
self.status = status
def send_header(self, key, value):
self.response_headers.append((key, value))
def end_headers(self):
self.response_headers.append(("__end__", ""))
class _Session:
session_id = "sess-moa-gateway"
workspace = str(tmp_path)
model = "gpt-5.5"
model_provider = "openai-codex"
profile = "default"
messages = []
context_messages = []
pending_user_message = None
def start_run(*_args, **_kwargs): # pragma: no cover - should fail before run start
raise AssertionError("gateway-backed /moa must fail closed before starting a run")
def resolve_moa_config(): # pragma: no cover - should fail before resolving MoA
raise AssertionError("gateway-backed /moa must fail before resolving MoA config")
monkeypatch.setattr(routes, "get_session", lambda _sid: _Session())
monkeypatch.setattr(routes, "_resolve_chat_workspace_with_recovery", lambda _s, _w: str(tmp_path))
monkeypatch.setattr(routes, "_start_run", start_run)
monkeypatch.setattr(routes, "get_config", lambda: {"chat_backend": "gateway"})
monkeypatch.setattr(routes, "webui_gateway_chat_enabled", lambda _cfg: True)
monkeypatch.setattr(commands, "resolve_moa_config", resolve_moa_config)
handler = _Handler()
routes._handle_chat_start(
handler,
{
"session_id": "sess-moa-gateway",
"message": "diagnose issue",
"workspace": str(tmp_path),
"moa_config": True,
},
)
body = json.loads(handler.wfile.getvalue().decode("utf-8"))
assert handler.status == 409
assert body["error"] == "MoA override is unavailable on gateway-backed sessions"