From ff952aa08306be6aa6a9febf4dc6a7b1f286219d Mon Sep 17 00:00:00 2001 From: Marko Djordjevic Date: Wed, 18 Feb 2026 11:27:12 +0100 Subject: [PATCH] feat(ml): add date range validation to POST /predict/batch - Parse start_date and end_date as datetime objects - Return HTTP 400 if end_date is before start_date - Return HTTP 400 if date range exceeds 365 days (1 year) Closes task 5.4 in code-review-fix tasks. Co-Authored-By: Claude Sonnet 4.6 --- openspec/changes/code-review-fix/tasks.md | 2 +- services/ml/app/main.py | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/openspec/changes/code-review-fix/tasks.md b/openspec/changes/code-review-fix/tasks.md index d8bbe7c..868a17d 100644 --- a/openspec/changes/code-review-fix/tasks.md +++ b/openspec/changes/code-review-fix/tasks.md @@ -44,7 +44,7 @@ - [x] 5.1 `[sonnet]` Replace `error.message` / traceback details with generic `"Internal server error"` in FastAPI exception handlers at lines 640, 778, 1091, 1134, 1199, 1296 of `services/ml/app/main.py` - [x] 5.2 `[opus]` Add SHA256 model integrity check: create `models/checksums.sha256` manifest, verify hash before `joblib.load()` in `services/ml/app/main.py:266` - [x] 5.3 `[sonnet]` Add `_model_swap_lock` to prediction reads (not just writes) in `services/ml/app/main.py` for thread-safe model access -- [ ] 5.4 `[sonnet]` Add date range validation (max 1 year) to `POST /predict/batch` in `services/ml/app/main.py` +- [x] 5.4 `[sonnet]` Add date range validation (max 1 year) to `POST /predict/batch` in `services/ml/app/main.py` - [ ] 5.5 `[sonnet]` Add candle time-sort validation/auto-sort to `POST /predict` in `services/ml/app/main.py` - [ ] 5.6 `[sonnet]` Implement real health checks: `SELECT 1` for PostgreSQL, MLflow API ping in `services/ml/app/main.py:396-409` - [ ] 5.7 `[sonnet]` Add training resource limits: 500MB dataset size check, 30-minute timeout with status update on expiry in `services/ml/app/main.py:907-1030` diff --git a/services/ml/app/main.py b/services/ml/app/main.py index 60cef4a..a77a543 100644 --- a/services/ml/app/main.py +++ b/services/ml/app/main.py @@ -760,6 +760,28 @@ async def predict_batch(request: BatchPredictRequest): detail="Pipeline configuration not loaded" ) + # Validate date range + try: + start_dt = datetime.strptime(request.start_date, "%Y-%m-%d") + end_dt = datetime.strptime(request.end_date, "%Y-%m-%d") + except ValueError as exc: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Invalid date format. Use YYYY-MM-DD", + ) + + if end_dt < start_dt: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="end_date must be after start_date", + ) + + if (end_dt - start_dt).days > 365: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Date range cannot exceed 1 year", + ) + logger.info( f"Batch predict: {request.pair} {request.timeframe} " f"from {request.start_date} to {request.end_date}"