New exceptions: DatabaseBusyError, DatabasePermissionDeniedError,
DatabasePathInvalidError, DatabaseCorruptedError, DatabaseUnavailableError.
open_db creates parent directory if missing. Catches all aiosqlite errors
and maps to specific exception types.
get_db retries up to 3x on locked database with backoff.
Propagates specific exceptions instead of generic HTTPException.
Tests for all new error types and retry behavior.
Replace check-then-insert race condition with INSERT ON CONFLICT.
- upsert_pending uses RETURNING id for atomic upsert
- UNIQUE(source_id, content_hash) constraint from migration 6
- blocklist_import_workflow updated to use upsert_pending
- test_import_source_success fixed for async mock patterns
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add global rate limiter utility with configurable limits and cleanup
- Move rate limiting logic to middleware for consistent application
- Update auth routes to use new rate limiter
- Add comprehensive tests for rate limiter functionality
- Update documentation with backend development guidelines and tasks
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move ConfigDirError, ConfigFileNotFoundError, ConfigFileExistsError, ConfigFileWriteError, and ConfigFileNameError from raw_config_io_service into the shared domain exception module. Update router and tests to import the exceptions from app.exceptions.
Move all shared domain exception classes to backend/app/exceptions.py and update services/routers to import the canonical exceptions. Update docs to reflect the shared exceptions source.