Upgrade configuration and Docker stack to v2.0.0
This commit is contained in:
+39
-1
@@ -4,7 +4,45 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
## [Unreleased]
|
||||
## [2.0.0] - 2026-06-22
|
||||
|
||||
### Security
|
||||
- API Key hashing now uses SHA-256 + pepper (SECRET_KEY) with timing-safe comparison via `secrets.compare_digest()`
|
||||
- CORS validation rejects `["*"]` when `allow_credentials=True` (Pydantic model_validator)
|
||||
- Scope validation: `ClientCreate.scopes` rejects invalid values via `field_validator`
|
||||
- Master key comparison uses constant-time compare
|
||||
|
||||
### Added
|
||||
- **Dead Letter Queue (DLQ)**: Failed ARQ jobs pushed to Redis DLQ after `PIPELINE_MAX_RETRIES` attempts. Admin endpoints to list/retry/clear dead jobs (`GET/POST/DELETE /admin/api/queue/dead`)
|
||||
- **Circuit Breaker AI**: All AI calls wrapped with `asyncio.wait_for()` + exponential backoff retry (configurable via `AI_REQUEST_TIMEOUT`, `AI_MAX_RETRIES`)
|
||||
- **Request ID Middleware**: `X-Request-ID` header injected in all responses + bound to structlog context
|
||||
- **Rate Limiting per Plan**: Dynamic rate limits based on client plan (free/standard/premium) via ContextVar
|
||||
- **Redis Rate Limit Storage**: Optional persistence via `RATE_LIMIT_STORAGE_URL`
|
||||
- **Worker script**: `worker.py` for standalone ARQ worker launch
|
||||
- **Docker Compose stack**: PostgreSQL 16 + Redis 7 + MinIO + API + Worker
|
||||
- **`.env.example`**: All configuration variables documented
|
||||
- **Grafana Dashboard**: `docs/grafana-dashboard.json` with 10 panels (images, tokens, pipeline, storage, WebSocket, errors)
|
||||
- **Database indexes**: Composite indexes `(client_id, uploaded_at)` and `(client_id, processing_status)` on images table
|
||||
|
||||
### Changed
|
||||
- `APP_VERSION` aligned to `2.0.0` in config (was `1.0.0`)
|
||||
- `delete_files()` now fully async — uses `await backend.delete()` instead of fire-and-forget `ensure_future()`
|
||||
- Upload flow: files deleted on DB commit failure (no orphaned S3 files)
|
||||
- Gemini client: cached with TTL — recreated if `GEMINI_API_KEY` changes
|
||||
- `parse_redis_url()` extracted to `app/workers/redis_client.py` (DRY — was duplicated in main.py and image_worker.py)
|
||||
- Rate limit key function encodes plan for per-plan bucket isolation
|
||||
- `_FallbackArqPool` moved to `app/workers/arq_fallback.py` (avoids circular imports)
|
||||
- ARQ worker: configurable `PIPELINE_TIMEOUT` and `PIPELINE_MAX_RETRIES`, `on_shutdown` handler
|
||||
- Pipeline: `push_dead_job()` on final retry failure marks image as `ERROR` with DLQ metadata
|
||||
- Admin panel: VITE_API_BASE_URL changed from internal Docker hostname to `http://localhost:8000`
|
||||
|
||||
### Fixed
|
||||
- ARQ fallback now returns explicit warning in `UploadResponse.message` instead of silently ignoring
|
||||
- Removed obsolete comment in `ai_vision.py` about `StorageBackend.read`
|
||||
- Removed signal handler instability in test fixtures
|
||||
- Fixed Docker Compose admin connectivity (browser couldn't resolve internal `backend` hostname)
|
||||
|
||||
## [1.0.0] - Previous
|
||||
|
||||
### Added (Phase 3: DX)
|
||||
- **WebSockets / Real-Time**:
|
||||
|
||||
Reference in New Issue
Block a user