feat(major2): the hosted surface refuses the proposal review by name and points at the CLI [skip-docs]

Ordre 20260904T173146Z-8102814273-from-portfolio-optimiser, steg 7 av 10.

En PRE-whitelist-sjekk paa raa payload, ETTER isinstance-vakten (en ikke-objekt-body skal
beholde sin 400, ikke bli en 500) og FOER den generiske unknown-field-sjekken, som ellers
ville svart foerst.

Plasseringen er MAALT, ikke valgt: _CONSUMED_FIELDS maa vaere disjunkt fra run_projects
parametre (Fase 4es negative halvdel) mens proposal_reviewer ER en av dem, saa navnet kan
ikke bo i noen av de tre listene. F4-presedensen er IKKE analog - enable_plan_review er en
NOESTET noekkel inne i det whitelistede explore_contract, som er derfor den kan navngis der.

DISKRIMINATOREN ER TEKSTEN, IKKE STATUSEN: whitelisten svarer alt enhver ukjent nokkel med
400 "unknown field(s)", saa en detachet navngitt nekt ville fortsatt gitt 400 med feltnavnet.
Den navngitte meldingen peker paa CLI-doera og paa /readiness, og kontrollen (et ordinaert
ukjent felt) asserterer at den generiske meldingen deler ingenting av det.

Null run_project-kall, ikke bare en 400 (oekt 57).

_response_payload er IKKE utvidet: flaten nekter revieweren, saa feltet kunne kun vaert tomt.

RODT foer impl: tre armer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-05 07:09:57 +02:00
commit bfc634d806
2 changed files with 80 additions and 2 deletions

View file

@ -98,6 +98,15 @@ _OPTIONAL_FIELDS = (
#: a real ``run_project`` parameter, and every consumed field must not be.
_CONSUMED_FIELDS = ("explore_prompt", "explore_contract")
_ALLOWED_FIELDS = frozenset(_REQUIRED_FIELDS + _OPTIONAL_FIELDS + _CONSUMED_FIELDS)
#: Names refused BY NAME on the raw payload, before the generic unknown-field check (MAJOR-2).
#:
#: A pre-whitelist check rather than a fourth list entry, and the placement is MEASURED.
#: ``_CONSUMED_FIELDS`` must be disjoint from ``run_project``'s parameters (Fase 4e's negative
#: half) while ``proposal_reviewer`` IS one; and the generic ``unknown field(s)`` refusal below
#: fires FIRST, so a name left to it would return the same 400 with a message that says nothing
#: about where the door actually is. The F4 precedent is NOT analogous: ``enable_plan_review`` is
#: a NESTED key inside the whitelisted ``explore_contract``, which is why it can be named there.
_REFUSED_BY_NAME = ("proposal_review",)
_REASONS = {
200: "OK",
400: "Bad Request",
@ -130,6 +139,15 @@ def _run_kwargs(payload: Any) -> tuple[str, dict[str, Any], dict[str, Any]]:
which the container answers as a 500 for what is really a wiring mistake."""
if not isinstance(payload, dict):
raise InvocationRefused("body must be a JSON object")
# AFTER the object guard (a non-object body must keep its 400 rather than become a 500) and
# BEFORE the generic unknown-field check, which would otherwise answer this one first.
if "proposal_review" in payload:
raise InvocationRefused(
"proposal_review: this surface has no terminal to answer a proposal review — the "
"synchronous door would block the request on nobody, and would block the event loop "
"that answers /readiness while doing it. The operator door is the CLI's "
"--proposal-review"
)
unknown = sorted(set(payload) - _ALLOWED_FIELDS)
if unknown:
raise InvocationRefused(f"unknown field(s): {', '.join(unknown)}")