peregrine/tests
pyr0ball d801650db1 feat(api): per-user LLM rate limiting via slowapi
Add scripts/rate_limit.py with cloud-aware key function:
- In cloud mode, extracts user_id from _request_db ContextVar path (part[-3])
  so each cloud user has their own rate limit bucket
- In demo mode, returns unique per-request key to disable limiting entirely
  (_demo_guard handles write-blocking; rate limiting would block the demo UX)
- Falls back to client IP for local/self-hosted installs

Wire limiter to 4 endpoints with conservative per-user limits:
- POST /generate/cover-letter: 20/hour
- POST /research/run: 10/hour
- POST /qa/suggest: 60/hour
- POST /survey/analyze: 30/hour

Add _demo_guard() to generate_research and suggest_qa_answer (was missing).
Fix pre-existing silent except in suggest_qa_answer: was bare except pass,
now logs warning with exc_info.

Add _RL_WIZARD placeholder constant with TODO to wire to wizard/ai/interview
after feat/77 merges (declared but intentionally not applied yet to avoid
false sense of security — comment makes the gap explicit).

18 tests covering cloud user isolation, demo bypass, IP fallback, all 4
endpoints returning 429 on excess, retry_after header, and demo guard.

Closes: #122
2026-06-14 12:14:21 -07:00
..
e2e chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
fixtures feat(linkedin): add HTML parser utils with fixture tests 2026-03-13 01:01:05 -07:00
__init__.py chore: seed Peregrine from personal job-seeker (pre-generalization) 2026-02-24 18:25:39 -08:00
test_app_gating.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_backup.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_benchmark_classifier.py feat: benchmark_classifier — MODEL_REGISTRY, --list-models, --score, --compare modes 2026-02-27 06:19:32 -08:00
test_byok_guard.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_calendar_push.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_classifier_adapters.py feat: label_tool — 9 labels, wildcard Other, InvalidCharacterError fix; sync with avocet canonical 2026-02-27 14:34:24 -08:00
test_cloud_session.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_company_research.py feat: extract hard-coded personal references from all scripts via UserProfile 2026-02-24 18:45:39 -08:00
test_cover_letter.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_cover_letter_refinement.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_craigslist.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_db.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_db_migrate.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_db_resumes.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_demo_guard.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_demo_toolbar.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_dev_api_digest.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_dev_api_feedback.py feat: wire feedback router from circuitforge-core 2026-04-05 18:45:18 -07:00
test_dev_api_interviews.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_dev_api_prep.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_dev_api_settings.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_dev_api_survey.py fix: update interview + survey tests for hired_feedback column and async analyze endpoint 2026-04-20 11:48:22 -07:00
test_dev_tab.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_discover.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_e2e_helpers.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_enrich_descriptions.py chore: seed Peregrine from personal job-seeker (pre-generalization) 2026-02-24 18:25:39 -08:00
test_feedback_api.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_home_banners.py feat: dismissible setup banners on Home page (13 contextual prompts) 2026-02-25 09:53:34 -08:00
test_hooks.sh feat: commit-msg hook enforces conventional commit format 2026-03-02 19:14:31 -08:00
test_imap_sync.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_integrations.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_license.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_license_tier_integration.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_linkedin_parser.py feat(linkedin): add staging file parser with re-parse support 2026-03-13 10:18:01 -07:00
test_linkedin_scraper.py fix(linkedin): improve scraper error handling, current-job date range, add missing tests 2026-03-13 06:02:03 -07:00
test_linkedin_utils.py feat(linkedin): add HTML parser utils with fixture tests 2026-03-13 01:01:05 -07:00
test_llm_config_generation.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_llm_router.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_llm_router_shim.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_match.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_messaging.py test: add missing update_template KeyError test (#74) 2026-04-20 12:32:35 -07:00
test_messaging_integration.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_mission_domains.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_preflight.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_preflight_env_adoption.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_rate_limiting.py feat(api): per-user LLM rate limiting via slowapi 2026-06-14 12:14:21 -07:00
test_reranker_integration.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_resume_optimizer.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_resume_parser.py refactor: replace LLM-based resume parser with section regex parser 2026-02-26 07:34:25 -08:00
test_resume_sync.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_resume_sync_integration.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_resumes_api.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_scrape_url.py feat: add Jobgether URL detection and scraper to scrape_url.py 2026-03-15 09:45:50 -07:00
test_suggest_helpers.py feat: add suggest_resume_keywords for skills/domains/keywords gap analysis 2026-03-05 15:00:53 -08:00
test_sync.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_task_runner.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_task_scheduler.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_telemetry.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_training_export.py feat: add training export API endpoints to dev_api.py 2026-05-02 23:40:44 -07:00
test_ui_switcher.py fix: update tests to match refactored scheduler and free-tier Vue SPA 2026-04-05 07:35:45 -07:00
test_user_profile.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00
test_wizard_api.py feat: Interview prep Q&A, cf-orch hardware profile, a11y fixes, dark theme 2026-04-14 17:01:18 -07:00
test_wizard_flow.py feat: wizard orchestrator — 7 steps, LLM generation polling, crash recovery 2026-02-25 09:10:51 -08:00
test_wizard_steps.py feat: step_integrations module with validate() + tier-filtered available list 2026-02-25 08:35:16 -08:00
test_wizard_tiers.py chore(lint): ruff auto-fix unused imports in tests/ 2026-05-20 23:07:52 -07:00