Skip to content

refactor(rate-limit): move the algorithm to limitkit; limits stay app semantics - #897

Merged
github-actions[bot] merged 1 commit into
mainfrom
refactor/limitkit
Sep 5, 2026
Merged

refactor(rate-limit): move the algorithm to limitkit; limits stay app semantics#897
github-actions[bot] merged 1 commit into
mainfrom
refactor/limitkit

Conversation

@catomean

@catomean catomean commented Sep 5, 2026

Copy link
Copy Markdown
Collaborator

Adopts the fleet package limitkit@0.2.0 as OrangeCat's rate-limit engine, completing ADR-0002's remaining work (addendum added in this PR). src/lib/rate-limit.ts keeps its full export surface — 138 importers untouched, every limit VALUE preserved exactly — but now only declares the limits, while limitkit supplies the sliding-window arithmetic, the bounded MemoryStore, and the standard X-RateLimit-*/Retry-After headers (ADR-0002's spec: Reset in epoch seconds, Retry-After on refusals only). Deleted: the hand-rolled InMemoryRateLimiter, the never-configured Upstash Redis path plus the @upstash/ratelimit/@upstash/redis dependencies (the in-memory fallback was always the live path on the single self-hosted instance, so runtime behaviour is unchanged), health.ts's Upstash cache probe and its "Cache" service row, the hand-rolled X-Forwarded-For parsing in src/lib/client-ip.ts (now limitkit's clientIp(), same last-hop correction, trustedProxies: 1 for the one Caddy hop), one route-local header-emission duplicate, and the unused _resetActionRateLimits test seam. New unit test pins every limit value locally, per limitkit's "no limits in the package" contract. Ops docs stop instructing operators to set UPSTASH_* env vars.

🤖 Generated with Claude Code

… semantics

Adopt limitkit@0.2.0 (fleet package) as the rate-limit engine, completing
ADR-0002's remaining work:

- src/lib/rate-limit.ts keeps its full export surface (138 importers
  untouched) but now only declares the LIMITS — every value preserved
  exactly — while limitkit supplies the sliding-window arithmetic, the
  bounded MemoryStore, and the standard headers. The five-fold
  upstash-limiter + fallback-limiter + function triple is gone.
- Delete the never-configured Upstash path and the @upstash/ratelimit +
  @upstash/redis dependencies; the live path was always the in-memory
  fallback on the single self-hosted instance, so runtime behaviour is
  unchanged. A second instance now means implementing limitkit's
  two-method Store over shared infrastructure, not a parallel code path.
- src/lib/client-ip.ts delegates X-Forwarded-For parsing to limitkit's
  clientIp() (same last-hop correction, trustedProxies: 1 for the one
  Caddy hop); the app keeps its 'anonymous' bucket naming and the
  clientIpOrUndefined address variant. check:client-ip gate unchanged.
- Headers now follow ADR-0002's spec exactly via limitkit toHeaders:
  X-RateLimit-Reset in epoch seconds (was ms), Retry-After on refusals
  only (was also emitted on success responses).
- health.ts drops the Upstash cache probe and its "Cache" service row —
  there is no cache dependency left to probe, and a hard-coded
  "operational" row would be a fake metric. uptime.yml only reads
  services.authentication, which is untouched.
- Drop _resetActionRateLimits (referenced by nothing).
- New __tests__/unit/rate-limit.test.ts pins every limit value — limits
  are app semantics, asserted locally, per limitkit's own contract.
- ADR-0002 gains a dated addendum; ops docs stop instructing operators
  to set UPSTASH_* env vars.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WqKqMnHQHSmkGFfc5t7Rxn
@github-actions
github-actions Bot merged commit 1ee64e9 into main Sep 5, 2026
6 checks passed
@github-actions
github-actions Bot deleted the refactor/limitkit branch September 5, 2026 16:35
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