Files
Imago/CHANGELOG.md
T

72 lines
4.4 KiB
Markdown

# Changelog
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/).
## [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**:
- Subscriptions on per-image workflows (`/ws/pipeline/{image_id}`).
- Redis 60-second Event Buffering for reconnections.
- Admin Monitor WebSocket feed (`/ws/admin/monitor`).
- **REST API Versioning**:
- Global `/api/v1/` prefix for structural stability.
- Added strict API Sunset Date tracking middleware.
- **Python SDK (`imago-client`)**:
- Publishable PyPI-ready package located inside `sdk/`.
- Automatic `httpx` HTTP reconnects, WebSockets streaming natively wrapped, and robust generic Error classes (`ImagoError`, `AuthError`, etc.).
- **Admin Backend APIs**:
- Complete JSON statistics (`/admin/api/stats`), global client configurations (`/admin/api/clients/*`) and Queue observability natively piped to the existing React Interface.
- **Shaarli Integrations**:
- Skeleton integration middleware (`integration/shaarli`) capable of bridging Shaarli's events right into Imago using the official SDK.
- **Extensive Documentation**:
- Modular guides provided inside `docs/` detailing WebSockets, Integrations, and SDK consumption.
### Changed
- All API routing endpoints have been moved behind the `/api/v1` namespace. Existing API Clients must update base URLs from `/` to `/api/v1/`.
### Fixed
- Fixed unawaited coroutines in async mocks causing `TypeError` on Pytest environments.
- Fixed an incorrect payload key mapping in `APIClient` responses causing 500s (`AttributeError`).
- Mocked S3 and ARQ correctly globally to ensure local automated tests pass completely isolated from network logic.