Skip to content

Dev - #51

Merged
rekabytes merged 4 commits into
mainfrom
dev
Dec 30, 2025
Merged

Dev#51
rekabytes merged 4 commits into
mainfrom
dev

Conversation

@rekabytes

@rekabytes rekabytes commented Dec 30, 2025

Copy link
Copy Markdown
Owner

📝 Description

Brief description of what this PR does.

🔗 Related Issue

Fixes #(issue number)

🏷️ Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📚 Documentation update
  • 🧹 Code refactoring (no functional changes)
  • 🧪 Test update (adding or updating tests)

✅ Checklist

  • I have read the Contributing Guidelines
  • My branch is created from dev (not main)
  • I have run pnpm lint:fix
  • I have run pnpm typecheck
  • I have tested my changes locally
  • My code follows the project's coding standards
  • I have updated documentation (if applicable)

📸 Screenshots (if applicable)

Add screenshots to help explain your changes.

🧪 How to Test

Steps to test this PR:

  1. ...
  2. ...
  3. ...

📝 Additional Notes

Any additional information reviewers should know.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added monthly usage tracking and display in dashboard and API key management pages
    • Introduced per-minute, daily, and monthly rate limit visibility in current tier displays
    • Enhanced rate limit response headers with granular time-based limits and detailed limit types
  • Documentation

    • Expanded API documentation with detailed tier limits, burst configuration, and VPS safety caps
  • Improvements

    • Improved responsive design with enhanced breakpoint support for wider screens
    • Better handling of user email data during profile sync

✏️ Tip: You can customize this high-level summary in your review settings.

- Add monthlyLimit to RateLimitConfig (free: 3000, tier_1: 7000, tier_2: 20000)
- Update getUsageStats backend query to aggregate monthly usage
- Add Monthly Usage card to dashboard and API Keys pages
- Update settings page to show monthly limit info
- Enhance useBreakpoint hook with 3xl (1920px) and 4xl (2560px) breakpoints
- Add isWideScreen, isUltraWide, and screenCategory helpers
- Add CSS auto-fit grid utilities for automatic responsive layouts
- Support 2K and 4K resolution screens with proper spacing
- Update API docs with complete tier rate limits table
Rate Limits by Tier:
- Free: 65/min, 3,300/day, 95,000/month, burst +15 (max 80)
- Tier 1: 130/min, 6,600/day, 195,000/month, burst +30 (max 160)
- Tier 2: 145/min, 7,500/day, 215,000/month, burst +45 (max 190)

VPS Safety Caps:
- Max 20 requests/second (global)
- Max 5 concurrent requests per API key

Changes:
- Expand RateLimitConfig with minuteLimit, dailyLimit, monthlyLimit
- Add burst config: burstBonus, burstWindowSeconds, maxBurstTotal
- Add VpsSafetyCaps interface and VPS_SAFETY_CAPS constant
- Rewrite rate-limit middleware with multi-level checking
- Add second-level tracking for VPS safety cap
- Update all dashboard components to use new limit fields
- Update API documentation with comprehensive rate limit info
- Drop unique index on email field (via cleanup script)
- Update User type to allow email: string | null
- Change context.ts to store null instead of empty string
- Prevents E11000 duplicate key errors for social login users without email
…acker-for-1-month

Kairul/kal 38 feat add limit tracker for 1 month
@coderabbitai

coderabbitai Bot commented Dec 30, 2025

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The PR introduces a multi-level rate-limiting system with per-minute, daily, and monthly quotas alongside burst bonuses and VPS safety caps. It updates backend middleware to track granular time windows, extends shared type definitions, adds monthly usage tracking and responsive grid utilities to frontend dashboards, and adjusts user data models to support nullable email fields.

Changes

Cohort / File(s) Summary
Documentation
docs/api.md
Updated rate-limit specification from single-level to multi-tier (minute, daily, monthly) with burst configuration details, safety caps, and expanded header format.
Backend Rate-Limit Middleware
packages/kal-backend/src/middleware/rate-limit.ts
Introduced per-second and per-minute time-window tracking, VPS safety cap enforcement, granular limit type detection (second/minute/daily/monthly), new response fields (minuteCount, secondCount, monthlyLimit), and expanded rate-limit header generation (X-RateLimit-Limit-Minute, X-RateLimit-Limit-Monthly, X-RateLimit-Type).
Backend Data Layer
packages/kal-backend/src/lib/context.ts, packages/kal-backend/src/routers/api-keys.ts
Modified email upsert to default to null instead of empty string; added monthly usage aggregation via MongoDB pipeline in usage stats endpoint.
Shared Type Definitions
packages/kal-shared/src/types/index.ts
Extended RateLimitConfig and RateLimitUsage with minute/second/monthly windows and counters; replaced single burstLimit with granular burst fields (burstBonus, burstWindowSeconds, maxBurstTotal); introduced VpsSafetyCaps interface; changed User.email from string to string | null.
Frontend Hooks
packages/kal-frontend/src/hooks/useBreakpoint.ts, packages/kal-frontend/src/app/globals.css
Extended breakpoint model to 3xl and 4xl; added responsive grid utility classes (grid-auto-fit-xs through grid-auto-fit-xl) and container fluid utilities; exposed isWideScreen, isUltraWide, and screenCategory from useBreakpoint hook.
Frontend Dashboard UI
packages/kal-frontend/src/app/dashboard/client.tsx, packages/kal-frontend/src/app/dashboard/api-keys/client.tsx, packages/kal-frontend/src/app/dashboard/settings/client.tsx
Added monthly usage metrics display (monthlyUsed, monthlyRemaining, monthlyPercentage) across dashboard views; updated limit displays to include minuteLimit and monthlyLimit; refactored grid layouts to use responsive auto-fit utilities and removed max-width constraints.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Poem

🐰 Hops through code with a leap and a bound,
Rate limits in layers, safety caps all around!
Monthly metrics now shine on the screen,
Responsive dashboards—the finest I've seen! 🌟
Per-minute, per-second, per-month, hooray!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The pull request title 'Dev' is extremely vague and does not clearly summarize the main changes, which involve multi-level rate limiting, monthly usage tracking, VPS safety caps, and user email handling fixes. Replace with a descriptive title that captures the primary change, such as 'Implement multi-level rate limiting with monthly usage tracking and VPS safety caps' or similar.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings

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: 4

🧹 Nitpick comments (7)
packages/kal-backend/src/routers/api-keys.ts (1)

168-187: Monthly aggregation logic is correct; consider index optimization for scale.

The implementation correctly aggregates daily counts for the current month. However, the regex match on date field ($regex: ^${currentMonth}) may not utilize indexes efficiently.

For better query performance at scale, consider a range-based match:

🔎 Optional optimization using date range
 const monthlyAggregation = await ctx.db
   .collection<RateLimitUsage>("rate_limit_usage")
   .aggregate([
     {
       $match: {
         userId: ctx.userId,
-        date: { $regex: `^${currentMonth}` },
+        date: { 
+          $gte: `${currentMonth}-01`,
+          $lte: `${currentMonth}-31`
+        },
       },
     },
     ...
   ])

This allows MongoDB to use a compound index on (userId, date) more effectively.

packages/kal-frontend/src/app/dashboard/settings/client.tsx (1)

109-121: Consider responsive breakpoints for the 3-column grid.

The fixed grid-cols-3 may cause cramped layouts on smaller screens. Consider using responsive classes for better mobile experience.

🔎 Suggested responsive fix
-<div className="grid grid-cols-3 gap-4 pt-4 border-t border-dark-border">
+<div className="grid grid-cols-1 sm:grid-cols-3 gap-4 pt-4 border-t border-dark-border">
packages/kal-shared/src/types/index.ts (1)

25-28: Burst configuration fields are defined but not enforced.

The burstBonus, burstWindowSeconds, and maxBurstTotal fields are defined here and values are set in RATE_LIMITS, but the rate-limit middleware (packages/kal-backend/src/middleware/rate-limit.ts) doesn't implement any burst logic. The RateLimitUsage interface also has burstWindowStart and burstCount fields that aren't being used.

If burst limiting is planned for future implementation, consider adding a TODO comment. Otherwise, remove these unused fields to avoid confusion.

packages/kal-backend/src/middleware/rate-limit.ts (4)

140-150: Consider adding monthlyLimit for consistency.

The "second" limit response doesn't include monthlyLimit, but the "daily" limit response does. For consistent header generation, consider adding it.

🔎 Proposed fix
       return {
         limited: true,
         retryAfter: 1, // Wait 1 second
         limitType: "second",
         secondCount,
         minuteCount: usage.minuteCount,
         dailyCount: usage.dailyCount,
         minuteLimit: limits.minuteLimit,
         dailyLimit: limits.dailyLimit,
+        monthlyLimit: limits.monthlyLimit,
       };

162-171: Missing monthlyLimit in minute-limited response.

Same as the second-limit response, monthlyLimit is missing here but included in the daily-limit response.

🔎 Proposed fix
       return {
         limited: true,
         retryAfter,
         limitType: "minute",
         minuteCount: usage.minuteCount,
         dailyCount: usage.dailyCount,
         minuteLimit: limits.minuteLimit,
         dailyLimit: limits.dailyLimit,
+        monthlyLimit: limits.monthlyLimit,
       };

182-191: Missing minuteLimit in daily-limited response.

This response includes monthlyLimit but omits minuteLimit, creating inconsistency with other responses.

🔎 Proposed fix
       return {
         limited: true,
         retryAfter: secondsUntilMidnight,
         limitType: "daily",
         dailyCount: usage.dailyCount,
         minuteCount: usage.minuteCount,
+        minuteLimit: limits.minuteLimit,
         dailyLimit: limits.dailyLimit,
         monthlyLimit: limits.monthlyLimit,
       };

225-228: Use logger.error for consistency.

Line 227 uses console.error while the rest of the file uses logger. For consistent logging and structured output, consider using the logger.

🔎 Proposed fix
     // Log stack trace for debugging
     if (errorStack) {
-      console.error("Rate limit error stack trace:", errorStack);
+      logger.error("Rate limit error stack trace", { stack: errorStack });
     }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5b25d0a and a70fe3b.

📒 Files selected for processing (10)
  • docs/api.md
  • packages/kal-backend/src/lib/context.ts
  • packages/kal-backend/src/middleware/rate-limit.ts
  • packages/kal-backend/src/routers/api-keys.ts
  • packages/kal-frontend/src/app/dashboard/api-keys/client.tsx
  • packages/kal-frontend/src/app/dashboard/client.tsx
  • packages/kal-frontend/src/app/dashboard/settings/client.tsx
  • packages/kal-frontend/src/app/globals.css
  • packages/kal-frontend/src/hooks/useBreakpoint.ts
  • packages/kal-shared/src/types/index.ts
🧰 Additional context used
🧬 Code graph analysis (2)
packages/kal-backend/src/routers/api-keys.ts (1)
packages/kal-shared/src/types/index.ts (1)
  • RateLimitUsage (69-90)
packages/kal-backend/src/middleware/rate-limit.ts (1)
packages/kal-shared/src/types/index.ts (2)
  • RateLimitUsage (69-90)
  • VPS_SAFETY_CAPS (64-67)
🪛 markdownlint-cli2 (0.18.1)
docs/api.md

330-330: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (18)
packages/kal-frontend/src/hooks/useBreakpoint.ts (1)

5-6: LGTM! Well-structured breakpoint extension.

The implementation correctly extends the breakpoint system with 3xl (1920px) and 4xl (2560px) thresholds for wide/ultrawide screens. The SSR-safe defaults are preserved, and the getScreenCategory function provides a clean abstraction for broader screen classifications.

Also applies to: 14-15, 59-61, 81-82, 91-97, 106-108

packages/kal-backend/src/lib/context.ts (1)

34-34: LGTM! Correct handling of nullable email.

Using null instead of an empty string for missing emails is the correct approach. This prevents duplicate key errors on unique email indexes for social login users without email addresses and aligns with the User type definition (email: string | null).

docs/api.md (1)

305-324: LGTM! Comprehensive rate limit documentation.

The updated documentation clearly explains the multi-level rate limiting system with tier-specific limits, burst configuration, and VPS safety caps. This provides excellent guidance for API consumers.

packages/kal-frontend/src/app/globals.css (2)

884-935: LGTM! Well-designed responsive grid utilities.

The auto-fit grid system using CSS custom properties is a clean, maintainable approach. The minmax() pattern with CSS variables allows easy customization while providing automatic column adjustment based on available space.


958-1017: LGTM! Progressive enhancement for containers and ultra-wide screens.

The fluid container utilities with progressive padding and the ultra-wide stats-grid adjustments provide appropriate enhancements for larger displays without breaking smaller viewports.

packages/kal-frontend/src/app/dashboard/api-keys/client.tsx (2)

114-116: LGTM! Consistent monthly usage implementation.

The monthly usage metrics follow the same pattern as daily usage, maintaining code consistency. The progress bar implementation and number formatting with toLocaleString() provide a good user experience.

Also applies to: 155-167


128-139: LGTM! Good adoption of responsive grid utilities.

Using grid-auto-fit-md from the new CSS utilities provides automatic responsive behavior without manual breakpoint management. The tier info card now comprehensively displays all rate limit tiers (minute/daily/monthly).

packages/kal-frontend/src/app/dashboard/client.tsx (2)

53-55: LGTM! Consistent monthly usage implementation across dashboard.

The monthly usage metrics and UI card implementation are consistent with the API keys page, providing a unified experience. The calculations follow the same pattern as daily usage metrics.

Also applies to: 97-109


70-70: LGTM! Good use of responsive grid utilities.

The adoption of grid-auto-fit-md for stats cards and grid-auto-fit-lg for quick actions provides appropriate responsive behavior with automatically adjusted column counts based on available space.

Also applies to: 125-125

packages/kal-shared/src/types/index.ts (3)

6-14: LGTM!

The email: string | null change properly supports social login users who may not have an email address. This aligns with the PR objective to handle nullable emails and prevent duplicate-key errors.


31-56: LGTM!

The rate limit configurations are well-structured and internally consistent. The maxBurstTotal values correctly equal minuteLimit + burstBonus for each tier.


69-90: LGTM!

The RateLimitUsage interface properly defines required fields for daily/minute tracking and optional fields for second-level tracking and burst windows, supporting backward compatibility with existing documents.

packages/kal-backend/src/middleware/rate-limit.ts (6)

7-21: LGTM!

The RateLimitResult interface is well-structured with clear separation of counts and limits. The optional fields allow flexible response composition based on which limit was triggered.


36-56: LGTM!

Time window calculations are correct. minuteStart.setSeconds(0, 0) properly resets both seconds and milliseconds, while secondStart.setMilliseconds(0) resets only milliseconds for second-level granularity.


106-129: LGTM!

The upsert pattern is correct for MongoDB driver 6.x which returns the document directly. The null check provides a safe fallback, though as noted this shouldn't occur with upsert: true.


193-204: LGTM!

The comment clearly documents that monthly limits are checked via aggregation elsewhere, and the success response includes all relevant counts and limits for header generation.


247-252: LGTM!

The getSecondsUntilMidnight implementation correctly uses setUTCHours(24, 0, 0, 0) to roll to the next day's midnight UTC.


257-286: LGTM!

Header generation is well-structured. The absence of X-RateLimit-Remaining-Monthly is consistent with the design decision to calculate monthly usage via aggregation elsewhere.

Comment thread docs/api.md
Comment on lines 330 to 338
```
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1703548800
X-RateLimit-Limit-Minute: 65
X-RateLimit-Remaining-Minute: 60
X-RateLimit-Limit-Daily: 3300
X-RateLimit-Remaining-Daily: 3295
X-RateLimit-Limit-Monthly: 95000
Retry-After: 5
X-RateLimit-Type: 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 | 🟡 Minor

Add language specifier to fenced code block.

The static analysis tool correctly identifies that the fenced code block lacks a language specifier. Adding one improves syntax highlighting and accessibility.

🔎 Proposed fix
-```
+```http
 X-RateLimit-Limit-Minute: 65
 X-RateLimit-Remaining-Minute: 60
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

330-330: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In docs/api.md around lines 330 to 338 the fenced code block is missing a
language specifier; update the opening fence to include the language (e.g.,
change ``` to ```http) so the block becomes a fenced "http" code block for
proper syntax highlighting and accessibility.

Comment on lines +26 to +30
* Rate limit hierarchy (checked in order):
* 1. VPS Safety Cap: 20 requests/second (global)
* 2. Minute limit: varies by tier (65/130/110 per minute)
* 3. Daily limit: varies by tier
* 4. Monthly limit: varies by tier

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 | 🟡 Minor

Fix outdated comment: tier_2 minute limit is 145, not 110.

The comment states 65/130/110 per minute, but according to RATE_LIMITS in the shared types, tier_2 has minuteLimit: 145.

🔎 Proposed fix
 * Rate limit hierarchy (checked in order):
 * 1. VPS Safety Cap: 20 requests/second (global)
-* 2. Minute limit: varies by tier (65/130/110 per minute)
+* 2. Minute limit: varies by tier (65/130/145 per minute)
 * 3. Daily limit: varies by tier
 * 4. Monthly limit: varies by tier
📝 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
* Rate limit hierarchy (checked in order):
* 1. VPS Safety Cap: 20 requests/second (global)
* 2. Minute limit: varies by tier (65/130/110 per minute)
* 3. Daily limit: varies by tier
* 4. Monthly limit: varies by tier
* Rate limit hierarchy (checked in order):
* 1. VPS Safety Cap: 20 requests/second (global)
* 2. Minute limit: varies by tier (65/130/145 per minute)
* 3. Daily limit: varies by tier
* 4. Monthly limit: varies by tier
🤖 Prompt for AI Agents
In packages/kal-backend/src/middleware/rate-limit.ts around lines 26 to 30, the
inline comment listing per-minute tier limits is outdated (shows "65/130/110 per
minute") — update that comment to reflect the current RATE_LIMITS which set
tier_2 minuteLimit to 145 (e.g., "65/130/145 per minute") so the documentation
matches the shared types; edit only the comment block to replace 110 with 145
and keep wording consistent.

Comment on lines 57 to +104
try {
// First, get current usage to check minute window
// First, get current usage to check windows
const existingUsage = await collection.findOne({ _id: compositeId as unknown as string });

// Check if we're in a new minute window
// Check if we're in new time windows
const isNewMinute =
!existingUsage?.minuteWindow ||
new Date(existingUsage.minuteWindow).getTime() < minuteStart.getTime();

const isNewSecond =
!existingUsage?.secondWindow ||
new Date(existingUsage.secondWindow).getTime() < secondStart.getTime();

// Use atomic upsert - single operation for both create and update
// This prevents race conditions and duplicate key errors
const updateDoc = isNewMinute || !existingUsage
? {
// New minute or first request: reset minute counter
$inc: { dailyCount: 1 },
$set: {
minuteWindow: minuteStart,
minuteCount: 1,
updatedAt: now,
},
$setOnInsert: {
userId,
date: today,
},
}
: {
// Same minute: increment both counters
$inc: { dailyCount: 1, minuteCount: 1 },
$set: { updatedAt: now },
};
// Build update document based on window states
interface UpdateOperation {
$inc: Record<string, number>;
$set: Record<string, Date | number>;
$setOnInsert?: Record<string, string>;
}

const updateDoc: UpdateOperation = {
$inc: { dailyCount: 1 },
$set: { updatedAt: now },
};

// Handle minute window
if (isNewMinute || !existingUsage) {
updateDoc.$set.minuteWindow = minuteStart;
updateDoc.$set.minuteCount = 1;
} else {
updateDoc.$inc.minuteCount = 1;
}

// Handle second window (for VPS safety cap)
if (isNewSecond || !existingUsage) {
updateDoc.$set.secondWindow = secondStart;
updateDoc.$set.secondCount = 1;
} else {
updateDoc.$inc.secondCount = 1;
}

// Set on insert for new documents
if (!existingUsage) {
updateDoc.$setOnInsert = {
userId,
date: today,
};
}

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 | 🟠 Major

Race condition: concurrent requests may lose counts.

The pattern of findOne followed by findOneAndUpdate creates a race window. If two concurrent requests both see existingUsage as null (or both see the same stale minuteWindow), they'll both execute $set.minuteCount = 1 instead of incrementing, losing a count.

Consider using a single atomic update with conditional operators like $cond in an aggregation pipeline update, or accept the minor inaccuracy for simplicity. Given the VPS safety cap of 20 req/s, this race is likely rare but could affect burst scenarios.

🔎 Alternative: Use aggregation pipeline for atomic window reset

MongoDB 4.2+ supports aggregation pipelines in updates for conditional logic:

const result = await collection.findOneAndUpdate(
  { _id: compositeId },
  [
    {
      $set: {
        userId: { $ifNull: ["$userId", userId] },
        date: { $ifNull: ["$date", today] },
        updatedAt: now,
        // Minute window: reset if new window, otherwise keep
        minuteWindow: {
          $cond: {
            if: { $lt: [{ $ifNull: ["$minuteWindow", new Date(0)] }, minuteStart] },
            then: minuteStart,
            else: "$minuteWindow"
          }
        },
        minuteCount: {
          $cond: {
            if: { $lt: [{ $ifNull: ["$minuteWindow", new Date(0)] }, minuteStart] },
            then: 1,
            else: { $add: [{ $ifNull: ["$minuteCount", 0] }, 1] }
          }
        },
        // Similar for secondWindow/secondCount...
        dailyCount: { $add: [{ $ifNull: ["$dailyCount", 0] }, 1] }
      }
    }
  ],
  { upsert: true, returnDocument: "after" }
);

This ensures atomicity without a preliminary read.

🤖 Prompt for AI Agents
In packages/kal-backend/src/middleware/rate-limit.ts around lines 57 to 104, the
current findOne then findOneAndUpdate flow creates a race where concurrent
requests can both treat a window as "new" and reset counts (losing increments);
replace the two-step read+update with a single atomic findOneAndUpdate using an
aggregation-pipeline update that uses $set/$cond/$ifNull/$add to: set
userId/date on insert, set updatedAt, reset minuteWindow/secondWindow and set
minuteCount/secondCount to 1 when the stored window is older than the computed
window, otherwise add 1 to the existing counts, and always $add to dailyCount;
ensure options include upsert: true and returnDocument: "after" so the operation
is atomic and returns the updated counters.

Comment on lines +64 to 67
export const VPS_SAFETY_CAPS: VpsSafetyCaps = {
maxRequestsPerSecond: 20,
maxConcurrentPerApiKey: 5,
};

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 | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

rg -n "maxConcurrentPerApiKey" --type ts

Repository: Zen0space/Kal-Monorepo

Length of output: 212


🏁 Script executed:

rg -n "VPS_SAFETY_CAPS" --type ts

Repository: Zen0space/Kal-Monorepo

Length of output: 489


🏁 Script executed:

rg -n "maxConcurrent" --type ts

Repository: Zen0space/Kal-Monorepo

Length of output: 212


🏁 Script executed:

fd -name "*middleware*" -o -name "*rate*" --type f

Repository: Zen0space/Kal-Monorepo

Length of output: 296


🏁 Script executed:

find . -name "*middleware*" -type f 2>/dev/null

Repository: Zen0space/Kal-Monorepo

Length of output: 125


🏁 Script executed:

rg -n "concurrent" -i --type ts

Repository: Zen0space/Kal-Monorepo

Length of output: 212


🏁 Script executed:

rg -n "api.?key.*middleware\|api.?key.*rate" -i --type ts

Repository: Zen0space/Kal-Monorepo

Length of output: 48


🏁 Script executed:

cat -n ./packages/kal-backend/src/middleware/api-key-middleware.ts

Repository: Zen0space/Kal-Monorepo

Length of output: 6356


Remove unused maxConcurrentPerApiKey or implement concurrent request limiting.

maxConcurrentPerApiKey: 5 is defined in VPS_SAFETY_CAPS but never enforced anywhere in the codebase. It is not used in rate-limit.ts or api-key-middleware.ts. Either implement the concurrent request limiting logic using this constant or remove it from the type definition and export to avoid misleading developers about the actual safety measures in place.

🤖 Prompt for AI Agents
packages/kal-shared/src/types/index.ts lines 64-67: VPS_SAFETY_CAPS currently
defines maxConcurrentPerApiKey:5 but this limit is never enforced; either remove
the property from the exported constant and the VpsSafetyCaps type, or implement
enforcement in the request pipeline: add a per-api-key in-flight
counter/semaphore (e.g., Map<apiKey, number> or a lightweight semaphore) that
increments at request start and decrements on finish/error, check against
VPS_SAFETY_CAPS.maxConcurrentPerApiKey and immediately respond with 429 when
exceeded, and ensure the counter is decremented in all code paths (including
error and timeouts) to avoid leaks.

@rekabytes
rekabytes merged commit ef394c9 into main Dec 30, 2025
7 checks passed
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.

1 participant