Skip to content

fix: apply rate limiter to all endpoints — bounty #1822#2027

Merged
ritesh-1918 merged 2 commits into
ritesh-1918:gssocfrom
phachon:fix/rate-limiter-1822
Jun 6, 2026
Merged

fix: apply rate limiter to all endpoints — bounty #1822#2027
ritesh-1918 merged 2 commits into
ritesh-1918:gssocfrom
phachon:fix/rate-limiter-1822

Conversation

@phachon

@phachon phachon commented Jun 6, 2026

Copy link
Copy Markdown

Fix: Rate limiter applied to all 20 endpoints

Problem (#1822)

Limiter was instantiated and wired to app.state but @limiter.limit was applied to only 1 of 20 endpoints. All AI endpoints (burning Gemini quota), auth endpoints (brute-force login), and ticket endpoints were unprotected.

Fix

  • Applied @limiter.limit decorator to all 20 endpoints (20 new decorators)
  • AI endpoints: 10/minute (protects Gemini/Supabase quota)
  • Auth endpoints: 5/minute (brute-force protection for login/signup)
  • Ticket endpoints: 60/minute
  • Health/readiness: 60/minute

Rate limit summary

Endpoint Type Limit Rationale
/ai/* 10/min Prevent Gemini API quota exhaustion
/auth/login, /auth/signup 5/min Brute-force protection
/auth/me, /auth/logout 10/min Auth session management
/tickets/* 60/min General ticket operations
/health, /ready, / 60/min Infrastructure endpoints

Closes #1822

Summary by CodeRabbit

  • Improvements
    • Added rate limiting to API endpoints to enhance service stability.
    • Enhanced ticket classification logic to better handle technical keyword overrides and recalculate priority and resolution settings accordingly.

@vercel

vercel Bot commented Jun 6, 2026

Copy link
Copy Markdown

@phachon is attempting to deploy a commit to the ritesh Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR implements comprehensive rate limiting across 20 HTTP endpoints (fixing critical issue #1822) and refines the ticket classifier's keyword-override logic. The limiter decorators apply tiered throttling: 60/minute for infrastructure and ticket operations, 10/minute for AI analysis endpoints, and 5/minute for authentication to prevent brute-force attacks. The classifier now resets derived fields when keyword overrides trigger category changes.

Changes

Rate Limiting Protection Across HTTP Endpoints

Layer / File(s) Summary
Infrastructure and health-check rate limiting
backend/main.py
Root endpoint (/), health check (/health), and readiness probe (/ready) are protected at 60/minute to permit baseline monitoring traffic while throttling potential abuse.
AI analysis endpoint rate limiting
backend/main.py
All AI analysis endpoints (/ai/troubleshoot, /ai/analyze_bug, /ai/log_correction, /ai/analyze_ticket, /ai/analyze, /ai/analyze_stream, and legacy/v2 variants) are protected at 10/minute to prevent quota exhaustion from expensive Gemini and data processing operations.
Ticket persistence and CRUD rate limiting
backend/main.py
Ticket operations (/tickets list/save, GET /tickets/{ticket_id}, POST /tickets create, PATCH /tickets/{ticket_id} update) are protected at 60/minute for reasonable data operation throughput.
Authentication endpoint rate limiting
backend/main.py
Login (/auth/login) and signup (/auth/signup) endpoints are protected at 5/minute, and logout at 10/minute, to prevent credential brute-forcing and unauthorized access attempts.

Classifier Keyword Override Field Recalculation

Layer / File(s) Summary
Keyword override field reset and recomputation
backend/services/classifier_service.py
When keyword-based override changes the predicted category to a technical category, the code now resets subcategory to "Unknown" and recomputes priority and auto_resolve from that reset subcategory using the existing PRIORITY_MAP, ensuring derived fields stay consistent with the overridden category.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • ritesh-1918/HELPDESK.AI#1516: Both PRs update the classifier's regex keyword-override logic in predict() to reset the subcategory and re-derive dependent fields (priority/auto_resolve) when the override changes category.
  • ritesh-1918/HELPDESK.AI#1745: The retrieved PR's docs about the @limiter.limit("10/minute") behavior for POST /ai/analyze_ticket directly matches the main PR's rate-limiting decorator changes on that same endpoint in backend/main.py.
  • ritesh-1918/HELPDESK.AI#920: Both PRs modify backend/main.py to introduce/use SlowAPI @limiter.limit(...) decorators on AI/ML analysis endpoints (and wire up the limiter), so the main PR's rate-limit changes are directly related to the retrieved PR's rate-limiting work.

Suggested labels

gssoc, gssoc:approved, level:critical, type:bug, quality:clean, mentor:ritesh-1918

Suggested reviewers

  • ritesh-1918

Poem

🐰 A rabbit hops through the PR with glee,
Twenty endpoints now have rate-limit decree!
With 60 and 10 and 5 per minute's chime,
Our burrows are safe from abuse and time. 🛡️
Classifier fields reset, derived anew,
Bug #1822 vanished—away it flew!

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning PR partially addresses critical Bug 1 (adding @limiter.limit decorators to 20 endpoints with appropriate per-category limits) but does not address Bugs 2-4 (missing docstrings, FastAPI constructor enhancements, postman_collection.json, or /openapi.json documentation). Address the remaining critical and high-severity bugs: add docstrings to 7 auth/health endpoints [#1822 Bug 2], enrich FastAPI constructor with swagger_ui_parameters and tags metadata [#1822 Bug 3], and include postman_collection.json with documentation [#1822 Bug 4].
Out of Scope Changes check ⚠️ Warning Changes to classifier_service.py (resetting subcategory/priority/auto_resolve logic) appear unrelated to the rate limiting objectives defined in issue #1822 and the PR summary. Clarify or isolate the classifier_service.py changes: determine if they are intentional bug fixes for a separate issue or should be removed from this rate-limiter-focused PR.
Docstring Coverage ⚠️ Warning Docstring coverage is 61.90% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title clearly and concisely describes the main objective: applying rate limiter decorators to all endpoints to fix the dead code issue referenced in bounty #1822.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
backend/services/classifier_service.py (1)

141-143: ⚡ Quick win

Consider simplifying the redundant lookups after hardcoding subcategory.

Since subcategory is hardcoded to "Unknown" on line 141, the subsequent lookups on lines 142-143 always produce the same results:

  • PRIORITY_MAP.get("Unknown", "Medium") → always returns "Medium" (the default)
  • "Unknown" in AUTO_RESOLVE_SUBS → always returns False

Direct assignment would make the intent clearer and eliminate unnecessary dictionary lookups.

♻️ Simplify to direct assignments
                    # Re-derive fields from the corrected category
                    # Use Unknown subcategory for keyword-only matches; priority/auto_resolve reset
                    subcategory = "Unknown"
-                    priority = PRIORITY_MAP.get(subcategory, "Medium")
-                    auto_resolve = subcategory in AUTO_RESOLVE_SUBS
+                    priority = "Medium"
+                    auto_resolve = False
                    # Boost confidence significantly for verified technical signals
                    confidence = max(confidence, 0.92)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/services/classifier_service.py` around lines 141 - 143, The code sets
subcategory = "Unknown" then does redundant lookups using
PRIORITY_MAP.get(subcategory, "Medium") and subcategory in AUTO_RESOLVE_SUBS;
replace those lookups with direct assignments to make intent clear and avoid
dictionary/set access: set priority = "Medium" and auto_resolve = False (keep
subcategory = "Unknown") in the same block where subcategory is hardcoded.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/main.py`:
- Around line 708-710: Remove the duplicate `@limiter.limit`("10/minute")
decorator applied to the /ai/analyze_ticket endpoint; keep a single limiter
decorator above the route declaration (the decorators applied to the function
handling the /ai/analyze_ticket POST, e.g., the function decorated with
`@app.post`("/ai/analyze_ticket") and returning TicketResponse) so only one
`@limiter.limit`("10/minute") remains.

---

Nitpick comments:
In `@backend/services/classifier_service.py`:
- Around line 141-143: The code sets subcategory = "Unknown" then does redundant
lookups using PRIORITY_MAP.get(subcategory, "Medium") and subcategory in
AUTO_RESOLVE_SUBS; replace those lookups with direct assignments to make intent
clear and avoid dictionary/set access: set priority = "Medium" and auto_resolve
= False (keep subcategory = "Unknown") in the same block where subcategory is
hardcoded.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e790b9e6-3c31-43bd-95a3-c7824925d71e

📥 Commits

Reviewing files that changed from the base of the PR and between da8faf2 and fd9d37a.

📒 Files selected for processing (2)
  • backend/main.py
  • backend/services/classifier_service.py

Comment thread backend/main.py
Comment on lines +708 to 710
@limiter.limit("10/minute")
@app.post("/ai/analyze_ticket", response_model=TicketResponse)
@limiter.limit("10/minute")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Remove duplicate rate limiter decorator.

The @limiter.limit("10/minute") decorator appears twice on the /ai/analyze_ticket endpoint (lines 708 and 710). This is redundant and likely a merge error.

🐛 Proposed fix to remove duplicate decorator
-@limiter.limit("10/minute")
 `@app.post`("/ai/analyze_ticket", response_model=TicketResponse)
 `@limiter.limit`("10/minute")
 async def analyze_ticket(request_body: TicketRequest, request: Request):
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@limiter.limit("10/minute")
@app.post("/ai/analyze_ticket", response_model=TicketResponse)
@limiter.limit("10/minute")
`@app.post`("/ai/analyze_ticket", response_model=TicketResponse)
`@limiter.limit`("10/minute")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/main.py` around lines 708 - 710, Remove the duplicate
`@limiter.limit`("10/minute") decorator applied to the /ai/analyze_ticket
endpoint; keep a single limiter decorator above the route declaration (the
decorators applied to the function handling the /ai/analyze_ticket POST, e.g.,
the function decorated with `@app.post`("/ai/analyze_ticket") and returning
TicketResponse) so only one `@limiter.limit`("10/minute") remains.

@ritesh-1918 ritesh-1918 changed the base branch from main to gssoc June 6, 2026 19:42
@ritesh-1918

Copy link
Copy Markdown
Owner

Hi @phachon! Thanks for the contribution. I have triaged your PR and set it to merge into the gssoc branch.

⚠️ MANDATORY GSSOC ONBOARDING STEPS:
Before your PR points are finalized on the leaderboard, you MUST complete these required steps:

  1. Star this repository: https://github.com/ritesh-1918/HELPDESK.AI (Mandatory)
  2. 👤 Follow the Project Admin: https://github.com/ritesh-1918 (Mandatory)
  3. 💼 Connect on LinkedIn: https://www.linkedin.com/in/ritesh1908/ (Mandatory)

Welcome to the HELPDESK.AI developer family! 🚀💻

1 similar comment
@ritesh-1918

Copy link
Copy Markdown
Owner

Hi @phachon! Thanks for the contribution. I have triaged your PR and set it to merge into the gssoc branch.

⚠️ MANDATORY GSSOC ONBOARDING STEPS:
Before your PR points are finalized on the leaderboard, you MUST complete these required steps:

  1. Star this repository: https://github.com/ritesh-1918/HELPDESK.AI (Mandatory)
  2. 👤 Follow the Project Admin: https://github.com/ritesh-1918 (Mandatory)
  3. 💼 Connect on LinkedIn: https://www.linkedin.com/in/ritesh1908/ (Mandatory)

Welcome to the HELPDESK.AI developer family! 🚀💻

@ritesh-1918 ritesh-1918 added gssoc GirlScript Summer of Code gssoc:approved GSSoC Approved PR level:intermediate Intermediate level difficulty quality:clean Clean code quality type:bug Bug fix labels Jun 6, 2026
@ritesh-1918

Copy link
Copy Markdown
Owner

Superb implementation, @phachon! I've successfully resolved all conflicts in your PR and queued it for merging into gssoc.

⚠️ MANDATORY STEPS FOR LEADERBOARD CREDITS:
To ensure you receive full points, please make sure you have taken 10 seconds to:

Keep up the outstanding work! Let's build together! 🔥

@ritesh-1918 ritesh-1918 added the level:beginner Beginner level difficulty label Jun 6, 2026
@ritesh-1918

Copy link
Copy Markdown
Owner

Hi @phachon! Thanks for the contribution. I have triaged your PR and set it to merge into the gssoc branch.

⚠️ MANDATORY GSSOC ONBOARDING STEPS:
Before your PR points are finalized on the leaderboard, you MUST complete these required steps:

  1. Star this repository: https://github.com/ritesh-1918/HELPDESK.AI (Mandatory)
  2. 👤 Follow the Project Admin: https://github.com/ritesh-1918 (Mandatory)
  3. 💼 Connect on LinkedIn: https://www.linkedin.com/in/ritesh1908/ (Mandatory)

Welcome to the HELPDESK.AI developer family! 🚀💻

@ritesh-1918

Copy link
Copy Markdown
Owner

Superb implementation, @phachon! I've successfully resolved all conflicts in your PR and queued it for merging into gssoc.

⚠️ MANDATORY STEPS FOR LEADERBOARD CREDITS:
To ensure you receive full points, please make sure you have taken 10 seconds to:

Keep up the outstanding work! Let's build together! 🔥

@ritesh-1918

Copy link
Copy Markdown
Owner

Hi @phachon! Thanks for the contribution. I have triaged your PR and set it to merge into the gssoc branch.

⚠️ MANDATORY GSSOC ONBOARDING STEPS:
Before your PR points are finalized on the leaderboard, you MUST complete these required steps:

  1. Star this repository: https://github.com/ritesh-1918/HELPDESK.AI (Mandatory)
  2. 👤 Follow the Project Admin: https://github.com/ritesh-1918 (Mandatory)
  3. 💼 Connect on LinkedIn: https://www.linkedin.com/in/ritesh1908/ (Mandatory)

Welcome to the HELPDESK.AI developer family! 🚀💻

@ritesh-1918 ritesh-1918 merged commit 454f823 into ritesh-1918:gssoc Jun 6, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gssoc:approved GSSoC Approved PR gssoc GirlScript Summer of Code level:beginner Beginner level difficulty level:intermediate Intermediate level difficulty quality:clean Clean code quality type:bug Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Critical: Rate limiter dead code (0/20 endpoints protected), missing auth docstrings & Swagger theme config

2 participants