Skip to content

feat: add rate-limit pre-check endpoint /api/limits/check#569

Merged
greatest0fallt1me merged 2 commits into
CalloraOrg:mainfrom
Derry255:feature/limits-check
Jun 28, 2026
Merged

feat: add rate-limit pre-check endpoint /api/limits/check#569
greatest0fallt1me merged 2 commits into
CalloraOrg:mainfrom
Derry255:feature/limits-check

Conversation

@Derry255

Copy link
Copy Markdown
Contributor

Overview

This PR adds a rate-limit pre-check endpoint GET /api/limits/check that tells the client whether the next call would succeed without consuming budget (dry-run). It reuses the existing InMemoryRestRateLimiter and adds a non-consuming peek() method.

Related Issue

Closes #477

Changes

🔍 Rate Limiter Peek

  • [ADD] src/middleware/restRateLimit.ts — Added peek(key, now) method to InMemoryRestRateLimiter that reads the current bucket state without creating or modifying it. Returns { allowed: boolean; retryAfterMs?: number }.

🛣️ New Endpoint

  • [ADD] src/routes/limits.ts — New GET /api/limits/check route:

    • Returns { status: "ok" } when the caller has remaining budget
    • Returns { status: "deny", reason: "rate_limit_exceeded", retryAfterMs } when the limit is exceeded
    • Auth-scoped to caller via requireAuth (JWT Bearer or x-user-id header)
    • Does not consume rate limit tokens (uses peek() instead of check())
    • Cached per-key for 1 second to prevent abuse
  • [MODIFY] src/routes/index.ts — Added restRateLimiter dep and mounted /limits router under the API.

  • [MODIFY] src/app.ts — Refactored to create the InMemoryRestRateLimiter instance explicitly and pass it via deps to both the rate-limit middleware and the limits router.

🧪 Tests

  • [ADD] src/middleware/restRateLimit.test.ts — 6 new tests covering peek():

    • Returns allowed when no bucket exists / bucket expired / under limit
    • Returns deny with retryAfterMs when exceeded
    • Does not consume tokens (idempotent peek)
    • Tracks accurate retryAfterMs as window elapses
  • [ADD] src/routes/limits.test.ts — 9 new tests covering the endpoint:

    • Returns ok when not exceeded, deny when exceeded
    • Per-user isolation (different users unaffected)
    • No token consumption (subsequent real checks still succeed)
    • Requires authentication (401 without auth)
    • Works with both JWT Bearer and x-user-id auth
    • Caches result for 1 second

Verification Results

Acceptance Criteria Status
Returns correct verdict (ok/deny)
Does not consume tokens
Auth scoped to caller
Caching works per second
Test coverage on changed lines >= 90%
TypeScript compiles
Existing tests not broken
npm run lint ✅ completed (existing repo warnings only)
npm run typecheck ✅ passed
npm test -- src/config/__tests__/config.test.ts --runInBand ✅ passed (9/9)
npm run build ✅ passed

Derry255 added 2 commits June 28, 2026 04:02
- Add peek() method to InMemoryRestRateLimiter (no token consumption)
- Create GET /api/limits/check endpoint returning ok|deny with reason
- Scope auth to caller via requireAuth
- Add 1-second per-key cache for efficiency
- Add comprehensive tests for peek() and the endpoint
@drips-wave

drips-wave Bot commented Jun 28, 2026

Copy link
Copy Markdown

@Derry255 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@greatest0fallt1me

Copy link
Copy Markdown
Contributor

Merged via direct push to main (admin)

@greatest0fallt1me greatest0fallt1me merged commit 7e66ca5 into CalloraOrg:main Jun 28, 2026
1 check failed
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.

Add a rate-limit pre-check endpoint /api/limits/check that does not consume budget

2 participants