Skip to content

The four inference request models do not forbid unknown fields; every other one does #466

Description

@JArmandoAnaya

Every request model in server/models.py sets model_config = ConfigDict(extra="forbid") except the four the inference slices added. On those four, a body carrying a field the model does not declare is silently ignored instead of refused.

Model extra
AnnotationCreate, AnnotationUpdate forbid
BatchCreate, ProjectCreate, ReleaseCreate, SchemaVersionCreate forbid
ConnectionCreate, ConnectionUpdate (pydantic default — ignore)
SuggestPoint, SuggestRequest (pydantic default — ignore)

Found while removing the dead detail field (cf. #463), where the question "what does this wire do with an unexpected field?" had to be answered before the removal could be called behaviour-preserving. Nothing in the code or the docstrings records the omission as deliberate — the six models that forbid carry a bare model_config line with no comment, so there is no stated rule the four are an exception to.

Why it is worth closing

forbid is what turns a client's typo into a 422 instead of a silent no-op. On these four routes:

  • {"model_revision": "..."} misspelled on a connection update is accepted, changes nothing, and answers 200 with the old value — the caller has no way to tell it did not take.
  • A field removed from the contract goes on being accepted forever, which is the shape #463 was in: detail had been accepted and ignored since it shipped.

The second point cuts both ways and is the reason this is worth a decision rather than a reflex. Because SuggestRequest ignores extras today, removing detail was invisible to any caller still sending it. Tightening to forbid would make that same caller start getting a 422 — so the change is only free while no client depends on the laxness.

What it needs

A decision on whether the four join the convention, and if so a ConfigDict(extra="forbid") on each plus one test per model proving an undeclared field is refused. openapi.json moves too — forbid emits additionalProperties: false — so the contract and the generated client are part of the diff.

Metadata

Metadata

Assignees

No one assigned

    Labels

    apivisionset.server — REST API and OpenAPI contractbackendvisionset Python distribution — kernel, server, cli, mcp, formats

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions