Resolved by PRs #352 and #56 (merged). Skeleton loaders and error states have been added to the Batch and Analytics pages.
Resolved by PR #29 (merged). Patent.patent_id in types.py is correctly typed as str (verified in current codebase).
Resolved by PRs #1374, #31, and #55 (merged). Patent volume mount requirement is documented. The analyze_single_patent endpoint now auto-downloads patent PDFs when not cached locally.
Resolved by PRs #29 and #270 (merged). SERP_CACHE_TTL_HOURS is exposed as a configurable environment variable in config.py and documented in .env.example.
Resolved by PR #29 (merged). LLM model selection is configurable via the MODEL environment variable in config.py. Also documented in .env.example via PR #270.
Resolved by PRs #29 and #54 (merged). All print() calls in analyzer.py, serp_api.py, and llm.py have been replaced with structured Python logging. No bare print() calls remain in the…
Resolved by PR #35 (merged). Comprehensive JWT auth flow tests exist in tests/test_auth.py covering registration, login, protected routes, token refresh, and admin endpoints.
Resolved by PR #34 (merged). Async batch job state is now persisted to PostgreSQL via db.create_job(), db.update_job(), db.get_job(), and db.list_jobs(). Stale jobs are marked failed on…
Resolved by PR #30 (merged). get_db_client() in auth.py now uses a shared module-level singleton DatabaseClient, initialized at startup via init_db_client() and cleaned up via `close_db_cli…
Resolved by PR #28 (merged). Rate limiting is applied via slowapi: /auth/login is limited to 10/minute and /auth/register to 5/minute. Tests exist in tests/test_rate_limit.py.