vibes-plug 2.5.0 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/.claude/rules/vibes-plug-core.md +32 -0
  2. package/.cursor/rules/vibes-plug-core.mdc +51 -0
  3. package/.cursorrules +42 -0
  4. package/AGENTS.md +37 -7
  5. package/BLUEPRINT.md +309 -217
  6. package/CHANGELOG.md +133 -1
  7. package/CLAUDE.md +70 -0
  8. package/LICENSE +1 -1
  9. package/README.md +641 -415
  10. package/index.js +19 -0
  11. package/package.json +44 -8
  12. package/plugin.json +24 -7
  13. package/scripts/generate_swarm_gif.py +295 -0
  14. package/scripts/install.js +201 -0
  15. package/skills/accessibility-testing-expert/SKILL.md +116 -0
  16. package/skills/ai-cost-token-optimizer/SKILL.md +82 -52
  17. package/skills/ai-evals-benchmark-expert/SKILL.md +188 -0
  18. package/skills/ai-llm-integration-expert/SKILL.md +185 -178
  19. package/skills/ai-media-generation-expert/SKILL.md +172 -0
  20. package/skills/ai-prompt-engineering-expert/SKILL.md +84 -0
  21. package/skills/angular-expert/SKILL.md +148 -0
  22. package/skills/api-design-expert/SKILL.md +6 -3
  23. package/skills/api-gateway-proxy-expert/SKILL.md +81 -0
  24. package/skills/app-analyzer-optimizer/SKILL.md +6 -3
  25. package/skills/apple-ecosystem-expert/SKILL.md +144 -141
  26. package/skills/{asisten_ramah → asisten-ramah}/SKILL.md +7 -1
  27. package/skills/astro-framework-expert/SKILL.md +200 -0
  28. package/skills/async-queue-temporal-expert/SKILL.md +210 -24
  29. package/skills/authentication-identity-expert/SKILL.md +278 -275
  30. package/skills/auto-doc-updater/SKILL.md +7 -1
  31. package/skills/autonomous-chaos-monkey/SKILL.md +63 -63
  32. package/skills/autonomous-red-teamer/SKILL.md +172 -28
  33. package/skills/autonomous-tdd-debugger/SKILL.md +70 -64
  34. package/skills/background-jobs-queue-expert/SKILL.md +235 -0
  35. package/skills/biome-linter-formatter-expert/SKILL.md +89 -0
  36. package/skills/blockchain-web3-expert/SKILL.md +115 -0
  37. package/skills/bootstrap-to-modern/SKILL.md +9 -6
  38. package/skills/brainstorming/SKILL.md +58 -50
  39. package/skills/browser-automation-expert/SKILL.md +197 -21
  40. package/skills/bun-runtime-expert/SKILL.md +7 -1
  41. package/skills/chatbot-messaging-expert/SKILL.md +114 -0
  42. package/skills/ci-cd-devops-architect/SKILL.md +45 -36
  43. package/skills/cloud-hosting-expert/SKILL.md +7 -1
  44. package/skills/coderabbit/SKILL.md +7 -1
  45. package/skills/compliance-gdpr-privacy-expert/SKILL.md +85 -0
  46. package/skills/cron-scheduler-expert/SKILL.md +303 -297
  47. package/skills/data-pipeline-etl-expert/SKILL.md +84 -0
  48. package/skills/data-telemetry-expert/SKILL.md +7 -1
  49. package/skills/data-visualization-expert/SKILL.md +154 -0
  50. package/skills/database-migration-versioning-expert/SKILL.md +90 -0
  51. package/skills/database-orm-expert/SKILL.md +13 -3
  52. package/skills/dependency-upgrade-migrator/SKILL.md +300 -294
  53. package/skills/design-system-architect/SKILL.md +278 -259
  54. package/skills/desktop-electron-expert/SKILL.md +128 -0
  55. package/skills/documentation-site-expert/SKILL.md +59 -0
  56. package/skills/doku-mcp-server/SKILL.md +7 -1
  57. package/skills/doku-payment-gateway/SKILL.md +7 -1
  58. package/skills/domain-driven-design-expert/SKILL.md +82 -0
  59. package/skills/e2e-testing-expert/SKILL.md +7 -1
  60. package/skills/ecommerce-expert/SKILL.md +87 -0
  61. package/skills/edge-serverless-db-expert/SKILL.md +98 -42
  62. package/skills/email-notification-expert/SKILL.md +367 -361
  63. package/skills/error-resilience-expert/SKILL.md +485 -479
  64. package/skills/event-driven-architect/SKILL.md +7 -1
  65. package/skills/feature-flag-analytics-expert/SKILL.md +65 -45
  66. package/skills/file-upload-media-expert/SKILL.md +436 -430
  67. package/skills/firebase-security-expert/SKILL.md +7 -1
  68. package/skills/form-validation-expert/SKILL.md +406 -400
  69. package/skills/fullstack-expert/SKILL.md +60 -1
  70. package/skills/gemini-agent-booster/SKILL.md +173 -135
  71. package/skills/geospatial-maps-expert/SKILL.md +80 -0
  72. package/skills/global-a11y-i18n-expert/SKILL.md +7 -1
  73. package/skills/glsl-shader-expert/SKILL.md +106 -100
  74. package/skills/go-programming-expert/SKILL.md +21 -15
  75. package/skills/graph-rag-knowledge-expert/SKILL.md +159 -0
  76. package/skills/graphql-apollo-expert/SKILL.md +113 -107
  77. package/skills/headless-cms-expert/SKILL.md +181 -0
  78. package/skills/hig/SKILL.md +7 -1
  79. package/skills/js-backend-expert/SKILL.md +218 -216
  80. package/skills/legacy-code-translator/SKILL.md +70 -64
  81. package/skills/local-slm-edge-ai-expert/SKILL.md +167 -0
  82. package/skills/logging-error-tracking-expert/SKILL.md +343 -337
  83. package/skills/mcp-client-orchestrator/SKILL.md +75 -69
  84. package/skills/mcp-server-architect/SKILL.md +294 -194
  85. package/skills/micro-frontend-architect/SKILL.md +111 -105
  86. package/skills/mobile-expo-expert/SKILL.md +8 -2
  87. package/skills/mobile-push-notification-expert/SKILL.md +70 -50
  88. package/skills/modern-css-native-expert/SKILL.md +189 -0
  89. package/skills/monday-design-aesthetic/SKILL.md +7 -1
  90. package/skills/monorepo-architect/SKILL.md +7 -1
  91. package/skills/mpa-orchestrator/SKILL.md +20 -1
  92. package/skills/multi-agent-orchestration/SKILL.md +254 -234
  93. package/skills/multiple-entry-points/SKILL.md +37 -1
  94. package/skills/mvc-expert/SKILL.md +7 -1
  95. package/skills/n8n-automation-expert/SKILL.md +89 -0
  96. package/skills/nextjs-app-router-expert/SKILL.md +148 -0
  97. package/skills/openapi-swagger-codegen-expert/SKILL.md +67 -0
  98. package/skills/payment-gateway-expert/SKILL.md +85 -1
  99. package/skills/pdf-document-generation-expert/SKILL.md +91 -0
  100. package/skills/performance-web-vitals/SKILL.md +7 -1
  101. package/skills/post-quantum-crypto-migrator/SKILL.md +57 -57
  102. package/skills/prd-architect/SKILL.md +7 -1
  103. package/skills/proactive-background-watcher/SKILL.md +67 -61
  104. package/skills/production-ready-hardener/SKILL.md +461 -455
  105. package/skills/project-context-mapper/SKILL.md +84 -78
  106. package/skills/pwa-offline-first-expert/SKILL.md +185 -0
  107. package/skills/python-programming-expert/SKILL.md +407 -401
  108. package/skills/rate-limit-abuse-prevention/SKILL.md +376 -370
  109. package/skills/realtime-collaboration-expert/SKILL.md +55 -1
  110. package/skills/rich-text-editor-expert/SKILL.md +177 -0
  111. package/skills/rust-programming-expert/SKILL.md +7 -1
  112. package/skills/saas-billing/SKILL.md +7 -1
  113. package/skills/saas-multi-tenant/SKILL.md +7 -1
  114. package/skills/saas-mvp-launcher/SKILL.md +20 -1
  115. package/skills/saas-transformer/SKILL.md +499 -488
  116. package/skills/scalability-clean-code/SKILL.md +7 -1
  117. package/skills/search-engine-expert/SKILL.md +89 -0
  118. package/skills/secure-fuzz-testing/SKILL.md +7 -1
  119. package/skills/self-evolving-memory-graph/SKILL.md +90 -74
  120. package/skills/self-healing-cloud-orchestrator/SKILL.md +57 -57
  121. package/skills/senior-frontend/SKILL.md +141 -161
  122. package/skills/seo/SKILL.md +41 -17
  123. package/skills/session-context-loader/SKILL.md +82 -76
  124. package/skills/session-handoff-resume/SKILL.md +7 -1
  125. package/skills/{skill_baru → skill-baru}/SKILL.md +8 -2
  126. package/skills/solidjs-expert/SKILL.md +80 -0
  127. package/skills/spa-orchestrator/SKILL.md +20 -1
  128. package/skills/sse-websocket-streaming-expert/SKILL.md +93 -0
  129. package/skills/state-management-expert/SKILL.md +7 -1
  130. package/skills/supabase-migration/SKILL.md +47 -1
  131. package/skills/supabase-security-expert/SKILL.md +7 -1
  132. package/skills/svelte-sveltekit-expert/SKILL.md +91 -0
  133. package/skills/svg-animation-motion-expert/SKILL.md +115 -0
  134. package/skills/tailwind-expert/SKILL.md +88 -136
  135. package/skills/tanstack-query-expert/SKILL.md +7 -1
  136. package/skills/tauri-expert/SKILL.md +7 -1
  137. package/skills/token-saver/SKILL.md +1 -1
  138. package/skills/typescript-expert/SKILL.md +12 -6
  139. package/skills/ui-components-expert/SKILL.md +165 -279
  140. package/skills/ui-ux-pro-max/SKILL.md +23 -3
  141. package/skills/vector-db-rag-expert/SKILL.md +175 -19
  142. package/skills/vibe-code-gardener/SKILL.md +1 -1
  143. package/skills/visual-qa-vision-agent/SKILL.md +70 -64
  144. package/skills/voice-ai-realtime-agent/SKILL.md +202 -0
  145. package/skills/vue-frontend-expert/SKILL.md +131 -125
  146. package/skills/wasm-edge-computing-expert/SKILL.md +97 -0
  147. package/skills/web-3d-graphics-expert/SKILL.md +136 -130
  148. package/skills/web-game-engine-expert/SKILL.md +101 -95
  149. package/skills/web-scraper/SKILL.md +157 -207
  150. package/skills/website-design-cloner/SKILL.md +179 -173
  151. package/skills/webxr-ar-vr-expert/SKILL.md +122 -116
  152. package/skills/wordpress-headless-expert/SKILL.md +144 -0
  153. package/skills/zero-to-prod-orchestrator/SKILL.md +52 -27
  154. package/skills/zero-trust-secret-vault/SKILL.md +87 -39
  155. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  156. package/.github/workflows/publish.yml +0 -20
  157. package/CONTRIBUTING.md +0 -199
  158. package/SECURITY.md +0 -21
  159. package/banner.png +0 -0
  160. package/skills/autonomous-swarm-director/SKILL.md +0 -69
  161. package/skills/hyper-context-synthesizer/SKILL.md +0 -55
  162. package/skills/llm-cost-arbitrage-router/SKILL.md +0 -59
  163. package/skills/senior-fullstack/SKILL.md +0 -167
  164. package/skills/senior-fullstack/references/architecture_patterns.md +0 -160
  165. package/skills/senior-fullstack/references/development_workflows.md +0 -222
  166. package/skills/senior-fullstack/references/tech_stack_guide.md +0 -190
  167. package/skills/senior-fullstack/scripts/code_quality_analyzer.py +0 -114
  168. package/skills/senior-fullstack/scripts/fullstack_scaffolder.py +0 -114
  169. package/skills/senior-fullstack/scripts/project_scaffolder.py +0 -114
  170. package/skills/seo-aeo-landing-page-writer/SKILL.md +0 -97
  171. package/skills/seo-geo/SKILL.md +0 -188
  172. package/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-310.pyc +0 -0
  173. package/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-312.pyc +0 -0
  174. package/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-310.pyc +0 -0
  175. package/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-312.pyc +0 -0
  176. package/skills/ui_ux_expert/SKILL.md +0 -125
  177. package/vibes-swarm-demo.gif +0 -0
