Summary
test_request_bodies_use_extra_forbid is parametrized over every Request model and asserts model_config['extra'] == 'forbid' — but that's a config-level assertion, not behavioral. The actual behavioral assertion (constructing the model with a phantom kwarg raises ValidationError) is only spot-checked for CreateOrderRequest (test_forbid_extra_rejects_unknown_kwarg).
For all other request models (AmendOrderRequest, DecreaseOrderRequest, BatchCreate*, CreateOrderGroupRequest, UpdateOrderGroupLimitRequest, CreateRFQRequest, CreateQuoteRequest, AcceptQuoteRequest, ApplySubaccountTransferRequest, UpdateSubaccountNettingRequest, CreateApiKeyRequest, GenerateApiKeyRequest, all V2 order request models, etc.), there is no test that constructs the model with a phantom field and asserts ValidationError.
A model that accidentally sets extra='allow' AND has a typo in a field name would slip both gates: the config test catches the first miss, but if a contributor changes the config they may also re-add the field name with a typo elsewhere, and the per-model phantom test would catch only the second miss.
Location
tests/test_model_extra_policy.py:60-69 — config-level only
tests/test_orders.py / tests/test_async_orders.py — CreateOrderRequest-only spot check
tests/test_models.py:903 — CreateOrderRequest-only
Recommended fix
Add a single parametrized behavioral test that iterates the existing _REQUEST_MODELS collection, instantiates each model with minimal valid required kwargs plus ghost_field='x', and asserts pydantic.ValidationError:
import pytest
from pydantic import ValidationError
@pytest.mark.parametrize("model_cls", _REQUEST_MODELS, ids=lambda c: c.__name__)
def test_request_model_rejects_phantom_field(model_cls, minimal_kwargs):
valid = minimal_kwargs(model_cls)
with pytest.raises(ValidationError) as exc:
model_cls(**valid, ghost_field="x")
assert any(err["type"] == "extra_forbidden" for err in exc.value.errors())
minimal_kwargs(model_cls) can use model_cls.model_fields to compute required kwargs from defaults / annotations, or maintain a small fixture map for the ones that can't be auto-derived.
This pairs with the existing config check and pins behavior in addition to configuration.
Severity & category
medium / testing
Summary
test_request_bodies_use_extra_forbidis parametrized over every Request model and assertsmodel_config['extra'] == 'forbid'— but that's a config-level assertion, not behavioral. The actual behavioral assertion (constructing the model with a phantom kwarg raisesValidationError) is only spot-checked forCreateOrderRequest(test_forbid_extra_rejects_unknown_kwarg).For all other request models (
AmendOrderRequest,DecreaseOrderRequest,BatchCreate*,CreateOrderGroupRequest,UpdateOrderGroupLimitRequest,CreateRFQRequest,CreateQuoteRequest,AcceptQuoteRequest,ApplySubaccountTransferRequest,UpdateSubaccountNettingRequest,CreateApiKeyRequest,GenerateApiKeyRequest, all V2 order request models, etc.), there is no test that constructs the model with a phantom field and assertsValidationError.A model that accidentally sets
extra='allow'AND has a typo in a field name would slip both gates: the config test catches the first miss, but if a contributor changes the config they may also re-add the field name with a typo elsewhere, and the per-model phantom test would catch only the second miss.Location
tests/test_model_extra_policy.py:60-69— config-level onlytests/test_orders.py/tests/test_async_orders.py—CreateOrderRequest-only spot checktests/test_models.py:903—CreateOrderRequest-onlyRecommended fix
Add a single parametrized behavioral test that iterates the existing
_REQUEST_MODELScollection, instantiates each model with minimal valid required kwargs plusghost_field='x', and assertspydantic.ValidationError:minimal_kwargs(model_cls)can usemodel_cls.model_fieldsto compute required kwargs from defaults / annotations, or maintain a small fixture map for the ones that can't be auto-derived.This pairs with the existing config check and pins behavior in addition to configuration.
Severity & category
medium / testing