Skip to content

feat: implement BYOK AI key resolution and rate limits - #383

Merged
yash-pouranik merged 6 commits into
mainfrom
feat/byok-ai
Aug 6, 2026
Merged

yash-pouranik merged 6 commits into
mainfrom
feat/byok-ai

Conversation

@yash-pouranik

@yash-pouranik yash-pouranik commented Aug 6, 2026 •

Copy link
Copy Markdown
Member

BYOK-GROK-AI KEY

Summary by CodeRabbit

  • New Features

    • Added support for configuring personal Groq API keys at developer and project levels.
    • AI requests now prioritize project keys, then developer keys, with platform fallback.
    • Added free-tier usage limits and expanded access for eligible paid plans.
    • Added validation, secure storage, encrypted transmission, and key-status responses.
  • Documentation

    • Documented required encryption configuration for the AI service.
  • Tests

    • Added coverage for key management, decryption, limits, fallback behavior, and invalid keys.

@vercel

vercel Bot commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ur-backend-web-dashboard Ready Ready Preview Aug 6, 2026 7:12pm
urbackend Ready Ready Preview Aug 6, 2026 7:12pm

@coderabbitai

coderabbitai Bot commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@yash-pouranik, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 42 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d51c903a-6b78-4420-b7c4-44b9eb0eb763

📥 Commits

Reviewing files that changed from the base of the PR and between 292aecb and f83a6ab.

📒 Files selected for processing (3)
  • apps/dashboard-api/src/controllers/ai.controller.js
  • apps/python-service/services/byok.py
  • apps/python-service/tests/test_byok.py
📝 Walkthrough

Walkthrough

The PR adds user and project BYOK endpoints, encrypted key storage, AES-256-GCM transit protection, Python-side key resolution, Redis-backed plan limits, and AI request forwarding.

Changes

BYOK AI flow