@@ -1,371 +1,377 @@
1
- ---
2
- name: rate-limit-abuse-prevention
3
- description: "Expert guide for API rate limiting, bot protection, DDoS mitigation, brute-force prevention, and abuse detection / Panduan ahli untuk rate limiting API, perlindungan bot, mitigasi DDoS, pencegahan brute-force, dan deteksi penyalahgunaan."
1
+ ---
2
+ name: rate-limit-abuse-prevention
3
+ description: "Expert guide for API rate limiting, bot protection, DDoS mitigation, brute-force prevention, and abuse detection / Panduan ahli untuk rate limiting API, perlindungan bot, mitigasi DDoS, pencegahan brute-force, dan deteksi penyalahgunaan."
4
4
  author: "Roedy Rustam"
5
- ---
6
-
7
- # Rate Limit & Abuse Prevention (2026 Edition)
8
-
9
- [English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
10
-
11
- ---
12
-
13
- <a name="english"></a>
14
- ## English
15
-
16
- ### Description
17
- Production-grade guide for protecting APIs and web applications from abuse, overuse, and attacks. Covers **rate limiting algorithms** (Token Bucket, Sliding Window), **Upstash Ratelimit**, **bot protection** (Cloudflare Turnstile, hCaptcha), **DDoS mitigation** at edge, **brute-force login prevention**, **API key management & usage quotas**, and **response headers** (X-RateLimit, Retry-After).
18
-
19
- ### Trigger Conditions
20
- Activate this skill when:
21
- - Implementing API rate limiting for public or authenticated endpoints.
22
- - Adding bot protection (CAPTCHA) to forms (login, signup, contact).
23
- - Setting up DDoS protection at the edge (Cloudflare, Vercel).
24
- - Preventing brute-force attacks on authentication endpoints.
25
- - Implementing API key issuance and usage quotas for SaaS.
26
- - Building tiered rate limits based on subscription plans.
27
-
28
- ---
29
-
30
- ### Rate Limiting Algorithm Comparison
31
-
32
- | Algorithm | Behavior | Best For | Burst Handling |
33
- |---|---|---|---|
34
- | **Fixed Window** | Resets counter at interval boundary | Simple endpoints | Allows double burst at window edge |
35
- | **Sliding Window** | Rolling window, smooth distribution | API endpoints | Smooth, no edge burst |
36
- | **Token Bucket** | Tokens refill at fixed rate | High-throughput APIs | Allows controlled bursts |
37
- | **Leaky Bucket** | Processes at fixed rate, queues excess | Stream processing | No bursts, constant rate |
38
-
39
- **Recommendation**: Use **Sliding Window** for most API endpoints. Use **Token Bucket** for endpoints that should allow burst traffic.
40
-
41
- ---
42
-
43
- ### 1. Upstash Ratelimit (Edge-Compatible)
44
-
45
- ```typescript
46
- // lib/ratelimit.ts
47
- import { Ratelimit } from '@upstash/ratelimit';
48
- import { Redis } from '@upstash/redis';
49
-
50
- const redis = Redis.fromEnv();
51
-
52
- // Different rate limiters for different tiers
53
- export const rateLimiters = {
54
- /** Public API: 10 requests per 10 seconds */
55
- public: new Ratelimit({
56
- redis,
57
- limiter: Ratelimit.slidingWindow(10, '10s'),
58
- prefix: 'rl:public',
59
- analytics: true,
60
- }),
61
-
62
- /** Authenticated API: 100 requests per minute */
63
- authenticated: new Ratelimit({
64
- redis,
65
- limiter: Ratelimit.slidingWindow(100, '1m'),
66
- prefix: 'rl:auth',
67
- analytics: true,
68
- }),
69
-
70
- /** Pro tier: 1000 requests per minute */
71
- pro: new Ratelimit({
72
- redis,
73
- limiter: Ratelimit.slidingWindow(1000, '1m'),
74
- prefix: 'rl:pro',
75
- analytics: true,
76
- }),
77
-
78
- /** Login endpoint: 5 attempts per 15 minutes */
79
- login: new Ratelimit({
80
- redis,
81
- limiter: Ratelimit.slidingWindow(5, '15m'),
82
- prefix: 'rl:login',
83
- }),
84
-
85
- /** Password reset: 3 per hour */
86
- passwordReset: new Ratelimit({
87
- redis,
88
- limiter: Ratelimit.slidingWindow(3, '1h'),
89
- prefix: 'rl:pwreset',
90
- }),
91
- };
92
- ```
93
-
94
- ```typescript
95
- // middleware.ts (Next.js)
96
- import { NextResponse, type NextRequest } from 'next/server';
97
- import { rateLimiters } from '@/lib/ratelimit';
98
-
99
- export async function middleware(request: NextRequest) {
100
- if (request.nextUrl.pathname.startsWith('/api/')) {
101
- const ip = request.headers.get('x-forwarded-for') ?? request.ip ?? '127.0.0.1';
102
- const identifier = ip;
103
-
104
- const limiter = request.nextUrl.pathname.startsWith('/api/auth/login')
105
- ? rateLimiters.login
106
- : rateLimiters.public;
107
-
108
- const { success, limit, remaining, reset } = await limiter.limit(identifier);
109
-
110
- if (!success) {
111
- return NextResponse.json(
112
- { error: 'Too many requests', retryAfter: Math.ceil((reset - Date.now()) / 1000) },
113
- {
114
- status: 429,
115
- headers: {
116
- 'X-RateLimit-Limit': limit.toString(),
117
- 'X-RateLimit-Remaining': '0',
118
- 'X-RateLimit-Reset': reset.toString(),
119
- 'Retry-After': Math.ceil((reset - Date.now()) / 1000).toString(),
120
- },
121
- },
122
- );
123
- }
124
-
125
- const response = NextResponse.next();
126
- response.headers.set('X-RateLimit-Limit', limit.toString());
127
- response.headers.set('X-RateLimit-Remaining', remaining.toString());
128
- response.headers.set('X-RateLimit-Reset', reset.toString());
129
- return response;
130
- }
131
- }
132
-
133
- export const config = { matcher: '/api/:path*' };
134
- ```
135
-
136
- ---
137
-
138
- ### 2. Tiered Rate Limits for SaaS
139
-
140
- ```typescript
141
- // lib/tiered-ratelimit.ts
142
- import { Ratelimit } from '@upstash/ratelimit';
143
-
144
- type PlanTier = 'free' | 'pro' | 'enterprise';
145
-
146
- const PLAN_LIMITS: Record<PlanTier, { requests: number; window: string }> = {
147
- free: { requests: 100, window: '1h' },
148
- pro: { requests: 5000, window: '1h' },
149
- enterprise: { requests: 50000, window: '1h' },
150
- };
151
-
152
- export function getRateLimiterForPlan(plan: PlanTier): Ratelimit {
153
- const config = PLAN_LIMITS[plan];
154
- return new Ratelimit({
155
- redis,
156
- limiter: Ratelimit.slidingWindow(config.requests, config.window as any),
157
- prefix: `rl:api:${plan}`,
158
- });
159
- }
160
-
161
- // Usage in API route
162
- export async function GET(request: Request) {
163
- const user = await getAuthUser(request);
164
- const limiter = getRateLimiterForPlan(user.plan);
165
- const { success, remaining } = await limiter.limit(user.id);
166
-
167
- if (!success) {
168
- return Response.json({
169
- error: 'Rate limit exceeded',
170
- upgrade: user.plan !== 'enterprise' ? 'https://app.example.com/pricing' : undefined,
171
- }, { status: 429 });
172
- }
173
-
174
- // ...handle request
175
- }
176
- ```
177
-
178
- ---
179
-
180
- ### 3. Bot Protection (Cloudflare Turnstile)
181
-
182
- ```tsx
183
- // components/turnstile.tsx
184
- 'use client';
185
-
186
- import { Turnstile } from '@marsidev/react-turnstile';
187
-
188
- interface TurnstileWidgetProps {
189
- onVerify: (token: string) => void;
190
- }
191
-
192
- export function TurnstileWidget({ onVerify }: TurnstileWidgetProps) {
193
- return (
194
- <Turnstile
195
- siteKey={process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY!}
196
- onSuccess={onVerify}
197
- options={{ theme: 'auto', size: 'flexible' }}
198
- />
199
- );
200
- }
201
- ```
202
-
203
- ```typescript
204
- // Server-side verification
205
- export async function verifyTurnstileToken(token: string, ip?: string): Promise<boolean> {
206
- const response = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
207
- method: 'POST',
208
- headers: { 'Content-Type': 'application/json' },
209
- body: JSON.stringify({
210
- secret: process.env.TURNSTILE_SECRET_KEY,
211
- response: token,
212
- remoteip: ip,
213
- }),
214
- });
215
-
216
- const data = await response.json();
217
- return data.success === true;
218
- }
219
- ```
220
-
221
- ---
222
-
223
- ### 4. Brute-Force Login Prevention
224
-
225
- ```typescript
226
- // lib/login-protection.ts
227
- const MAX_ATTEMPTS = 5;
228
- const LOCKOUT_DURATION = 15 * 60; // 15 minutes in seconds
229
- const PROGRESSIVE_DELAYS = [0, 1000, 2000, 4000, 8000]; // Progressive delay per attempt
230
-
231
- export async function checkLoginAttempt(email: string, ip: string): Promise<{
232
- allowed: boolean;
233
- remainingAttempts: number;
234
- lockoutEndsAt?: Date;
235
- }> {
236
- const key = `login-attempts:${email}:${ip}`;
237
- const attempts = await redis.incr(key);
238
-
239
- if (attempts === 1) {
240
- await redis.expire(key, LOCKOUT_DURATION);
241
- }
242
-
243
- if (attempts > MAX_ATTEMPTS) {
244
- const ttl = await redis.ttl(key);
245
- return {
246
- allowed: false,
247
- remainingAttempts: 0,
248
- lockoutEndsAt: new Date(Date.now() + ttl * 1000),
249
- };
250
- }
251
-
252
- // Progressive delay
253
- const delay = PROGRESSIVE_DELAYS[Math.min(attempts - 1, PROGRESSIVE_DELAYS.length - 1)];
254
- if (delay > 0) await new Promise(r => setTimeout(r, delay));
255
-
256
- return { allowed: true, remainingAttempts: MAX_ATTEMPTS - attempts };
257
- }
258
-
259
- export async function clearLoginAttempts(email: string, ip: string): Promise<void> {
260
- await redis.del(`login-attempts:${email}:${ip}`);
261
- }
262
- ```
263
-
264
- ---
265
-
266
- ### 5. API Key Management
267
-
268
- ```typescript
269
- // lib/api-keys.ts
270
- import { nanoid } from 'nanoid';
271
- import { hash, verify } from '@node-rs/argon2';
272
-
273
- export async function createApiKey(userId: string, name: string) {
274
- const rawKey = `sk_live_${nanoid(32)}`;
275
- const prefix = rawKey.slice(0, 12); // Show prefix for identification
276
- const hashedKey = await hash(rawKey);
277
-
278
- await db.insert(apiKeys).values({
279
- userId,
280
- name,
281
- prefix,
282
- hashedKey,
283
- lastUsedAt: null,
284
- });
285
-
286
- // Return raw key only once — cannot be retrieved later
287
- return { key: rawKey, prefix };
288
- }
289
-
290
- export async function validateApiKey(rawKey: string) {
291
- const prefix = rawKey.slice(0, 12);
292
- const candidates = await db.query.apiKeys.findMany({
293
- where: and(
294
- eq(apiKeys.prefix, prefix),
295
- eq(apiKeys.isRevoked, false),
296
- ),
297
- });
298
-
299
- for (const candidate of candidates) {
300
- if (await verify(candidate.hashedKey, rawKey)) {
301
- // Update last used timestamp
302
- await db.update(apiKeys)
303
- .set({ lastUsedAt: new Date() })
304
- .where(eq(apiKeys.id, candidate.id));
305
- return candidate;
306
- }
307
- }
308
-
309
- return null;
310
- }
311
- ```
312
-
313
- ---
314
-
315
- ### Response Headers Specification
316
-
317
- | Header | Purpose | Example |
318
- |---|---|---|
319
- | `X-RateLimit-Limit` | Max requests allowed | `100` |
320
- | `X-RateLimit-Remaining` | Remaining requests in window | `87` |
321
- | `X-RateLimit-Reset` | Unix timestamp when window resets | `1723382400` |
322
- | `Retry-After` | Seconds until retry is allowed (on 429) | `60` |
323
-
324
- ---
325
-
326
- ### Common Pitfalls to Avoid
327
-
328
- | Anti-Pattern | Problem | Correct Approach |
329
- |---|---|---|
330
- | Rate limiting by IP only | Shared IPs affect multiple users | Combine IP + user ID + API key |
331
- | No rate limit on auth endpoints | Brute-force attacks | Strict limits: 5 attempts / 15 min |
332
- | Fixed window rate limiting | 2x burst at window boundary | Use sliding window algorithm |
333
- | No 429 response headers | Clients can't implement backoff | Always include Retry-After header |
334
- | CAPTCHA on every request | Terrible UX, accessibility issues | Only trigger after suspicious behavior |
335
- | Rate limit in application only | Still hits your server | Add edge-level protection (Cloudflare WAF) |
336
-
337
- ---
338
-
339
- ### Integration with Other Skills
340
-
341
- - `authentication-identity-expert` — Brute-force prevention on login/signup endpoints
342
- - `api-design-expert` Rate limit headers, API key patterns
343
- - `js-backend-expert` — Express/Fastify/Hono middleware integration
344
- - `saas-billing` — Tiered rate limits per subscription plan
345
- - `production-ready-hardener` — Pre-launch security audit
346
- - `cloud-hosting-expert` — Edge-level WAF and DDoS protection
347
-
348
- ---
349
-
350
- <a name="bahasa-indonesia"></a>
351
- ## Bahasa Indonesia
352
-
353
- ### Deskripsi
354
- Panduan tingkat produksi untuk melindungi API dan aplikasi web dari penyalahgunaan, penggunaan berlebihan, dan serangan. Mencakup **algoritma rate limiting** (Token Bucket, Sliding Window), **Upstash Ratelimit**, **perlindungan bot** (Cloudflare Turnstile, hCaptcha), **mitigasi DDoS** di edge, **pencegahan brute-force login**, **manajemen API key & kuota penggunaan**, dan **header respons** (X-RateLimit, Retry-After).
355
-
356
- ### Kondisi Pemicu
357
- Aktifkan skill ini ketika:
358
- - Mengimplementasikan rate limiting API untuk endpoint publik atau terautentikasi.
359
- - Menambahkan perlindungan bot (CAPTCHA) ke formulir.
360
- - Menyiapkan perlindungan DDoS di edge.
361
- - Mencegah serangan brute-force pada endpoint autentikasi.
362
- - Mengimplementasikan penerbitan API key dan kuota penggunaan untuk SaaS.
363
-
364
- ### Integrasi dengan Skill Lain
365
-
366
- - `authentication-identity-expert` Pencegahan brute-force pada endpoint login/signup
367
- - `api-design-expert` Header rate limit, pola API key
368
- - `js-backend-expert` Integrasi middleware Express/Fastify/Hono
369
- - `saas-billing` — Rate limit bertingkat per paket langganan
370
- - `production-ready-hardener` Audit keamanan pra-peluncuran
371
- - `cloud-hosting-expert` — Perlindungan WAF dan DDoS di edge
5
+ ---
6
+
7
+ # Rate Limit & Abuse Prevention (2026 Edition)
8
+
9
+ [English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
10
+
11
+ ---
12
+
13
+ <a name="english"></a>
14
+ ## English
15
+
16
+ ### Orchestration & Integration
17
+ Connects and orchestrates with relevant domain skills like `brainstorming`, `zero-to-prod-orchestrator`, and `project-context-mapper` to ensure cohesive execution.
18
+
19
+ ### Description
20
+ Production-grade guide for protecting APIs and web applications from abuse, overuse, and attacks. Covers **rate limiting algorithms** (Token Bucket, Sliding Window), **Upstash Ratelimit**, **bot protection** (Cloudflare Turnstile, hCaptcha), **DDoS mitigation** at edge, **brute-force login prevention**, **API key management & usage quotas**, and **response headers** (X-RateLimit, Retry-After).
21
+
22
+ ### Trigger Conditions
23
+ Activate this skill when:
24
+ - Implementing API rate limiting for public or authenticated endpoints.
25
+ - Adding bot protection (CAPTCHA) to forms (login, signup, contact).
26
+ - Setting up DDoS protection at the edge (Cloudflare, Vercel).
27
+ - Preventing brute-force attacks on authentication endpoints.
28
+ - Implementing API key issuance and usage quotas for SaaS.
29
+ - Building tiered rate limits based on subscription plans.
30
+
31
+ ---
32
+
33
+ ### Rate Limiting Algorithm Comparison
34
+
35
+ | Algorithm | Behavior | Best For | Burst Handling |
36
+ |---|---|---|---|
37
+ | **Fixed Window** | Resets counter at interval boundary | Simple endpoints | Allows double burst at window edge |
38
+ | **Sliding Window** | Rolling window, smooth distribution | API endpoints | Smooth, no edge burst |
39
+ | **Token Bucket** | Tokens refill at fixed rate | High-throughput APIs | Allows controlled bursts |
40
+ | **Leaky Bucket** | Processes at fixed rate, queues excess | Stream processing | No bursts, constant rate |
41
+
42
+ **Recommendation**: Use **Sliding Window** for most API endpoints. Use **Token Bucket** for endpoints that should allow burst traffic.
43
+
44
+ ---
45
+
46
+ ### 1. Upstash Ratelimit (Edge-Compatible)
47
+
48
+ ```typescript
49
+ // lib/ratelimit.ts
50
+ import { Ratelimit } from '@upstash/ratelimit';
51
+ import { Redis } from '@upstash/redis';
52
+
53
+ const redis = Redis.fromEnv();
54
+
55
+ // Different rate limiters for different tiers
56
+ export const rateLimiters = {
57
+ /** Public API: 10 requests per 10 seconds */
58
+ public: new Ratelimit({
59
+ redis,
60
+ limiter: Ratelimit.slidingWindow(10, '10s'),
61
+ prefix: 'rl:public',
62
+ analytics: true,
63
+ }),
64
+
65
+ /** Authenticated API: 100 requests per minute */
66
+ authenticated: new Ratelimit({
67
+ redis,
68
+ limiter: Ratelimit.slidingWindow(100, '1m'),
69
+ prefix: 'rl:auth',
70
+ analytics: true,
71
+ }),
72
+
73
+ /** Pro tier: 1000 requests per minute */
74
+ pro: new Ratelimit({
75
+ redis,
76
+ limiter: Ratelimit.slidingWindow(1000, '1m'),
77
+ prefix: 'rl:pro',
78
+ analytics: true,
79
+ }),
80
+
81
+ /** Login endpoint: 5 attempts per 15 minutes */
82
+ login: new Ratelimit({
83
+ redis,
84
+ limiter: Ratelimit.slidingWindow(5, '15m'),
85
+ prefix: 'rl:login',
86
+ }),
87
+
88
+ /** Password reset: 3 per hour */
89
+ passwordReset: new Ratelimit({
90
+ redis,
91
+ limiter: Ratelimit.slidingWindow(3, '1h'),
92
+ prefix: 'rl:pwreset',
93
+ }),
94
+ };
95
+ ```
96
+
97
+ ```typescript
98
+ // middleware.ts (Next.js)
99
+ import { NextResponse, type NextRequest } from 'next/server';
100
+ import { rateLimiters } from '@/lib/ratelimit';
101
+
102
+ export async function middleware(request: NextRequest) {
103
+ if (request.nextUrl.pathname.startsWith('/api/')) {
104
+ const ip = request.headers.get('x-forwarded-for') ?? request.ip ?? '127.0.0.1';
105
+ const identifier = ip;
106
+
107
+ const limiter = request.nextUrl.pathname.startsWith('/api/auth/login')
108
+ ? rateLimiters.login
109
+ : rateLimiters.public;
110
+
111
+ const { success, limit, remaining, reset } = await limiter.limit(identifier);
112
+
113
+ if (!success) {
114
+ return NextResponse.json(
115
+ { error: 'Too many requests', retryAfter: Math.ceil((reset - Date.now()) / 1000) },
116
+ {
117
+ status: 429,
118
+ headers: {
119
+ 'X-RateLimit-Limit': limit.toString(),
120
+ 'X-RateLimit-Remaining': '0',
121
+ 'X-RateLimit-Reset': reset.toString(),
122
+ 'Retry-After': Math.ceil((reset - Date.now()) / 1000).toString(),
123
+ },
124
+ },
125
+ );
126
+ }
127
+
128
+ const response = NextResponse.next();
129
+ response.headers.set('X-RateLimit-Limit', limit.toString());
130
+ response.headers.set('X-RateLimit-Remaining', remaining.toString());
131
+ response.headers.set('X-RateLimit-Reset', reset.toString());
132
+ return response;
133
+ }
134
+ }
135
+
136
+ export const config = { matcher: '/api/:path*' };
137
+ ```
138
+
139
+ ---
140
+
141
+ ### 2. Tiered Rate Limits for SaaS
142
+
143
+ ```typescript
144
+ // lib/tiered-ratelimit.ts
145
+ import { Ratelimit } from '@upstash/ratelimit';
146
+
147
+ type PlanTier = 'free' | 'pro' | 'enterprise';
148
+
149
+ const PLAN_LIMITS: Record<PlanTier, { requests: number; window: string }> = {
150
+ free: { requests: 100, window: '1h' },
151
+ pro: { requests: 5000, window: '1h' },
152
+ enterprise: { requests: 50000, window: '1h' },
153
+ };
154
+
155
+ export function getRateLimiterForPlan(plan: PlanTier): Ratelimit {
156
+ const config = PLAN_LIMITS[plan];
157
+ return new Ratelimit({
158
+ redis,
159
+ limiter: Ratelimit.slidingWindow(config.requests, config.window as any),
160
+ prefix: `rl:api:${plan}`,
161
+ });
162
+ }
163
+
164
+ // Usage in API route
165
+ export async function GET(request: Request) {
166
+ const user = await getAuthUser(request);
167
+ const limiter = getRateLimiterForPlan(user.plan);
168
+ const { success, remaining } = await limiter.limit(user.id);
169
+
170
+ if (!success) {
171
+ return Response.json({
172
+ error: 'Rate limit exceeded',
173
+ upgrade: user.plan !== 'enterprise' ? 'https://app.example.com/pricing' : undefined,
174
+ }, { status: 429 });
175
+ }
176
+
177
+ // ...handle request
178
+ }
179
+ ```
180
+
181
+ ---
182
+
183
+ ### 3. Bot Protection (Cloudflare Turnstile)
184
+
185
+ ```tsx
186
+ // components/turnstile.tsx
187
+ 'use client';
188
+
189
+ import { Turnstile } from '@marsidev/react-turnstile';
190
+
191
+ interface TurnstileWidgetProps {
192
+ onVerify: (token: string) => void;
193
+ }
194
+
195
+ export function TurnstileWidget({ onVerify }: TurnstileWidgetProps) {
196
+ return (
197
+ <Turnstile
198
+ siteKey={process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY!}
199
+ onSuccess={onVerify}
200
+ options={{ theme: 'auto', size: 'flexible' }}
201
+ />
202
+ );
203
+ }
204
+ ```
205
+
206
+ ```typescript
207
+ // Server-side verification
208
+ export async function verifyTurnstileToken(token: string, ip?: string): Promise<boolean> {
209
+ const response = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
210
+ method: 'POST',
211
+ headers: { 'Content-Type': 'application/json' },
212
+ body: JSON.stringify({
213
+ secret: process.env.TURNSTILE_SECRET_KEY,
214
+ response: token,
215
+ remoteip: ip,
216
+ }),
217
+ });
218
+
219
+ const data = await response.json();
220
+ return data.success === true;
221
+ }
222
+ ```
223
+
224
+ ---
225
+
226
+ ### 4. Brute-Force Login Prevention
227
+
228
+ ```typescript
229
+ // lib/login-protection.ts
230
+ const MAX_ATTEMPTS = 5;
231
+ const LOCKOUT_DURATION = 15 * 60; // 15 minutes in seconds
232
+ const PROGRESSIVE_DELAYS = [0, 1000, 2000, 4000, 8000]; // Progressive delay per attempt
233
+
234
+ export async function checkLoginAttempt(email: string, ip: string): Promise<{
235
+ allowed: boolean;
236
+ remainingAttempts: number;
237
+ lockoutEndsAt?: Date;
238
+ }> {
239
+ const key = `login-attempts:${email}:${ip}`;
240
+ const attempts = await redis.incr(key);
241
+
242
+ if (attempts === 1) {
243
+ await redis.expire(key, LOCKOUT_DURATION);
244
+ }
245
+
246
+ if (attempts > MAX_ATTEMPTS) {
247
+ const ttl = await redis.ttl(key);
248
+ return {
249
+ allowed: false,
250
+ remainingAttempts: 0,
251
+ lockoutEndsAt: new Date(Date.now() + ttl * 1000),
252
+ };
253
+ }
254
+
255
+ // Progressive delay
256
+ const delay = PROGRESSIVE_DELAYS[Math.min(attempts - 1, PROGRESSIVE_DELAYS.length - 1)];
257
+ if (delay > 0) await new Promise(r => setTimeout(r, delay));
258
+
259
+ return { allowed: true, remainingAttempts: MAX_ATTEMPTS - attempts };
260
+ }
261
+
262
+ export async function clearLoginAttempts(email: string, ip: string): Promise<void> {
263
+ await redis.del(`login-attempts:${email}:${ip}`);
264
+ }
265
+ ```
266
+
267
+ ---
268
+
269
+ ### 5. API Key Management
270
+
271
+ ```typescript
272
+ // lib/api-keys.ts
273
+ import { nanoid } from 'nanoid';
274
+ import { hash, verify } from '@node-rs/argon2';
275
+
276
+ export async function createApiKey(userId: string, name: string) {
277
+ const rawKey = `sk_live_${nanoid(32)}`;
278
+ const prefix = rawKey.slice(0, 12); // Show prefix for identification
279
+ const hashedKey = await hash(rawKey);
280
+
281
+ await db.insert(apiKeys).values({
282
+ userId,
283
+ name,
284
+ prefix,
285
+ hashedKey,
286
+ lastUsedAt: null,
287
+ });
288
+
289
+ // Return raw key only once — cannot be retrieved later
290
+ return { key: rawKey, prefix };
291
+ }
292
+
293
+ export async function validateApiKey(rawKey: string) {
294
+ const prefix = rawKey.slice(0, 12);
295
+ const candidates = await db.query.apiKeys.findMany({
296
+ where: and(
297
+ eq(apiKeys.prefix, prefix),
298
+ eq(apiKeys.isRevoked, false),
299
+ ),
300
+ });
301
+
302
+ for (const candidate of candidates) {
303
+ if (await verify(candidate.hashedKey, rawKey)) {
304
+ // Update last used timestamp
305
+ await db.update(apiKeys)
306
+ .set({ lastUsedAt: new Date() })
307
+ .where(eq(apiKeys.id, candidate.id));
308
+ return candidate;
309
+ }
310
+ }
311
+
312
+ return null;
313
+ }
314
+ ```
315
+
316
+ ---
317
+
318
+ ### Response Headers Specification
319
+
320
+ | Header | Purpose | Example |
321
+ |---|---|---|
322
+ | `X-RateLimit-Limit` | Max requests allowed | `100` |
323
+ | `X-RateLimit-Remaining` | Remaining requests in window | `87` |
324
+ | `X-RateLimit-Reset` | Unix timestamp when window resets | `1723382400` |
325
+ | `Retry-After` | Seconds until retry is allowed (on 429) | `60` |
326
+
327
+ ---
328
+
329
+ ### Common Pitfalls to Avoid
330
+
331
+ | Anti-Pattern | Problem | Correct Approach |
332
+ |---|---|---|
333
+ | Rate limiting by IP only | Shared IPs affect multiple users | Combine IP + user ID + API key |
334
+ | No rate limit on auth endpoints | Brute-force attacks | Strict limits: 5 attempts / 15 min |
335
+ | Fixed window rate limiting | 2x burst at window boundary | Use sliding window algorithm |
336
+ | No 429 response headers | Clients can't implement backoff | Always include Retry-After header |
337
+ | CAPTCHA on every request | Terrible UX, accessibility issues | Only trigger after suspicious behavior |
338
+ | Rate limit in application only | Still hits your server | Add edge-level protection (Cloudflare WAF) |
339
+
340
+ ---
341
+
342
+ ### Integration with Other Skills
343
+
344
+ - `authentication-identity-expert` — Brute-force prevention on login/signup endpoints
345
+ - `api-design-expert` — Rate limit headers, API key patterns
346
+ - `js-backend-expert` — Express/Fastify/Hono middleware integration
347
+ - `saas-billing` — Tiered rate limits per subscription plan
348
+ - `production-ready-hardener` — Pre-launch security audit
349
+ - `cloud-hosting-expert` — Edge-level WAF and DDoS protection
350
+
351
+ ---
352
+
353
+ <a name="bahasa-indonesia"></a>
354
+ ## Bahasa Indonesia
355
+
356
+ ### Integrasi Orkestrasi
357
+ Terhubung dan mengorkestrasi skill domain yang relevan seperti `brainstorming`, `zero-to-prod-orchestrator`, dan `project-context-mapper` untuk memastikan eksekusi yang kohesif.
358
+
359
+ ### Deskripsi
360
+ Panduan tingkat produksi untuk melindungi API dan aplikasi web dari penyalahgunaan, penggunaan berlebihan, dan serangan. Mencakup **algoritma rate limiting** (Token Bucket, Sliding Window), **Upstash Ratelimit**, **perlindungan bot** (Cloudflare Turnstile, hCaptcha), **mitigasi DDoS** di edge, **pencegahan brute-force login**, **manajemen API key & kuota penggunaan**, dan **header respons** (X-RateLimit, Retry-After).
361
+
362
+ ### Kondisi Pemicu
363
+ Aktifkan skill ini ketika:
364
+ - Mengimplementasikan rate limiting API untuk endpoint publik atau terautentikasi.
365
+ - Menambahkan perlindungan bot (CAPTCHA) ke formulir.
366
+ - Menyiapkan perlindungan DDoS di edge.
367
+ - Mencegah serangan brute-force pada endpoint autentikasi.
368
+ - Mengimplementasikan penerbitan API key dan kuota penggunaan untuk SaaS.
369
+
370
+ ### Integrasi dengan Skill Lain
371
+
372
+ - `authentication-identity-expert` — Pencegahan brute-force pada endpoint login/signup
373
+ - `api-design-expert` — Header rate limit, pola API key
374
+ - `js-backend-expert` — Integrasi middleware Express/Fastify/Hono
375
+ - `saas-billing` — Rate limit bertingkat per paket langganan
376
+ - `production-ready-hardener` — Audit keamanan pra-peluncuran
377
+ - `cloud-hosting-expert` — Perlindungan WAF dan DDoS di edge