vibes-plug 1.0.0 → 2.5.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.
- package/.github/workflows/publish.yml +20 -0
- package/AGENTS.md +66 -0
- package/BLUEPRINT.md +152 -60
- package/CHANGELOG.md +50 -0
- package/README.md +346 -194
- package/package.json +25 -25
- package/plugin.json +1 -1
- package/skills/ai-cost-token-optimizer/SKILL.md +52 -0
- package/skills/ai-llm-integration-expert/SKILL.md +180 -162
- package/skills/api-design-expert/SKILL.md +314 -310
- package/skills/app-analyzer-optimizer/SKILL.md +193 -189
- package/skills/apple-ecosystem-expert/SKILL.md +142 -0
- package/skills/async-queue-temporal-expert/SKILL.md +54 -0
- package/skills/authentication-identity-expert/SKILL.md +251 -20
- package/skills/auto-doc-updater/SKILL.md +214 -204
- package/skills/autonomous-chaos-monkey/SKILL.md +63 -0
- package/skills/autonomous-red-teamer/SKILL.md +59 -0
- package/skills/autonomous-swarm-director/SKILL.md +69 -0
- package/skills/autonomous-tdd-debugger/SKILL.md +65 -0
- package/skills/bootstrap-to-modern/SKILL.md +90 -86
- package/skills/brainstorming/SKILL.md +373 -353
- package/skills/browser-automation-expert/SKILL.md +46 -0
- package/skills/ci-cd-devops-architect/SKILL.md +72 -45
- package/skills/cloud-hosting-expert/SKILL.md +244 -244
- package/skills/coderabbit/SKILL.md +192 -192
- package/skills/cron-scheduler-expert/SKILL.md +298 -0
- package/skills/data-telemetry-expert/SKILL.md +213 -213
- package/skills/database-orm-expert/SKILL.md +294 -294
- package/skills/dependency-upgrade-migrator/SKILL.md +295 -0
- package/skills/design-system-architect/SKILL.md +27 -10
- package/skills/doku-mcp-server/SKILL.md +251 -0
- package/skills/doku-payment-gateway/SKILL.md +227 -0
- package/skills/e2e-testing-expert/SKILL.md +315 -315
- package/skills/edge-serverless-db-expert/SKILL.md +43 -0
- package/skills/email-notification-expert/SKILL.md +362 -0
- package/skills/error-resilience-expert/SKILL.md +480 -0
- package/skills/event-driven-architect/SKILL.md +81 -81
- package/skills/feature-flag-analytics-expert/SKILL.md +46 -0
- package/skills/file-upload-media-expert/SKILL.md +431 -0
- package/skills/form-validation-expert/SKILL.md +401 -0
- package/skills/fullstack-expert/SKILL.md +202 -202
- package/skills/fullstack-expert/references/api_design_guide.md +466 -466
- package/skills/fullstack-expert/references/multi_language_backend.md +528 -528
- package/skills/fullstack-expert/scripts/api_contract_validator.py +253 -253
- package/skills/fullstack-expert/scripts/architecture_analyzer.py +326 -326
- package/skills/gemini-agent-booster/SKILL.md +135 -135
- package/skills/global-a11y-i18n-expert/SKILL.md +81 -81
- package/skills/glsl-shader-expert/SKILL.md +101 -0
- package/skills/go-programming-expert/SKILL.md +295 -295
- package/skills/graphql-apollo-expert/SKILL.md +108 -0
- package/skills/hig/SKILL.md +188 -188
- package/skills/hyper-context-synthesizer/SKILL.md +55 -0
- package/skills/js-backend-expert/SKILL.md +34 -9
- package/skills/legacy-code-translator/SKILL.md +65 -0
- package/skills/llm-cost-arbitrage-router/SKILL.md +59 -0
- package/skills/logging-error-tracking-expert/SKILL.md +338 -0
- package/skills/mcp-client-orchestrator/SKILL.md +70 -0
- package/skills/mcp-server-architect/SKILL.md +194 -194
- package/skills/micro-frontend-architect/SKILL.md +106 -0
- package/skills/mobile-expo-expert/SKILL.md +186 -186
- package/skills/mobile-push-notification-expert/SKILL.md +51 -0
- package/skills/monday-design-aesthetic/SKILL.md +67 -67
- package/skills/monorepo-architect/SKILL.md +227 -227
- package/skills/mpa-orchestrator/SKILL.md +101 -101
- package/skills/multi-agent-orchestration/SKILL.md +234 -234
- package/skills/multiple-entry-points/SKILL.md +55 -55
- package/skills/mvc-expert/SKILL.md +231 -231
- package/skills/payment-gateway-expert/SKILL.md +45 -45
- package/skills/performance-web-vitals/SKILL.md +332 -332
- package/skills/post-quantum-crypto-migrator/SKILL.md +57 -0
- package/skills/prd-architect/SKILL.md +201 -191
- package/skills/proactive-background-watcher/SKILL.md +62 -0
- package/skills/production-ready-hardener/PRODUCTION_READINESS_REPORT.md +67 -0
- package/skills/production-ready-hardener/SKILL.md +173 -186
- package/skills/production-ready-hardener/references/production_checklist.md +161 -161
- package/skills/production-ready-hardener/scripts/production_readiness_scanner.py +881 -875
- package/skills/project-context-mapper/SKILL.md +79 -0
- package/skills/python-programming-expert/SKILL.md +263 -132
- package/skills/rate-limit-abuse-prevention/SKILL.md +371 -0
- package/skills/realtime-collaboration-expert/SKILL.md +45 -45
- package/skills/rust-programming-expert/SKILL.md +235 -235
- package/skills/saas-billing/SKILL.md +377 -377
- package/skills/saas-multi-tenant/SKILL.md +251 -237
- package/skills/saas-mvp-launcher/SKILL.md +10 -0
- package/skills/saas-transformer/SKILL.md +187 -144
- package/skills/saas-transformer/references/billing_integration_guide.md +401 -401
- package/skills/saas-transformer/references/feature_gating_patterns.md +137 -137
- package/skills/saas-transformer/references/saas_transformation_checklist.md +121 -121
- package/skills/saas-transformer/scripts/saas_transformation_scanner.py +39 -29
- package/skills/scalability-clean-code/SKILL.md +229 -229
- package/skills/self-evolving-memory-graph/SKILL.md +75 -0
- package/skills/self-healing-cloud-orchestrator/SKILL.md +57 -0
- package/skills/senior-frontend/SKILL.md +161 -161
- package/skills/senior-fullstack/SKILL.md +167 -167
- package/skills/seo/SKILL.md +235 -225
- package/skills/seo-geo/SKILL.md +188 -188
- package/skills/session-context-loader/SKILL.md +77 -0
- package/skills/session-handoff-resume/SKILL.md +158 -158
- package/skills/skill_baru/SKILL.md +172 -147
- package/skills/spa-orchestrator/SKILL.md +288 -288
- package/skills/state-management-expert/SKILL.md +272 -272
- package/skills/supabase-security-expert/SKILL.md +243 -243
- package/skills/tailwind-expert/SKILL.md +188 -188
- package/skills/tanstack-query-expert/SKILL.md +199 -199
- package/skills/token-saver/SKILL.md +119 -111
- package/skills/typescript-expert/SKILL.md +324 -279
- package/skills/ui-components-expert/SKILL.md +263 -46
- package/skills/ui-ux-pro-max/SKILL.md +202 -201
- package/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-310.pyc +0 -0
- package/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-310.pyc +0 -0
- package/skills/ui_ux_expert/SKILL.md +17 -6
- package/skills/vector-db-rag-expert/SKILL.md +52 -0
- package/skills/vibe-code-gardener/SKILL.md +181 -173
- package/skills/visual-qa-vision-agent/SKILL.md +65 -0
- package/skills/vue-frontend-expert/SKILL.md +126 -0
- package/skills/web-3d-graphics-expert/SKILL.md +131 -0
- package/skills/web-game-engine-expert/SKILL.md +96 -0
- package/skills/web-scraper/SKILL.md +207 -205
- package/skills/website-design-cloner/SKILL.md +174 -0
- package/skills/webxr-ar-vr-expert/SKILL.md +117 -0
- package/skills/zero-to-prod-orchestrator/SKILL.md +206 -180
- package/skills/zero-trust-secret-vault/SKILL.md +40 -0
- package/vibes-swarm-demo.gif +0 -0
|
@@ -0,0 +1,371 @@
|
|
|
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
|
+
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
|
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: realtime-collaboration-expert
|
|
3
|
-
description: "Expert guide for building real-time collaboration features using WebSockets, WebRTC, CRDTs (Yjs, Automerge), and Liveblocks / Panduan ahli untuk fitur kolaborasi real-time."
|
|
4
|
-
author: "Antigravity"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Real-Time Collaboration Expert / Ahli Kolaborasi Real-Time
|
|
8
|
-
|
|
9
|
-
[English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
<a name="english"></a>
|
|
14
|
-
## English
|
|
15
|
-
|
|
16
|
-
### Description
|
|
17
|
-
Expert guide for implementing multiplayer, real-time collaboration features in web applications. Covers Conflict-free Replicated Data Types (CRDTs) like Yjs/Automerge, WebSockets, WebRTC, and Managed services like Liveblocks or Pusher.
|
|
18
|
-
|
|
19
|
-
### Instructions
|
|
20
|
-
- **CRDTs for State**: Use CRDTs (e.g., `yjs` or `automerge`) instead of Operational Transformation (OT) for handling distributed state and concurrent document editing smoothly.
|
|
21
|
-
- **Connection Resiliency**: Always implement automatic reconnection logic with exponential backoff for WebSockets. Handle offline states gracefully by syncing local changes once reconnected.
|
|
22
|
-
- **Presence & Awareness**: Implement presence indicators (who is online, cursor positions) separated from the core document state to reduce bandwidth and storage overhead.
|
|
23
|
-
- **Security in Real-time**: Authenticate and authorize every WebSocket connection upon establishment and validate all incoming socket messages to prevent malicious payloads.
|
|
24
|
-
- **Scale**: Be mindful of message broadcasting limits. Use Redis Pub/Sub or similar message brokers when scaling WebSocket servers across multiple instances.
|
|
25
|
-
|
|
26
|
-
### Trigger Conditions
|
|
27
|
-
Active whenever the user is building multiplayer features, live cursors, document co-editing, real-time chats, or working with WebSockets, Yjs, or WebRTC.
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
<a name="bahasa-indonesia"></a>
|
|
32
|
-
## Bahasa Indonesia
|
|
33
|
-
|
|
34
|
-
### Deskripsi
|
|
35
|
-
Panduan ahli untuk mengimplementasikan fitur kolaborasi real-time dan *multiplayer* pada aplikasi web. Mencakup Conflict-free Replicated Data Types (CRDTs) seperti Yjs/Automerge, WebSockets, WebRTC, dan layanan terkelola seperti Liveblocks atau Pusher.
|
|
36
|
-
|
|
37
|
-
### Instruksi
|
|
38
|
-
- **CRDT untuk State**: Gunakan CRDT (misalnya `yjs` atau `automerge`) daripada Operational Transformation (OT) untuk menangani *state* terdistribusi dan pengeditan dokumen secara bersamaan dengan lancar.
|
|
39
|
-
- **Ketahanan Koneksi**: Selalu terapkan logika penyambungan ulang otomatis dengan *exponential backoff* untuk WebSockets. Tangani *offline state* dengan baik dengan menyinkronkan perubahan lokal setelah tersambung kembali.
|
|
40
|
-
- **Presence & Awareness**: Terapkan indikator kehadiran (siapa yang sedang online, posisi kursor) yang dipisahkan dari status dokumen inti untuk mengurangi *overhead* bandwidth dan penyimpanan.
|
|
41
|
-
- **Keamanan Real-time**: Lakukan autentikasi dan otorisasi setiap koneksi WebSocket pada saat tersambung dan validasi semua pesan *socket* yang masuk untuk mencegah *payload* berbahaya.
|
|
42
|
-
- **Skalabilitas**: Perhatikan batas penyiaran (broadcasting) pesan. Gunakan Redis Pub/Sub atau *message broker* serupa saat meningkatkan (scaling) server WebSocket di beberapa instans.
|
|
43
|
-
|
|
44
|
-
### Kondisi Pemicu
|
|
45
|
-
Aktif setiap kali pengguna sedang membangun fitur *multiplayer*, kursor langsung (live cursors), pengeditan dokumen bersama, obrolan real-time, atau bekerja dengan WebSockets, Yjs, atau WebRTC.
|
|
1
|
+
---
|
|
2
|
+
name: realtime-collaboration-expert
|
|
3
|
+
description: "Expert guide for building real-time collaboration features using WebSockets, WebRTC, CRDTs (Yjs, Automerge), and Liveblocks / Panduan ahli untuk fitur kolaborasi real-time."
|
|
4
|
+
author: "Antigravity"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Real-Time Collaboration Expert / Ahli Kolaborasi Real-Time
|
|
8
|
+
|
|
9
|
+
[English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
<a name="english"></a>
|
|
14
|
+
## English
|
|
15
|
+
|
|
16
|
+
### Description
|
|
17
|
+
Expert guide for implementing multiplayer, real-time collaboration features in web applications. Covers Conflict-free Replicated Data Types (CRDTs) like Yjs/Automerge, WebSockets, WebRTC, and Managed services like Liveblocks or Pusher.
|
|
18
|
+
|
|
19
|
+
### Instructions
|
|
20
|
+
- **CRDTs for State**: Use CRDTs (e.g., `yjs` or `automerge`) instead of Operational Transformation (OT) for handling distributed state and concurrent document editing smoothly.
|
|
21
|
+
- **Connection Resiliency**: Always implement automatic reconnection logic with exponential backoff for WebSockets. Handle offline states gracefully by syncing local changes once reconnected.
|
|
22
|
+
- **Presence & Awareness**: Implement presence indicators (who is online, cursor positions) separated from the core document state to reduce bandwidth and storage overhead.
|
|
23
|
+
- **Security in Real-time**: Authenticate and authorize every WebSocket connection upon establishment and validate all incoming socket messages to prevent malicious payloads.
|
|
24
|
+
- **Scale**: Be mindful of message broadcasting limits. Use Redis Pub/Sub or similar message brokers when scaling WebSocket servers across multiple instances.
|
|
25
|
+
|
|
26
|
+
### Trigger Conditions
|
|
27
|
+
Active whenever the user is building multiplayer features, live cursors, document co-editing, real-time chats, or working with WebSockets, Yjs, or WebRTC.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
<a name="bahasa-indonesia"></a>
|
|
32
|
+
## Bahasa Indonesia
|
|
33
|
+
|
|
34
|
+
### Deskripsi
|
|
35
|
+
Panduan ahli untuk mengimplementasikan fitur kolaborasi real-time dan *multiplayer* pada aplikasi web. Mencakup Conflict-free Replicated Data Types (CRDTs) seperti Yjs/Automerge, WebSockets, WebRTC, dan layanan terkelola seperti Liveblocks atau Pusher.
|
|
36
|
+
|
|
37
|
+
### Instruksi
|
|
38
|
+
- **CRDT untuk State**: Gunakan CRDT (misalnya `yjs` atau `automerge`) daripada Operational Transformation (OT) untuk menangani *state* terdistribusi dan pengeditan dokumen secara bersamaan dengan lancar.
|
|
39
|
+
- **Ketahanan Koneksi**: Selalu terapkan logika penyambungan ulang otomatis dengan *exponential backoff* untuk WebSockets. Tangani *offline state* dengan baik dengan menyinkronkan perubahan lokal setelah tersambung kembali.
|
|
40
|
+
- **Presence & Awareness**: Terapkan indikator kehadiran (siapa yang sedang online, posisi kursor) yang dipisahkan dari status dokumen inti untuk mengurangi *overhead* bandwidth dan penyimpanan.
|
|
41
|
+
- **Keamanan Real-time**: Lakukan autentikasi dan otorisasi setiap koneksi WebSocket pada saat tersambung dan validasi semua pesan *socket* yang masuk untuk mencegah *payload* berbahaya.
|
|
42
|
+
- **Skalabilitas**: Perhatikan batas penyiaran (broadcasting) pesan. Gunakan Redis Pub/Sub atau *message broker* serupa saat meningkatkan (scaling) server WebSocket di beberapa instans.
|
|
43
|
+
|
|
44
|
+
### Kondisi Pemicu
|
|
45
|
+
Aktif setiap kali pengguna sedang membangun fitur *multiplayer*, kursor langsung (live cursors), pengeditan dokumen bersama, obrolan real-time, atau bekerja dengan WebSockets, Yjs, atau WebRTC.
|