From 68688dacbef4484351933e9e527252245f7d9d37 Mon Sep 17 00:00:00 2001 From: Corey Leath Date: Sun, 9 Aug 2026 14:27:42 -0400 Subject: [PATCH 1/3] fix: validate inference feature dimensions --- api/main.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/api/main.py b/api/main.py index 6a45b71..affa456 100644 --- a/api/main.py +++ b/api/main.py @@ -6,7 +6,7 @@ from slowapi.util import get_remote_address from slowapi.errors import RateLimitExceeded from api.inference import run_inference -from pydantic import BaseModel +from pydantic import BaseModel, Field from typing import List, Optional limiter = Limiter(key_func=get_remote_address) @@ -16,8 +16,16 @@ app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler) +FEATURE_DIMENSIONS = 16 + class RequestModel(BaseModel): - features: List[float] + """Fixed-width feature vector required by the shipped SentinelModel.""" + + features: List[float] = Field( + min_length=FEATURE_DIMENSIONS, + max_length=FEATURE_DIMENSIONS, + description="Exactly 16 numeric features in the model's expected order.", + ) class PromptRequest(BaseModel): From 2143b3a827b0bc16eece1b49799aa25af3174de8 Mon Sep 17 00:00:00 2001 From: Corey Leath Date: Sun, 9 Aug 2026 14:27:45 -0400 Subject: [PATCH 2/3] docs: clarify model feature dimension contract --- api/core/model.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/api/core/model.py b/api/core/model.py index e2cc47a..0a1972c 100644 --- a/api/core/model.py +++ b/api/core/model.py @@ -9,7 +9,11 @@ class SentinelModel(nn.Module): - """Two-layer MLP that accepts arbitrary-length feature vectors.""" + """Two-layer MLP with a fixed-width input contract per model instance. + + The default model expects 16 features. Deployments using a different + input dimension must update the API contract and model artifact together. + """ def __init__(self, input_dim: int = 16, hidden_dim: int = 32, output_dim: int = 1) -> None: super().__init__() From e46d61773743a4fa23fb90b0396543f2df4de6dc Mon Sep 17 00:00:00 2001 From: Corey Leath Date: Sun, 9 Aug 2026 14:27:47 -0400 Subject: [PATCH 3/3] test: cover inference feature dimension validation --- tests/test_predict.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/test_predict.py diff --git a/tests/test_predict.py b/tests/test_predict.py new file mode 100644 index 0000000..c60e8e6 --- /dev/null +++ b/tests/test_predict.py @@ -0,0 +1,17 @@ +from api import main + + +def test_predict_accepts_exact_model_feature_dimension(client, monkeypatch): + monkeypatch.setattr(main, "run_inference", lambda features: [0.42]) + + response = client.post("/predict", json={"features": [0.0] * 16}) + + assert response.status_code == 200 + assert response.json() == {"prediction": [0.42]} + + +def test_predict_rejects_feature_vectors_with_the_wrong_dimension(client): + response = client.post("/predict", json={"features": [0.0] * 15}) + + assert response.status_code == 422 + assert any(error["loc"] == ["body", "features"] for error in response.json()["detail"])