Introduce common/candles.py with a Pydantic Candle model enforcing OHLC
consistency (high≥max, low≤min), non-negative volume and positive
timestamp. validate_candles() coerces upstream rows, sorts by timestamp
and raises HTTPException(502) on malformed data — surfacing upstream
data corruption as a retryable envelope instead of silently returning
nonsense.
Wired into all five exchange historical endpoints (Bybit, Hyperliquid,
Deribit, Alpaca, IBKR). BREAKING: Alpaca get_bars and IBKR get_bars now
return 'candles' (was 'bars') to align with the other exchanges.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- /health/ready: ping di tutti i client (exchange, env) cached con
timeout 2s, status ready|degraded|not_ready, opt-in 503 via
READY_FAILS_ON_DEGRADED.
- Middleware mcp.request: 1 riga JSON per HTTP request con request_id,
method, path, status_code, duration_ms, actor, bot_tag, exchange,
tool, client_ip, user_agent.
- request_id propagato in request.state, audit log e error envelope per
correlazione cross-cutting.
- Aggiunto async health() come probe minimo a bybit/alpaca/macro/
sentiment/deribit (hyperliquid lo aveva già).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- ruff: contextlib.suppress al posto di try/except/pass (client_registry, test_env_routing)
- rimozione services/ legacy (residuo da git rm)
- fix integration test fixture: rimosso sys.modules.pop che inquinava module references nei test successivi (test_audit, test_client_init_default_http)
254 test passano. Ruff: clean. Mypy: 68 warning preesistenti dal codice V1 migrato (strict=false).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>