tribunal-kit 3.0.0 → 3.1.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/.agent/ARCHITECTURE.md +99 -99
- package/.agent/GEMINI.md +52 -52
- package/.agent/agents/accessibility-reviewer.md +187 -220
- package/.agent/agents/ai-code-reviewer.md +199 -233
- package/.agent/agents/backend-specialist.md +215 -238
- package/.agent/agents/code-archaeologist.md +161 -181
- package/.agent/agents/database-architect.md +184 -207
- package/.agent/agents/debugger.md +191 -218
- package/.agent/agents/dependency-reviewer.md +103 -136
- package/.agent/agents/devops-engineer.md +218 -238
- package/.agent/agents/documentation-writer.md +201 -221
- package/.agent/agents/explorer-agent.md +160 -180
- package/.agent/agents/frontend-reviewer.md +160 -194
- package/.agent/agents/frontend-specialist.md +248 -237
- package/.agent/agents/game-developer.md +48 -52
- package/.agent/agents/logic-reviewer.md +116 -149
- package/.agent/agents/mobile-developer.md +200 -223
- package/.agent/agents/mobile-reviewer.md +162 -195
- package/.agent/agents/orchestrator.md +181 -211
- package/.agent/agents/penetration-tester.md +157 -174
- package/.agent/agents/performance-optimizer.md +183 -203
- package/.agent/agents/performance-reviewer.md +178 -211
- package/.agent/agents/product-manager.md +142 -162
- package/.agent/agents/product-owner.md +6 -25
- package/.agent/agents/project-planner.md +142 -162
- package/.agent/agents/qa-automation-engineer.md +225 -242
- package/.agent/agents/security-auditor.md +174 -194
- package/.agent/agents/seo-specialist.md +193 -213
- package/.agent/agents/sql-reviewer.md +161 -194
- package/.agent/agents/supervisor-agent.md +184 -203
- package/.agent/agents/swarm-worker-contracts.md +17 -17
- package/.agent/agents/swarm-worker-registry.md +46 -46
- package/.agent/agents/test-coverage-reviewer.md +160 -193
- package/.agent/agents/test-engineer.md +0 -21
- package/.agent/agents/type-safety-reviewer.md +175 -208
- package/.agent/patterns/generator.md +9 -9
- package/.agent/patterns/inversion.md +12 -12
- package/.agent/patterns/pipeline.md +9 -9
- package/.agent/patterns/reviewer.md +13 -13
- package/.agent/patterns/tool-wrapper.md +9 -9
- package/.agent/rules/GEMINI.md +63 -63
- package/.agent/scripts/compress_skills.py +167 -0
- package/.agent/scripts/consolidate_skills.py +173 -0
- package/.agent/scripts/deep_compress.py +202 -0
- package/.agent/scripts/minify_context.py +80 -0
- package/.agent/scripts/security_scan.py +1 -1
- package/.agent/scripts/strip_tribunal.py +41 -0
- package/.agent/skills/agent-organizer/SKILL.md +92 -126
- package/.agent/skills/agentic-patterns/SKILL.md +0 -70
- package/.agent/skills/ai-prompt-injection-defense/SKILL.md +126 -160
- package/.agent/skills/api-patterns/SKILL.md +123 -215
- package/.agent/skills/api-security-auditor/SKILL.md +143 -177
- package/.agent/skills/app-builder/SKILL.md +326 -50
- package/.agent/skills/app-builder/templates/SKILL.md +13 -15
- package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +16 -16
- package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +22 -22
- package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +18 -18
- package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +20 -20
- package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +17 -17
- package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +18 -18
- package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +21 -21
- package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +19 -19
- package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +26 -26
- package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +26 -26
- package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +19 -19
- package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +18 -18
- package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +20 -20
- package/.agent/skills/appflow-wireframe/SKILL.md +87 -121
- package/.agent/skills/architecture/SKILL.md +82 -252
- package/.agent/skills/authentication-best-practices/SKILL.md +139 -173
- package/.agent/skills/bash-linux/SKILL.md +120 -154
- package/.agent/skills/behavioral-modes/SKILL.md +8 -69
- package/.agent/skills/brainstorming/SKILL.md +428 -104
- package/.agent/skills/building-native-ui/SKILL.md +143 -174
- package/.agent/skills/clean-code/SKILL.md +323 -360
- package/.agent/skills/code-review-checklist/SKILL.md +0 -62
- package/.agent/skills/config-validator/SKILL.md +107 -141
- package/.agent/skills/csharp-developer/SKILL.md +468 -528
- package/.agent/skills/database-design/SKILL.md +104 -369
- package/.agent/skills/deployment-procedures/SKILL.md +111 -145
- package/.agent/skills/devops-engineer/SKILL.md +295 -332
- package/.agent/skills/devops-incident-responder/SKILL.md +79 -113
- package/.agent/skills/doc.md +5 -5
- package/.agent/skills/documentation-templates/SKILL.md +19 -63
- package/.agent/skills/edge-computing/SKILL.md +123 -157
- package/.agent/skills/extract-design-system/SKILL.md +100 -134
- package/.agent/skills/framer-motion-expert/SKILL.md +111 -855
- package/.agent/skills/frontend-design/SKILL.md +151 -499
- package/.agent/skills/game-design-expert/SKILL.md +71 -105
- package/.agent/skills/game-engineering-expert/SKILL.md +88 -122
- package/.agent/skills/geo-fundamentals/SKILL.md +89 -124
- package/.agent/skills/github-operations/SKILL.md +279 -314
- package/.agent/skills/gsap-expert/SKILL.md +119 -826
- package/.agent/skills/i18n-localization/SKILL.md +104 -138
- package/.agent/skills/intelligent-routing/SKILL.md +159 -127
- package/.agent/skills/lint-and-validate/SKILL.md +8 -52
- package/.agent/skills/llm-engineering/SKILL.md +344 -357
- package/.agent/skills/local-first/SKILL.md +120 -154
- package/.agent/skills/mcp-builder/SKILL.md +84 -118
- package/.agent/skills/mobile-design/SKILL.md +213 -219
- package/.agent/skills/motion-engineering/SKILL.md +184 -0
- package/.agent/skills/nextjs-react-expert/SKILL.md +99 -698
- package/.agent/skills/nodejs-best-practices/SKILL.md +498 -559
- package/.agent/skills/observability/SKILL.md +293 -330
- package/.agent/skills/parallel-agents/SKILL.md +88 -122
- package/.agent/skills/performance-profiling/SKILL.md +217 -254
- package/.agent/skills/plan-writing/SKILL.md +84 -118
- package/.agent/skills/platform-engineer/SKILL.md +89 -123
- package/.agent/skills/playwright-best-practices/SKILL.md +128 -162
- package/.agent/skills/powershell-windows/SKILL.md +112 -146
- package/.agent/skills/python-patterns/SKILL.md +7 -35
- package/.agent/skills/python-pro/SKILL.md +148 -754
- package/.agent/skills/react-specialist/SKILL.md +123 -827
- package/.agent/skills/readme-builder/SKILL.md +15 -85
- package/.agent/skills/realtime-patterns/SKILL.md +269 -304
- package/.agent/skills/red-team-tactics/SKILL.md +10 -51
- package/.agent/skills/rust-pro/SKILL.md +623 -701
- package/.agent/skills/seo-fundamentals/SKILL.md +120 -154
- package/.agent/skills/server-management/SKILL.md +156 -190
- package/.agent/skills/shadcn-ui-expert/SKILL.md +172 -206
- package/.agent/skills/skill-creator/SKILL.md +18 -58
- package/.agent/skills/sql-pro/SKILL.md +579 -633
- package/.agent/skills/supabase-postgres-best-practices/SKILL.md +28 -68
- package/.agent/skills/swiftui-expert/SKILL.md +142 -176
- package/.agent/skills/systematic-debugging/SKILL.md +84 -118
- package/.agent/skills/tailwind-patterns/SKILL.md +516 -576
- package/.agent/skills/tdd-workflow/SKILL.md +103 -137
- package/.agent/skills/test-result-analyzer/SKILL.md +33 -73
- package/.agent/skills/testing-patterns/SKILL.md +512 -573
- package/.agent/skills/trend-researcher/SKILL.md +30 -71
- package/.agent/skills/ui-ux-pro-max/SKILL.md +0 -41
- package/.agent/skills/ui-ux-researcher/SKILL.md +51 -91
- package/.agent/skills/vue-expert/SKILL.md +127 -866
- package/.agent/skills/vulnerability-scanner/SKILL.md +354 -269
- package/.agent/skills/web-accessibility-auditor/SKILL.md +159 -193
- package/.agent/skills/web-design-guidelines/SKILL.md +17 -61
- package/.agent/skills/webapp-testing/SKILL.md +111 -145
- package/.agent/skills/whimsy-injector/SKILL.md +58 -132
- package/.agent/skills/workflow-optimizer/SKILL.md +28 -68
- package/.agent/workflows/api-tester.md +151 -151
- package/.agent/workflows/audit.md +127 -138
- package/.agent/workflows/brainstorm.md +110 -110
- package/.agent/workflows/changelog.md +112 -112
- package/.agent/workflows/create.md +124 -124
- package/.agent/workflows/debug.md +165 -189
- package/.agent/workflows/deploy.md +180 -189
- package/.agent/workflows/enhance.md +128 -151
- package/.agent/workflows/fix.md +114 -135
- package/.agent/workflows/generate.md +12 -4
- package/.agent/workflows/migrate.md +160 -160
- package/.agent/workflows/orchestrate.md +168 -168
- package/.agent/workflows/performance-benchmarker.md +114 -123
- package/.agent/workflows/plan.md +173 -173
- package/.agent/workflows/preview.md +80 -80
- package/.agent/workflows/refactor.md +161 -183
- package/.agent/workflows/review-ai.md +101 -129
- package/.agent/workflows/review.md +116 -116
- package/.agent/workflows/session.md +94 -94
- package/.agent/workflows/status.md +79 -79
- package/.agent/workflows/strengthen-skills.md +138 -139
- package/.agent/workflows/swarm.md +179 -179
- package/.agent/workflows/test.md +189 -211
- package/.agent/workflows/tribunal-backend.md +93 -113
- package/.agent/workflows/tribunal-database.md +94 -115
- package/.agent/workflows/tribunal-frontend.md +95 -118
- package/.agent/workflows/tribunal-full.md +92 -133
- package/.agent/workflows/tribunal-mobile.md +94 -119
- package/.agent/workflows/tribunal-performance.md +109 -133
- package/.agent/workflows/ui-ux-pro-max.md +122 -143
- package/package.json +1 -1
- package/.agent/skills/api-patterns/api-style.md +0 -42
- package/.agent/skills/api-patterns/auth.md +0 -24
- package/.agent/skills/api-patterns/documentation.md +0 -26
- package/.agent/skills/api-patterns/graphql.md +0 -41
- package/.agent/skills/api-patterns/rate-limiting.md +0 -31
- package/.agent/skills/api-patterns/response.md +0 -37
- package/.agent/skills/api-patterns/rest.md +0 -40
- package/.agent/skills/api-patterns/security-testing.md +0 -122
- package/.agent/skills/api-patterns/trpc.md +0 -41
- package/.agent/skills/api-patterns/versioning.md +0 -22
- package/.agent/skills/app-builder/agent-coordination.md +0 -71
- package/.agent/skills/app-builder/feature-building.md +0 -53
- package/.agent/skills/app-builder/project-detection.md +0 -34
- package/.agent/skills/app-builder/scaffolding.md +0 -118
- package/.agent/skills/app-builder/tech-stack.md +0 -40
- package/.agent/skills/architecture/context-discovery.md +0 -43
- package/.agent/skills/architecture/examples.md +0 -94
- package/.agent/skills/architecture/pattern-selection.md +0 -68
- package/.agent/skills/architecture/patterns-reference.md +0 -50
- package/.agent/skills/architecture/trade-off-analysis.md +0 -77
- package/.agent/skills/brainstorming/dynamic-questioning.md +0 -360
- package/.agent/skills/database-design/database-selection.md +0 -43
- package/.agent/skills/database-design/indexing.md +0 -39
- package/.agent/skills/database-design/migrations.md +0 -48
- package/.agent/skills/database-design/optimization.md +0 -36
- package/.agent/skills/database-design/orm-selection.md +0 -30
- package/.agent/skills/database-design/schema-design.md +0 -56
- package/.agent/skills/frontend-design/animation-guide.md +0 -331
- package/.agent/skills/frontend-design/color-system.md +0 -329
- package/.agent/skills/frontend-design/decision-trees.md +0 -418
- package/.agent/skills/frontend-design/motion-graphics.md +0 -306
- package/.agent/skills/frontend-design/typography-system.md +0 -363
- package/.agent/skills/frontend-design/ux-psychology.md +0 -1116
- package/.agent/skills/frontend-design/visual-effects.md +0 -383
- package/.agent/skills/intelligent-routing/router-manifest.md +0 -65
- package/.agent/skills/mobile-design/decision-trees.md +0 -516
- package/.agent/skills/mobile-design/mobile-backend.md +0 -491
- package/.agent/skills/mobile-design/mobile-color-system.md +0 -420
- package/.agent/skills/mobile-design/mobile-debugging.md +0 -122
- package/.agent/skills/mobile-design/mobile-design-thinking.md +0 -357
- package/.agent/skills/mobile-design/mobile-navigation.md +0 -458
- package/.agent/skills/mobile-design/mobile-performance.md +0 -767
- package/.agent/skills/mobile-design/mobile-testing.md +0 -356
- package/.agent/skills/mobile-design/mobile-typography.md +0 -433
- package/.agent/skills/mobile-design/platform-android.md +0 -666
- package/.agent/skills/mobile-design/platform-ios.md +0 -561
- package/.agent/skills/mobile-design/touch-psychology.md +0 -537
- package/.agent/skills/nextjs-react-expert/1-async-eliminating-waterfalls.md +0 -312
- package/.agent/skills/nextjs-react-expert/2-bundle-bundle-size-optimization.md +0 -240
- package/.agent/skills/nextjs-react-expert/3-server-server-side-performance.md +0 -490
- package/.agent/skills/nextjs-react-expert/4-client-client-side-data-fetching.md +0 -264
- package/.agent/skills/nextjs-react-expert/5-rerender-re-render-optimization.md +0 -581
- package/.agent/skills/nextjs-react-expert/6-rendering-rendering-performance.md +0 -432
- package/.agent/skills/nextjs-react-expert/7-js-javascript-performance.md +0 -684
- package/.agent/skills/nextjs-react-expert/8-advanced-advanced-patterns.md +0 -150
- package/.agent/skills/vulnerability-scanner/checklists.md +0 -121
|
@@ -2,206 +2,119 @@
|
|
|
2
2
|
name: api-patterns
|
|
3
3
|
description: API design mastery. REST, GraphQL, tRPC, and gRPC selection. Request/response design, pagination (cursor/offset), filtering, versioning, rate limiting, error formats (RFC 9457), authentication (JWT/OAuth2/API keys), idempotency, file uploads, webhooks, and OpenAPI documentation. Use when designing APIs, choosing protocols, or implementing API standards.
|
|
4
4
|
allowed-tools: Read, Write, Edit, Glob, Grep
|
|
5
|
-
version:
|
|
6
|
-
last-updated: 2026-04-
|
|
7
|
-
applies-to-model: gemini-
|
|
5
|
+
version: 3.1.0
|
|
6
|
+
last-updated: 2026-04-07
|
|
7
|
+
applies-to-model: gemini-3-1-pro, claude-3-7-sonnet
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# API Patterns — Design & Protocol Mastery
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
## Hallucination Traps (Read First)
|
|
13
|
+
- ❌ JWT in URL query params → ✅ `Authorization: Bearer` header only. Query params get logged in server access logs.
|
|
14
|
+
- ❌ Assuming JWT is encrypted → ✅ JWT is base64-encoded (NOT encrypted). Anyone can decode it. Never put secrets/PII in the payload.
|
|
15
|
+
- ❌ Offset pagination on large tables → ✅ `OFFSET 100000` scans and discards 100K rows. Use cursor pagination for tables > 10K rows.
|
|
16
|
+
- ❌ Verbs in REST URLs (`/api/getUsers`) → ✅ Nouns only (`GET /api/users`). HTTP method IS the verb.
|
|
17
|
+
- ❌ `POST` is idempotent → ✅ `POST` is NOT idempotent — requires `Idempotency-Key` header for safe retries.
|
|
18
|
+
- ❌ GraphQL has no security risks → ✅ Deeply nested queries are a DoS vector. Set max depth, query cost limits. Disable introspection in production.
|
|
14
19
|
|
|
15
20
|
---
|
|
16
21
|
|
|
17
|
-
## Protocol Selection
|
|
22
|
+
## Protocol Selection Matrix
|
|
18
23
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
| Protocol | Use When |
|
|
25
|
+
|----------|----------|
|
|
26
|
+
| **REST** | Public APIs, 3rd-party consumers, standard CRUD, HTTP caching |
|
|
27
|
+
| **GraphQL** | Complex nested data, multiple clients, flexible queries, mobile bandwidth sensitivity |
|
|
28
|
+
| **tRPC** | Full-stack TypeScript (Next.js monorepo), shared types, no codegen |
|
|
29
|
+
| **gRPC** | Internal microservices, high-throughput, streaming, binary protocol |
|
|
30
|
+
| **WebSocket** | Bidirectional real-time (chat, gaming, live collaboration) |
|
|
31
|
+
| **SSE** | Server-to-client streaming only (AI token streaming, live feeds) |
|
|
27
32
|
|
|
28
33
|
---
|
|
29
34
|
|
|
30
|
-
## REST
|
|
31
|
-
|
|
32
|
-
### URL Design
|
|
35
|
+
## REST Design
|
|
33
36
|
|
|
37
|
+
### URL Conventions
|
|
34
38
|
```
|
|
35
|
-
✅
|
|
36
|
-
GET /api/v1/users
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
DELETE /api/v1/users/123 → delete user 123
|
|
42
|
-
|
|
43
|
-
GET /api/v1/users/123/posts → list posts by user 123
|
|
44
|
-
POST /api/v1/users/123/posts → create post for user 123
|
|
45
|
-
|
|
46
|
-
❌ BAD:
|
|
47
|
-
GET /api/getUsers ← verb in URL
|
|
48
|
-
POST /api/createUser ← verb in URL
|
|
49
|
-
GET /api/v1/user ← singular (use plural)
|
|
50
|
-
DELETE /api/v1/users/123/delete ← redundant verb
|
|
51
|
-
GET /api/v1/Users ← uppercase (use lowercase)
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### Pagination (Cursor vs Offset)
|
|
55
|
-
|
|
56
|
-
```typescript
|
|
57
|
-
// ✅ Cursor-based (recommended for large/dynamic datasets)
|
|
58
|
-
// GET /api/v1/posts?cursor=eyJpZCI6MTAwfQ&limit=20
|
|
59
|
-
interface CursorPaginatedResponse<T> {
|
|
60
|
-
data: T[];
|
|
61
|
-
meta: {
|
|
62
|
-
hasMore: boolean;
|
|
63
|
-
nextCursor: string | null; // opaque, base64-encoded
|
|
64
|
-
prevCursor: string | null;
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Server implementation:
|
|
69
|
-
const cursor = decodeCursor(req.query.cursor); // { id: 100 }
|
|
70
|
-
const posts = await db.post.findMany({
|
|
71
|
-
where: { id: { lt: cursor.id } },
|
|
72
|
-
orderBy: { id: "desc" },
|
|
73
|
-
take: limit + 1, // fetch one extra to check hasMore
|
|
74
|
-
});
|
|
75
|
-
const hasMore = posts.length > limit;
|
|
76
|
-
if (hasMore) posts.pop();
|
|
77
|
-
|
|
78
|
-
// Offset-based (simpler, OK for small/static datasets)
|
|
79
|
-
// GET /api/v1/posts?page=3&limit=20
|
|
80
|
-
interface OffsetPaginatedResponse<T> {
|
|
81
|
-
data: T[];
|
|
82
|
-
meta: {
|
|
83
|
-
page: number;
|
|
84
|
-
limit: number;
|
|
85
|
-
totalCount: number;
|
|
86
|
-
totalPages: number;
|
|
87
|
-
};
|
|
88
|
-
}
|
|
39
|
+
✅ GET /api/v1/users list users
|
|
40
|
+
✅ GET /api/v1/users/123 get user by ID
|
|
41
|
+
✅ POST /api/v1/users create user
|
|
42
|
+
✅ PATCH /api/v1/users/123 partial update
|
|
43
|
+
✅ DELETE /api/v1/users/123 delete user
|
|
44
|
+
✅ GET /api/v1/users/123/posts nested resource
|
|
89
45
|
|
|
90
|
-
|
|
91
|
-
// OFFSET 100000 scans and discards 100,000 rows
|
|
92
|
-
// Use cursor pagination for tables with >10K rows
|
|
46
|
+
❌ /api/getUsers /api/createUser /api/user (singular) /api/Users (uppercase)
|
|
93
47
|
```
|
|
94
48
|
|
|
95
|
-
###
|
|
96
|
-
|
|
49
|
+
### HTTP Status Codes
|
|
97
50
|
```
|
|
98
|
-
GET /
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
51
|
+
200 OK → GET / PUT / PATCH success
|
|
52
|
+
201 Created → POST success (include Location: /api/v1/users/123 header)
|
|
53
|
+
204 No Content → DELETE success
|
|
54
|
+
400 Bad Request → Malformed request / missing fields
|
|
55
|
+
401 Unauthorized → Missing or invalid authentication
|
|
56
|
+
403 Forbidden → Authenticated but not authorized
|
|
57
|
+
404 Not Found → Resource does not exist
|
|
58
|
+
409 Conflict → Duplicate resource (email already exists)
|
|
59
|
+
422 Unprocessable → Valid JSON, semantically invalid data
|
|
60
|
+
429 Too Many Req → Rate limit exceeded
|
|
61
|
+
500 Internal → Unhandled server error — NEVER expose stack traces
|
|
102
62
|
```
|
|
103
63
|
|
|
104
64
|
### Response Envelope
|
|
105
|
-
|
|
106
65
|
```typescript
|
|
107
|
-
|
|
108
|
-
interface ApiResponse<T> {
|
|
109
|
-
data: T;
|
|
110
|
-
meta?: Record<string, unknown>;
|
|
111
|
-
}
|
|
66
|
+
interface ApiResponse<T> { data: T; meta?: Record<string, unknown>; }
|
|
112
67
|
|
|
113
68
|
interface ApiError {
|
|
114
69
|
error: {
|
|
115
70
|
code: string; // machine-readable: "VALIDATION_ERROR"
|
|
116
|
-
message: string; // human-readable: "Email is
|
|
117
|
-
details?: Array<{
|
|
118
|
-
|
|
119
|
-
message: string;
|
|
120
|
-
}>;
|
|
71
|
+
message: string; // human-readable: "Email is already in use"
|
|
72
|
+
details?: Array<{ field: string; message: string }>; // field-level errors
|
|
73
|
+
requestId?: string; // for support/tracing
|
|
121
74
|
};
|
|
122
75
|
}
|
|
123
|
-
|
|
124
|
-
// ✅ HTTP status codes — use correctly
|
|
125
|
-
// 200 OK → successful GET/PUT/PATCH
|
|
126
|
-
// 201 Created → successful POST (include Location header)
|
|
127
|
-
// 204 No Content → successful DELETE
|
|
128
|
-
// 400 Bad Request → validation error
|
|
129
|
-
// 401 Unauthorized → missing/invalid authentication
|
|
130
|
-
// 403 Forbidden → authenticated but not authorized
|
|
131
|
-
// 404 Not Found → resource doesn't exist
|
|
132
|
-
// 409 Conflict → duplicate resource (e.g., email already exists)
|
|
133
|
-
// 422 Unprocessable → semantically invalid (valid JSON, invalid data)
|
|
134
|
-
// 429 Too Many Req → rate limited
|
|
135
|
-
// 500 Internal → unhandled server error (never send stack traces)
|
|
136
76
|
```
|
|
137
77
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
```
|
|
141
|
-
URL path: /api/v1/users ← simplest, most common, recommended
|
|
142
|
-
Header: Accept: application/vnd.api.v1+json
|
|
143
|
-
Query param: /api/users?version=1
|
|
144
|
-
|
|
145
|
-
Rules:
|
|
146
|
-
- v1 is the default — never start at v0
|
|
147
|
-
- Deprecate before removing — give consumers 6+ months
|
|
148
|
-
- Breaking changes = new version (v2)
|
|
149
|
-
- Non-breaking additions (new fields) don't require a version bump
|
|
150
|
-
```
|
|
78
|
+
---
|
|
151
79
|
|
|
152
|
-
|
|
80
|
+
## Pagination
|
|
153
81
|
|
|
154
82
|
```typescript
|
|
155
|
-
//
|
|
156
|
-
//
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (!idempotencyKey) return res.status(400).json({ error: "Missing Idempotency-Key" });
|
|
162
|
-
|
|
163
|
-
// Check if this key was already processed
|
|
164
|
-
const existing = await cache.get(`idempotency:${idempotencyKey}`);
|
|
165
|
-
if (existing) return res.status(200).json(JSON.parse(existing));
|
|
166
|
-
|
|
167
|
-
// Process payment
|
|
168
|
-
const result = await processPayment(req.body);
|
|
169
|
-
|
|
170
|
-
// Store result with TTL (24h)
|
|
171
|
-
await cache.set(`idempotency:${idempotencyKey}`, JSON.stringify(result), "EX", 86400);
|
|
172
|
-
|
|
173
|
-
return res.status(201).json(result);
|
|
83
|
+
// ✅ Cursor-based — required for large/dynamic datasets
|
|
84
|
+
// GET /api/v1/posts?cursor=eyJpZCI6MTAwfQ&limit=20
|
|
85
|
+
const posts = await db.post.findMany({
|
|
86
|
+
where: { id: { lt: decodeCursor(req.query.cursor).id } },
|
|
87
|
+
orderBy: { id: "desc" },
|
|
88
|
+
take: limit + 1, // fetch one extra to determine hasMore
|
|
174
89
|
});
|
|
90
|
+
const hasMore = posts.length > limit;
|
|
91
|
+
if (hasMore) posts.pop();
|
|
92
|
+
return { data: posts, meta: { hasMore, nextCursor: encodeCursor(posts.at(-1)) } };
|
|
175
93
|
|
|
176
|
-
//
|
|
177
|
-
// GET
|
|
178
|
-
//
|
|
179
|
-
// PATCH → depends on implementation
|
|
94
|
+
// Offset-based — only for small datasets where users need page jumping
|
|
95
|
+
// GET /api/v1/posts?page=3&limit=20
|
|
96
|
+
// ❌ TRAP: OFFSET 100000 scans and discards 100K rows — degrades badly at scale
|
|
180
97
|
```
|
|
181
98
|
|
|
182
99
|
---
|
|
183
100
|
|
|
184
|
-
##
|
|
101
|
+
## Idempotency
|
|
185
102
|
|
|
186
103
|
```typescript
|
|
187
|
-
//
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
// API Key (service-to-service)
|
|
192
|
-
// Authorization: Bearer sk_live_abc123
|
|
193
|
-
// Scoped to specific permissions
|
|
194
|
-
|
|
195
|
-
// OAuth 2.0 (delegated access)
|
|
196
|
-
// Authorization Code flow for web apps
|
|
197
|
-
// PKCE flow for SPAs and mobile
|
|
104
|
+
// POST /api/v1/payments with header: Idempotency-Key: <uuid>
|
|
105
|
+
app.post("/api/v1/payments", async (req, res) => {
|
|
106
|
+
const key = req.headers["idempotency-key"];
|
|
107
|
+
if (!key) return res.status(400).json({ error: "Missing Idempotency-Key" });
|
|
198
108
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
// ✅ Authorization: Bearer eyJ... ← header only
|
|
109
|
+
const cached = await redis.get(`idempotency:${key}`);
|
|
110
|
+
if (cached) return res.status(200).json(JSON.parse(cached));
|
|
202
111
|
|
|
203
|
-
|
|
204
|
-
|
|
112
|
+
const result = await processPayment(req.body);
|
|
113
|
+
await redis.set(`idempotency:${key}`, JSON.stringify(result), "EX", 86400);
|
|
114
|
+
return res.status(201).json(result);
|
|
115
|
+
});
|
|
116
|
+
// GET, PUT, DELETE → naturally idempotent (safe to retry without a key)
|
|
117
|
+
// POST, PATCH → NOT idempotent by default — require Idempotency-Key
|
|
205
118
|
```
|
|
206
119
|
|
|
207
120
|
---
|
|
@@ -209,81 +122,76 @@ app.post("/api/v1/payments", async (req, res) => {
|
|
|
209
122
|
## Webhooks
|
|
210
123
|
|
|
211
124
|
```typescript
|
|
212
|
-
//
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
data: Record<string, unknown>;
|
|
125
|
+
// HMAC signature verification (always verify — never trust unsigned webhooks)
|
|
126
|
+
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
127
|
+
function verify(payload: string, signature: string, secret: string): boolean {
|
|
128
|
+
const expected = createHmac("sha256", secret).update(payload).digest("hex");
|
|
129
|
+
return timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
|
|
218
130
|
}
|
|
219
131
|
|
|
220
|
-
// Verification with HMAC signature
|
|
221
|
-
import { createHmac } from "node:crypto";
|
|
222
|
-
|
|
223
|
-
function signWebhook(payload: string, secret: string): string {
|
|
224
|
-
return createHmac("sha256", secret).update(payload).digest("hex");
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// Receiver verification:
|
|
228
132
|
app.post("/webhooks", (req, res) => {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
// Process webhook... return 200 quickly, process async
|
|
235
|
-
res.status(200).send("OK");
|
|
236
|
-
processWebhookAsync(req.body);
|
|
133
|
+
if (!verify(JSON.stringify(req.body), req.headers["x-webhook-signature"] as string, WEBHOOK_SECRET))
|
|
134
|
+
return res.status(401).send("Invalid signature");
|
|
135
|
+
res.status(200).send("OK"); // respond immediately
|
|
136
|
+
processWebhookAsync(req.body); // process asynchronously
|
|
237
137
|
});
|
|
238
|
-
|
|
239
|
-
//
|
|
138
|
+
// Retry policy: 3 retries with exponential backoff (1s → 10s → 100s)
|
|
139
|
+
// Include unique event ID in payload for receiver-side deduplication
|
|
240
140
|
```
|
|
241
141
|
|
|
242
142
|
---
|
|
243
143
|
|
|
244
|
-
##
|
|
144
|
+
## Versioning
|
|
245
145
|
|
|
246
146
|
```
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
147
|
+
URL path (recommended): /api/v1/users → simplest, most common, cache-friendly
|
|
148
|
+
Header: Accept: application/vnd.api.v1+json
|
|
149
|
+
Query param: /api/users?version=1 → messy, avoid
|
|
150
|
+
|
|
151
|
+
Rules:
|
|
152
|
+
- Start at v1, never v0
|
|
153
|
+
- Breaking changes = new major version (v2)
|
|
154
|
+
- Non-breaking additions (new optional fields) do NOT need a version bump
|
|
155
|
+
- Deprecate before removing — give consumers 6+ months notice
|
|
253
156
|
```
|
|
254
157
|
|
|
255
158
|
---
|
|
256
159
|
|
|
257
|
-
##
|
|
258
|
-
|
|
259
|
-
1. **Verbs in URLs:** REST URLs are nouns. Never `/api/getUsers` or `/api/deleteUser/123`.
|
|
260
|
-
2. **Singular Resource Names:** Use plural: `/users`, `/posts`, `/orders`. Not `/user`, `/post`.
|
|
261
|
-
3. **200 for Everything:** Use correct status codes. 201 for creation, 204 for deletion, 4xx for client errors.
|
|
262
|
-
4. **Offset Pagination on Large Tables:** OFFSET degrades linearly. Use cursor pagination for >10K rows.
|
|
263
|
-
5. **JWT in Query Params:** JWTs must be in `Authorization` header, never URL query strings.
|
|
264
|
-
6. **Secrets in JWT Payload:** JWT is base64, not encrypted. Never put passwords or PII in claims.
|
|
265
|
-
7. **Missing Idempotency on POST:** POST is not idempotent. Payment/order endpoints need `Idempotency-Key`.
|
|
266
|
-
8. **Inconsistent Error Shapes:** Every error must have the same `{ error: { code, message } }` structure.
|
|
267
|
-
9. **Breaking Changes Without Versioning:** Adding required fields or removing fields = breaking change = new version.
|
|
268
|
-
10. **Webhooks Without Signatures:** Always sign webhook payloads with HMAC. Receivers must verify signatures.
|
|
160
|
+
## Rate Limiting
|
|
269
161
|
|
|
270
|
-
|
|
162
|
+
```
|
|
163
|
+
Strategy How When
|
|
164
|
+
Token bucket → Burst allowed, refills Most APIs (recommended)
|
|
165
|
+
Sliding window → Smooth distribution Strict fairness required
|
|
166
|
+
Fixed window → Simple counter per period Basic needs only
|
|
271
167
|
|
|
272
|
-
|
|
168
|
+
Response headers to always include:
|
|
169
|
+
X-RateLimit-Limit (max requests in window)
|
|
170
|
+
X-RateLimit-Remaining (requests left)
|
|
171
|
+
X-RateLimit-Reset (Unix timestamp when limit resets)
|
|
172
|
+
Retry-After (seconds to wait on 429)
|
|
173
|
+
```
|
|
273
174
|
|
|
274
|
-
|
|
175
|
+
---
|
|
275
176
|
|
|
276
|
-
|
|
177
|
+
## GraphQL Security
|
|
277
178
|
|
|
278
179
|
```
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
✅ Are POST endpoints idempotent (with Idempotency-Key)?
|
|
285
|
-
✅ Am I versioning the API (v1, v2)?
|
|
286
|
-
✅ Are webhooks signed with HMAC?
|
|
287
|
-
✅ Is all input validated before processing?
|
|
288
|
-
✅ Did I add rate limiting to public endpoints?
|
|
180
|
+
Protect against:
|
|
181
|
+
Depth attacks → Set max query depth (typically 7–10)
|
|
182
|
+
Cost attacks → Calculate query complexity score, reject > threshold
|
|
183
|
+
Batch abuse → Limit batch size / alias count
|
|
184
|
+
Introspection → Disable in production (exposes full schema to attackers)
|
|
289
185
|
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Authentication Selection
|
|
190
|
+
|
|
191
|
+
| Pattern | Best For |
|
|
192
|
+
|---------|----------|
|
|
193
|
+
| **JWT** (short-lived access + httpOnly refresh) | Stateless services, microservices |
|
|
194
|
+
| **Session** | Traditional server-rendered apps |
|
|
195
|
+
| **OAuth 2.0 / OIDC** | Third-party login, delegated access |
|
|
196
|
+
| **API Key** | Server-to-server, public API consumers |
|
|
197
|
+
| **Passkey (WebAuthn)** | Modern passwordless (2026+) |
|