api-patterns ยท diff
v5.0.0 to v6.0.0
66 added, 5 removed. Audit A to A.
---
name: api-patterns
- description: "Use when 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."
- version: 5.0.0
- last-updated: 2026-09-13
+ description: "Use when designing, implementing, auditing, and hardening api patterns server logic, APIs, background jobs, and error boundaries."
+ version: 6.0.0
+ last-updated: 2026-09-29
skills:
- api-security-auditor
- backend-security-expert
- schema-reviewer
tools: Read, Grep, Glob, Bash, Edit, Write
scripts-binding:
- .agent/scripts/lint_runner.js
- .agent/scripts/verify_all.js
---
# API Patterns โ Design & Protocol Mastery
- ---
+ ## Mandatory Pre-Flight Context Inspection
+ Before reading, generating, or refactoring code in the `api-patterns` domain, inspect these 5 critical parameters:
+ 1. **System Boundaries & Dependencies**: Verify that all required dependencies exist in target package manifests and environment paths.
+ 2. **Runtime Context & Platform Invariants**: Confirm target platform constraints (Node.js, Browser, Mobile OS, Edge runtime) before applying APIs.
+ 3. **Execution Guardrails**: Identify potential side-effects, state mutations, and unhandled asynchronous exceptions.
+ 4. **Validation & Type Contracts**: Validate input data schemas and strict type constraints across all module interfaces.
+ 5. **Observability & Proof of Execution**: Ensure execution produces tangible verification signals (terminal output, tests, metrics).
- ## ๐ ๏ธ Technical Architecture & Reference Recipes
+ ## Activation Boundaries
+ - **Activate when:** Use when designing, implementing, auditing, and hardening api patterns server logic, APIs, background jobs, and error boundaries.
+ - **DO NOT activate when:** The task falls outside the `api-patterns` domain or is managed by a different dedicated specialist agent.
+
+
+ ## ๐ Multi-Pass Execution Protocol
+
+ | Pass | Phase | Core Action | Adaptive Depth |
+ |:---|:---|:---|:---|
+ | **Pass 1** | **Understand** | Deconstruct the user's explicit objective, implicit requirements, and platform constraints. | Fast / Standard / Deep |
+ | **Pass 2** | **Plan** | Decompose task into smallest logical steps; map dependencies, affected files, and tool calls. | Standard / Deep |
+ | **Pass 3** | **Execute** | Implement solution with production-grade craft, zero placeholders, and strict typing. | All Modes |
+ | **Pass 4** | **Verify** | Run linters, unit tests, or compiler checks to validate structural correctness. | All Modes |
+ | **Pass 5** | **Attack & Falsify** | Perform adversarial search for edge-case failures, counterexamples, race conditions, and traps. | Standard / Deep |
+ | **Pass 6** | **Harden** | Eliminate discovered friction, optimize performance, and harden error boundaries. | Standard / Deep |
+ | **Pass 7** | **Quality Gate** | Enforce Verification-Before-Completion (VBC) with concrete terminal proof before finalizing. | All Modes |
+
+
---
+ ## ๐ ๏ธ Technical Architecture & Reference Recipes
+
## Hallucination Traps (Read First)
- โ JWT in URL query params โ โ
`Authorization: Bearer` header only. Query params get logged in server access logs.
- โ Assuming JWT is encrypted โ โ
JWT is base64-encoded (NOT encrypted). Anyone can decode it. Never put secrets/PII in the payload.
- โ Offset pagination on large tables โ โ
`OFFSET 100000` scans and discards 100K rows. Use cursor pagination for tables > 10K rows.
- โ Verbs in REST URLs (`/api/getUsers`) โ โ
Nouns only (`GET /api/users`). HTTP method IS the verb.
- โ `POST` is idempotent โ โ
`POST` is NOT idempotent โ requires `Idempotency-Key` header for safe retries.
- โ GraphQL has no security risks โ โ
Deeply nested queries are a DoS vector. Set max depth, query cost limits. Disable introspection in production.
---
## Protocol Selection Matrix
| Protocol | Use When |
| ------------- | ------------------------------------------------------------------------------------- |
| **REST** | Public APIs, 3rd-party consumers, standard CRUD, HTTP caching |
| **GraphQL** | Complex nested data, multiple clients, flexible queries, mobile bandwidth sensitivity |
| **tRPC** | Full-stack TypeScript (Next.js monorepo), shared types, no codegen |
| **gRPC** | Internal microservices, high-throughput, streaming, binary protocol |
| **WebSocket** | Bidirectional real-time (chat, gaming, live collaboration) |
| **SSE** | Server-to-client streaming only (AI token streaming, live feeds) |
---
## REST Design
### URL Conventions
```
โ
GET /api/v1/users list users
โ
GET /api/v1/users/123 get user by ID
โ
POST /api/v1/users create user
โ
PATCH /api/v1/users/123 partial update
โ
DELETE /api/v1/users/123 delete user
โ
GET /api/v1/users/123/posts nested resource
โ /api/getUsers /api/createUser /api/user (singular) /api/Users (uppercase)
```
### HTTP Status Codes
```
200 OK โ GET / PUT / PATCH success
201 Created โ POST success (include Location: /api/v1/users/123 header)
204 No Content โ DELETE success
400 Bad Request โ Malformed request / missing fields
401 Unauthorized โ Missing or invalid authentication
403 Forbidden โ Authenticated but not authorized
404 Not Found โ Resource does not exist
409 Conflict โ Duplicate resource (email already exists)
422 Unprocessable โ Valid JSON, semantically invalid data
429 Too Many Req โ Rate limit exceeded
500 Internal โ Unhandled server error โ NEVER expose stack traces
```
### Response Envelope
```typescript
interface ApiResponse<T> {
data: T;
meta?: Record<string, unknown>;
}
interface ApiError {
error: {
code: string; // machine-readable: "VALIDATION_ERROR"
message: string; // human-readable: "Email is already in use"
details?: Array<{ field: string; message: string }>; // field-level errors
requestId?: string; // for support/tracing
};
}
```
---
## Pagination
```typescript
// โ
Cursor-based โ required for large/dynamic datasets
// GET /api/v1/posts?cursor=eyJpZCI6MTAwfQ&limit=20
const posts = await db.post.findMany({
where: { id: { lt: decodeCursor(req.query.cursor).id } },
orderBy: { id: 'desc' },
take: limit + 1, // fetch one extra to determine hasMore
});
const hasMore = posts.length > limit;
if (hasMore) posts.pop();
return { data: posts, meta: { hasMore, nextCursor: encodeCursor(posts.at(-1)) } };
// Offset-based โ only for small datasets where users need page jumping
// GET /api/v1/posts?page=3&limit=20
// โ TRAP: OFFSET 100000 scans and discards 100K rows โ degrades badly at scale
```
---
## Idempotency
```typescript
// POST /api/v1/payments with header: Idempotency-Key: <uuid>
app.post('/api/v1/payments', async (req, res) => {
const key = req.headers['idempotency-key'];
if (!key) return res.status(400).json({ error: 'Missing Idempotency-Key' });
const cached = await redis.get(`idempotency:${key}`);
if (cached) return res.status(200).json(JSON.parse(cached));
const result = await processPayment(req.body);
await redis.set(`idempotency:${key}`, JSON.stringify(result), 'EX', 86400);
return res.status(201).json(result);
});
// GET, PUT, DELETE โ naturally idempotent (safe to retry without a key)
// POST, PATCH โ NOT idempotent by default โ require Idempotency-Key
```
---
## Webhooks
```typescript
// HMAC signature verification (always verify โ never trust unsigned webhooks)
import { createHmac, timingSafeEqual } from 'node:crypto';
function verify(payload: string, signature: string, secret: string): boolean {
const expected = createHmac('sha256', secret).update(payload).digest('hex');
return timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}
app.post('/webhooks', (req, res) => {
if (
!verify(JSON.stringify(req.body), req.headers['x-webhook-signature'] as string, WEBHOOK_SECRET)
)
return res.status(401).send('Invalid signature');
res.status(200).send('OK'); // respond immediately
processWebhookAsync(req.body); // process asynchronously
});
// Retry policy: 3 retries with exponential backoff (1s โ 10s โ 100s)
// Include unique event ID in payload for receiver-side deduplication
```
---
## Versioning
```
URL path (recommended): /api/v1/users โ simplest, most common, cache-friendly
Header: Accept: application/vnd.api.v1+json
Query param: /api/users?version=1 โ messy, avoid
Rules:
- Start at v1, never v0
- Breaking changes = new major version (v2)
- Non-breaking additions (new optional fields) do NOT need a version bump
- Deprecate before removing โ give consumers 6+ months notice
```
---
## Rate Limiting
```
Strategy How When
Token bucket โ Burst allowed, refills Most APIs (recommended)
Sliding window โ Smooth distribution Strict fairness required
Fixed window โ Simple counter per period Basic needs only
Response headers to always include:
X-RateLimit-Limit (max requests in window)
X-RateLimit-Remaining (requests left)
X-RateLimit-Reset (Unix timestamp when limit resets)
Retry-After (seconds to wait on 429)
```
---
## GraphQL Security
```
Protect against:
Depth attacks โ Set max query depth (typically 7โ10)
Cost attacks โ Calculate query complexity score, reject > threshold
Batch abuse โ Limit batch size / alias count
Introspection โ Disable in production (exposes full schema to attackers)
```
---
## Authentication Selection
| Pattern | Best For |
| ----------------------------------------------- | -------------------------------------- |
| **JWT** (short-lived access + httpOnly refresh) | Stateless services, microservices |
| **Session** | Traditional server-rendered apps |
| **OAuth 2.0 / OIDC** | Third-party login, delegated access |
| **API Key** | Server-to-server, public API consumers |
| **Passkey (WebAuthn)** | Modern passwordless (2026+) |
+
+ ## ๐จ Edge-Case & Failure Mode Matrix
+
+ | Scenario | Risk | Production Mitigation |
+ |:---|:---|:---|
+ | **Empty or Null Inputs** | Unhandled exception or unexpected rendering collapse | Enforce fallback guards, optional chaining, and explicit empty state handlers |
+ | **Network Timeout / Latency** | Hanging operations or duplicate side-effects | Implement bounded abort controllers, exponential backoff, and idempotency keys |
+ | **Concurrency / Race Conditions** | Stale state overwrite or inconsistent data mutations | Use atomic transactions, mutex locking, or cancel-on-resubmit controls |
+ | **Invalid Schema / Malformed Payload** | Downstream runtime errors or security injection | Validate boundary payloads with Zod/Pydantic schemas prior to execution |
+ | **Resource / Memory Saturation** | OOM errors, frame drops, or memory leaks | Clean up listeners, cancel active timers, and enforce pagination/virtualization |
+
+
+ ## ๐๏ธ Tribunal Verification & Guardrails
+
+ **Active Reviewers:** `logic-reviewer` ยท `security-auditor` ยท `api-architect` ยท `resilience-reviewer`
+ **Slash Command:** `/review` or `/tribunal-full`
+
+ ### ๐ฌ Evidence Standard (Tri-State Verification)
+ Every finding, audit statement, or completion claim must classify its factual certainty:
+ - **`[OBSERVED]`**: Directly confirmed in the codebase or verified via executed terminal command.
+ - **`[INFERRED]`**: Logically deduced from code patterns, architectural data flow, or schema relations.
+ - **`[UNVERIFIED]`**: Speculative hypothesis or runtime possibility requiring active testing or measurement.
+
+ ### โ
Pre-Flight Self-Audit Checklist
+ ```
+ โ
Are all inputs and boundary payloads validated against schemas (Zod/Pydantic)?
+ โ
Are SQL and database queries parameterized with zero string concatenation?
+ โ
Are error boundaries and timeout/retry policies explicitly declared?
+ โ
Are authentication and object-level authorization (IDOR/BOLA) checked before business logic?
+ โ
Did I verify that imported dependencies exist in package manifests?
+ ```
+
+ ### ๐ Verification-Before-Completion (VBC) Protocol
+ **CRITICAL:** You must follow a strict "evidence-based closeout" state machine.
+ - โ **Forbidden:** Declaring a task complete because the output "looks correct."
+ - โ
**Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing test suites, compiler success, or equivalent operational proof) that your output works as intended.