Layer / File(s) Summary
BYOK storage and transit cryptography
packages/common/src/models/Developer.js, packages/common/src/models/Project.js, apps/dashboard-api/src/utils/transitEncryption.js, apps/python-service/services/transit_crypto.py, apps/python-service/config.py, apps/python-service/.env.example, apps/python-service/requirements.txt
The models store encrypted Groq key metadata. The Dashboard API and Python service use compatible AES-256-GCM payload encryption.
Dashboard BYOK update endpoints
apps/dashboard-api/src/controllers/auth.controller.js, apps/dashboard-api/src/controllers/project.controller.js, apps/dashboard-api/src/routes/projects.js, apps/dashboard-api/src/routes/user.js, apps/dashboard-api/src/__tests__/*
Authenticated endpoints validate, encrypt, persist, clear, and report user or project Groq keys. Project updates enforce access and invalidate the project cache.
AI request forwarding and resolution
apps/dashboard-api/src/controllers/ai.controller.js, apps/python-service/routers/ai.py
The Dashboard API resolves project or developer credentials and forwards developer ID, plan, and encrypted key data. The query builder resolves the AI client and preserves HTTP exceptions.
Python BYOK client resolution
apps/python-service/services/byok.py, apps/python-service/tests/test_byok.py, apps/python-service/tests/test_auth.py
The Python service decrypts supplied keys, uses the platform key when needed, applies free- and pro-tier Redis limits, and tests these paths.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DashboardAPI
  participant PythonAIService
  participant TransitCrypto
  participant Redis
  participant Groq
  DashboardAPI->>PythonAIService: Send developer ID, plan, and encrypted Groq key
  PythonAIService->>TransitCrypto: Decrypt transit payload
  TransitCrypto-->>PythonAIService: Return Groq API key
  PythonAIService->>Redis: Check platform usage counter
  Redis-->>PythonAIService: Return counter state
  PythonAIService->>Groq: Create ChatGroq client and execute query
  Groq-->>PythonAIService: Return structured result
Loading

Possibly related PRs

Suggested labels: type:feature

Suggested reviewers: nitin-kumar-yadav1307, copilot

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main changes: BYOK AI key resolution and rate limiting.
Docstring Coverage ✅ Passed Docstring coverage is 91.67% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/byok-ai

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
apps/python-service/tests/test_byok.py (1)

77-77: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Resolve the reported unused-unpack warnings.

Replace unused mock values with _. This keeps the test file clean under the configured Ruff checks.

Proposed fix
-    mock_rc, mock_pipe = mock_redis
+    _, mock_pipe = mock_redis
...
-    mock_rc, mock_pipe = mock_redis
+    _, mock_pipe = mock_redis
...
-    mock_rc, mock_pipe = mock_redis
+    mock_rc, _ = mock_redis

Also applies to: 94-94, 105-105

🤖 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 `@apps/python-service/tests/test_byok.py` at line 77, Update the mock unpacking
assignments in the affected tests to bind unused values to _ instead of mock_rc
or mock_pipe, including the assignments around mock_redis at all referenced
locations, while preserving the values that each test uses.

Source: Linters/SAST tools

🤖 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 `@apps/dashboard-api/src/__tests__/routes.user.test.js`:
- Line 43: Update the updateByok mock response in the route test to include the
required message field alongside success and data, using an empty string
consistent with the API response contract.

In `@apps/dashboard-api/src/controllers/auth.controller.js`:
- Around line 705-707: Normalize unexpected BYOK errors in the catch blocks at
apps/dashboard-api/src/controllers/auth.controller.js:705-707 and
apps/dashboard-api/src/controllers/project.controller.js:3482-3483 by forwarding
existing AppError instances unchanged and wrapping every other error in a
generic AppError before calling next, preventing database or encryption details
from reaching response middleware.

In `@apps/python-service/services/byok.py`:
- Line 64: Require a stable developer identity before resolving platform keys:
in apps/python-service/services/byok.py lines 64-64, reject platform-key
requests without developer_id, then apply the free-tier limit whenever plan !=
"pro"; in apps/python-service/routers/ai.py lines 35-37, require developer_id
for non-BYOK requests or add model validation rejecting requests with neither
BYOK credentials nor a developer identity.

---

Nitpick comments:
In `@apps/python-service/tests/test_byok.py`:
- Line 77: Update the mock unpacking assignments in the affected tests to bind
unused values to _ instead of mock_rc or mock_pipe, including the assignments
around mock_redis at all referenced locations, while preserving the values that
each test uses.
🪄 Autofix

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 Plus

Run ID: 19a88815-eb7f-4b48-b0a5-0fd382edab83

📥 Commits

Reviewing files that changed from the base of the PR and between 50e759c and 0f27629.

📒 Files selected for processing (19)
  • apps/dashboard-api/src/__tests__/routes.projects.storage.test.js
  • apps/dashboard-api/src/__tests__/routes.user.test.js
  • apps/dashboard-api/src/controllers/ai.controller.js
  • apps/dashboard-api/src/controllers/auth.controller.js
  • apps/dashboard-api/src/controllers/project.controller.js
  • apps/dashboard-api/src/routes/projects.js
  • apps/dashboard-api/src/routes/user.js
  • apps/dashboard-api/src/utils/transitEncryption.js
  • apps/python-service/.env.example
  • apps/python-service/config.py
  • apps/python-service/requirements.txt
  • apps/python-service/routers/ai.py
  • apps/python-service/services/__init__.py
  • apps/python-service/services/byok.py
  • apps/python-service/services/transit_crypto.py
  • apps/python-service/tests/test_auth.py
  • apps/python-service/tests/test_byok.py
  • packages/common/src/models/Developer.js
  • packages/common/src/models/Project.js

Comment thread apps/dashboard-api/src/__tests__/routes.user.test.js Outdated
Comment thread apps/dashboard-api/src/controllers/auth.controller.js Outdated
Comment thread apps/python-service/services/byok.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds Bring-Your-Own-Key (BYOK) support for Groq-backed AI features across the dashboard API and Python AI service, including hierarchical key resolution (project → developer → platform) and free-tier generation rate limiting, with a new AES-256-GCM “transit encryption” layer for safely passing decrypted keys to the Python service.

Changes:

  • Introduces byok.groqKey storage on both Project and Developer models (encrypted at rest), with new dashboard endpoints to save/clear keys.
  • Adds Python-side BYOK resolution (resolve_ai_client) and free-tier monthly generation limiting via Redis; updates the AI router to use this resolver.
  • Implements Node→Python transit encryption/decryption (AES-256-GCM) and adds tests + documentation/env example updates.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
packages/common/src/models/Project.js Adds project-level BYOK field for Groq key.
packages/common/src/models/Developer.js Adds developer-level BYOK field for Groq key (encrypted at rest).
apps/python-service/tests/test_byok.py Adds tests for BYOK decryption, fallback behavior, and rate limiting.
apps/python-service/tests/test_auth.py Updates env setup for new required/used config fields.
apps/python-service/services/transit_crypto.py Adds AES-256-GCM decryption compatible with Node transit encryption.
apps/python-service/services/byok.py Adds key resolution + free-tier rate limiting logic.
apps/python-service/services/init.py Introduces services package marker.
apps/python-service/routers/ai.py Adds request fields for plan/BYOK payload and uses resolver.
apps/python-service/requirements.txt Adds pycryptodome for AES-GCM operations.
apps/python-service/config.py Adds INTERNAL_PAYLOAD_KEY setting for transit decryption.
apps/python-service/.env.example Documents INTERNAL_PAYLOAD_KEY usage and requirement.
apps/dashboard-api/src/utils/transitEncryption.js Adds Node-side AES-256-GCM transit encryption helper.
apps/dashboard-api/src/routes/user.js Adds developer BYOK update endpoint.
apps/dashboard-api/src/routes/projects.js Adds project BYOK update endpoint.
apps/dashboard-api/src/controllers/project.controller.js Implements project BYOK save/clear controller.
apps/dashboard-api/src/controllers/auth.controller.js Implements developer BYOK save/clear controller.
apps/dashboard-api/src/controllers/ai.controller.js Resolves project/developer key, encrypts for transit, forwards to Python.
apps/dashboard-api/src/tests/routes.user.test.js Mocks new user BYOK controller route.
apps/dashboard-api/src/tests/routes.projects.storage.test.js Mocks new project BYOK controller route.
Suppressed comments (1)

apps/dashboard-api/src/controllers/ai.controller.js:82

  • This developer BYOK lookup is read-only; adding .lean() avoids Mongoose document hydration overhead.
            const dev = await Developer.findById(req.user._id).select('+byok');

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread apps/dashboard-api/src/controllers/project.controller.js
Comment thread apps/python-service/services/byok.py Outdated
Comment thread apps/python-service/config.py Outdated
Comment thread apps/dashboard-api/src/controllers/auth.controller.js Outdated
Comment thread apps/python-service/services/byok.py Outdated
Comment thread apps/python-service/routers/ai.py Outdated
Comment thread apps/python-service/routers/ai.py Outdated
Comment thread apps/dashboard-api/src/controllers/ai.controller.js Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@apps/dashboard-api/src/controllers/ai.controller.js`:
- Around line 82-84: Update the project lookup in the controller around
Project.findById so it applies getProjectAccessQuery(req.user._id) before
selecting the encrypted BYOK fields. Preserve the existing lean result and
ensure the BYOK key is only loaded when the current user still has project
access.

In `@apps/python-service/services/byok.py`:
- Around line 75-83: Update the counter logic around the Redis pipeline in the
enclosing usage-tracking function to atomically increment the key and assign the
initial 32-day TTL in the same Redis operation, using a Lua script or equivalent
atomic command, and return the resulting count. Remove the separate
post-execution expire path, while preserving existing TTL behavior for
already-expiring counters. Add a test covering first use and verifying the TTL
is set.
🪄 Autofix

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 Plus

Run ID: 37f28911-a2b4-417e-8ce6-a5e3f668eb18

📥 Commits

Reviewing files that changed from the base of the PR and between 0f27629 and 292aecb.

📒 Files selected for processing (8)
  • apps/dashboard-api/src/__tests__/routes.user.test.js
  • apps/dashboard-api/src/controllers/ai.controller.js
  • apps/dashboard-api/src/controllers/auth.controller.js
  • apps/dashboard-api/src/controllers/project.controller.js
  • apps/python-service/config.py
  • apps/python-service/routers/ai.py
  • apps/python-service/services/byok.py
  • apps/python-service/tests/test_byok.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/dashboard-api/src/tests/routes.user.test.js
  • apps/python-service/config.py
  • apps/python-service/routers/ai.py

Comment thread apps/dashboard-api/src/controllers/ai.controller.js Outdated
Comment thread apps/python-service/services/byok.py Outdated
@yash-pouranik
yash-pouranik temporarily deployed to feat/byok-ai - urBackend-frankfrut PR #383 August 6, 2026 19:10 — with Render Destroyed
@yash-pouranik
yash-pouranik merged commit e7b1e5a into main Aug 6, 2026
5 checks passed

This branch was successfully deployed

2 active deployments
Preview – ur-backend-web-dashboard — f83a6ab2 Deployed Aug 6, 2026 by vercel[bot]
Preview – urbackend — f83a6ab2 Deployed Aug 6, 2026 by vercel[bot]
feat/byok-ai - urBackend-frankfrut PR #383 — f83a6ab2 Deployed Aug 6, 2026 by yash-pouranik
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants