codeforge-dev 1.7.0 → 1.9.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/.devcontainer/.env +4 -6
- package/.devcontainer/.env.example +29 -0
- package/.devcontainer/.gitignore +8 -0
- package/.devcontainer/.secrets.example +12 -0
- package/.devcontainer/CHANGELOG.md +181 -0
- package/.devcontainer/CLAUDE.md +57 -20
- package/.devcontainer/README.md +111 -56
- package/.devcontainer/config/{main-system-prompt.md → defaults/main-system-prompt.md} +72 -0
- package/.devcontainer/config/defaults/rules/spec-workflow.md +67 -0
- package/.devcontainer/config/defaults/rules/workspace-scope.md +7 -0
- package/.devcontainer/config/defaults/settings.json +67 -0
- package/.devcontainer/config/file-manifest.json +32 -0
- package/.devcontainer/devcontainer.json +20 -0
- package/.devcontainer/docs/configuration-reference.md +90 -0
- package/.devcontainer/docs/keybindings.md +100 -0
- package/.devcontainer/docs/optional-features.md +129 -0
- package/.devcontainer/docs/plugins.md +154 -0
- package/.devcontainer/docs/troubleshooting.md +128 -0
- package/.devcontainer/features/agent-browser/install.sh +6 -0
- package/.devcontainer/features/ast-grep/install.sh +6 -0
- package/.devcontainer/features/biome/README.md +27 -0
- package/.devcontainer/features/biome/install.sh +6 -0
- package/.devcontainer/features/ccburn/install.sh +6 -0
- package/.devcontainer/features/ccstatusline/devcontainer-feature.json +5 -0
- package/.devcontainer/features/ccstatusline/install.sh +7 -0
- package/.devcontainer/features/ccusage/install.sh +6 -0
- package/.devcontainer/features/claude-monitor/install.sh +6 -0
- package/.devcontainer/features/dprint/README.md +30 -0
- package/.devcontainer/features/dprint/devcontainer-feature.json +18 -0
- package/.devcontainer/features/dprint/install.sh +131 -0
- package/.devcontainer/features/hadolint/README.md +35 -0
- package/.devcontainer/features/hadolint/devcontainer-feature.json +13 -0
- package/.devcontainer/features/hadolint/install.sh +86 -0
- package/.devcontainer/features/lsp-servers/devcontainer-feature.json +5 -0
- package/.devcontainer/features/lsp-servers/install.sh +7 -0
- package/.devcontainer/features/mcp-qdrant/devcontainer-feature.json +5 -0
- package/.devcontainer/features/mcp-qdrant/install.sh +13 -6
- package/.devcontainer/features/mcp-reasoner/devcontainer-feature.json +5 -0
- package/.devcontainer/features/mcp-reasoner/install.sh +8 -1
- package/.devcontainer/features/notify-hook/devcontainer-feature.json +5 -0
- package/.devcontainer/features/notify-hook/install.sh +7 -0
- package/.devcontainer/features/ruff/README.md +26 -0
- package/.devcontainer/features/ruff/devcontainer-feature.json +21 -0
- package/.devcontainer/features/ruff/install.sh +74 -0
- package/.devcontainer/features/shellcheck/README.md +38 -0
- package/.devcontainer/features/shellcheck/devcontainer-feature.json +13 -0
- package/.devcontainer/features/shellcheck/install.sh +24 -0
- package/.devcontainer/features/shfmt/README.md +37 -0
- package/.devcontainer/features/shfmt/devcontainer-feature.json +13 -0
- package/.devcontainer/features/shfmt/install.sh +85 -0
- package/.devcontainer/features/splitrail/devcontainer-feature.json +5 -0
- package/.devcontainer/features/splitrail/install.sh +7 -0
- package/.devcontainer/features/tmux/install.sh +8 -0
- package/.devcontainer/features/tree-sitter/install.sh +6 -0
- package/.devcontainer/plugins/devs-marketplace/.claude-plugin/marketplace.json +104 -104
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/README.md +158 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/hooks/hooks.json +39 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/scripts/collect-edited-files.py +47 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/scripts/format-on-stop.py +297 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/scripts/lint-file.py +536 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/scripts/syntax-validator.py +146 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/.claude-plugin/plugin.json +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/__pycache__/format-on-stop.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/format-on-stop.py +114 -9
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/.claude-plugin/plugin.json +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/hooks/hooks.json +4 -5
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/scripts/__pycache__/lint-file.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/scripts/lint-file.py +478 -76
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/.claude-plugin/plugin.json +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/AGENT-REDIRECTION.md +226 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/architect.md +94 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/bash-exec.md +4 -4
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/claude-guide.md +14 -23
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/debug-logs.md +20 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/dependency-analyst.md +20 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/doc-writer.md +99 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/explorer.md +20 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/generalist.md +152 -9
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/git-archaeologist.md +18 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/migrator.md +114 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/perf-profiler.md +24 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/refactorer.md +101 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/researcher.md +33 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/security-auditor.md +24 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/spec-writer.md +65 -24
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/statusline-config.md +3 -3
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/test-writer.md +99 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/hooks/hooks.json +100 -56
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/advisory-test-runner.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/collect-edited-files.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/commit-reminder.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/git-state-injector.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/redirect-builtin-agents.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/ticket-linker.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/todo-harvester.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/advisory-test-runner.py +174 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/collect-edited-files.py +8 -6
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/commit-reminder.py +90 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/git-state-injector.py +114 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/skill-suggester.py +61 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/spec-reminder.py +121 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/ticket-linker.py +137 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/todo-harvester.py +130 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/api-design/SKILL.md +224 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/api-design/references/error-handling.md +166 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/api-design/references/rest-conventions.md +215 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/ast-grep-patterns/SKILL.md +211 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/ast-grep-patterns/references/language-patterns.md +327 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/dependency-management/SKILL.md +134 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/dependency-management/references/ecosystem-commands.md +264 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/dependency-management/references/license-compliance.md +80 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/documentation-patterns/SKILL.md +153 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/documentation-patterns/references/api-doc-templates.md +221 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/documentation-patterns/references/docstring-formats.md +296 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/migration-patterns/SKILL.md +150 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/migration-patterns/references/javascript-migrations.md +179 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/migration-patterns/references/python-migrations.md +141 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-check/SKILL.md +86 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-init/SKILL.md +97 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-init/references/backlog-template.md +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-init/references/roadmap-template.md +13 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-new/SKILL.md +101 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-new/references/template.md +110 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-update/SKILL.md +124 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/specification-writing/SKILL.md +32 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/scripts/__pycache__/block-dangerous.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/notify-hook/hooks/hooks.json +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/__pycache__/guard-protected.cpython-314.pyc +0 -0
- package/.devcontainer/scripts/check-setup.sh +72 -0
- package/.devcontainer/scripts/setup-aliases.sh +43 -3
- package/.devcontainer/scripts/setup-auth.sh +74 -0
- package/.devcontainer/scripts/setup-config.sh +117 -24
- package/.devcontainer/scripts/setup-update-claude.sh +8 -0
- package/.devcontainer/scripts/setup.sh +46 -13
- package/README.md +23 -190
- package/package.json +42 -42
- package/setup.js +245 -71
- package/.devcontainer/config/settings.json +0 -70
- package/.devcontainer/features/claude-code/README.md +0 -498
- package/.devcontainer/features/claude-code/config/settings.json +0 -72
- package/.devcontainer/features/claude-code/config/system-prompt.md +0 -118
- package/.devcontainer/features/claude-code/config/world-building-sp.md +0 -1432
- package/.devcontainer/features/claude-code/devcontainer-feature.json +0 -42
- package/.devcontainer/features/claude-code/install.sh +0 -466
- package/.devcontainer/plugins/devs-marketplace/plugins/planning-reminder/.claude-plugin/plugin.json +0 -7
- package/.devcontainer/plugins/devs-marketplace/plugins/planning-reminder/hooks/hooks.json +0 -17
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/.claude-plugin/plugin.json +0 -6
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/config/planning-instructions.md +0 -14
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/functional-conjuring-map.md +0 -989
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/hooks/hooks.json +0 -33
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/__pycache__/post-enhance-task.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhance-planning.py +0 -71
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhancers/enhance-plan.sh +0 -68
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhancers/enhance-task.sh +0 -120
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/post-enhance-plan.py +0 -133
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/post-enhance-task.py +0 -253
- /package/.devcontainer/config/{keybindings.json → defaults/keybindings.json} +0 -0
package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/api-design/SKILL.md
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: api-design
|
|
3
|
+
description: >-
|
|
4
|
+
This skill should be used when the user asks to "design an API",
|
|
5
|
+
"design REST endpoints", "plan API versioning", "choose pagination strategy",
|
|
6
|
+
"design error responses", "API conventions", "endpoint design",
|
|
7
|
+
"create API documentation", or discusses REST API design, HTTP method
|
|
8
|
+
semantics, status code selection, authentication patterns, or rate limiting.
|
|
9
|
+
version: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# API Design
|
|
13
|
+
|
|
14
|
+
## Mental Model
|
|
15
|
+
|
|
16
|
+
APIs are **contracts**. Once published, they are promises to consumers. Design for the consumer, not the implementation. Consistency beats cleverness — a predictable API with simple conventions is easier to use than a clever API with special cases.
|
|
17
|
+
|
|
18
|
+
**Key principles:**
|
|
19
|
+
- **Resources, not actions.** URLs name things (`/users`, `/orders`), HTTP methods express actions (GET, POST, PUT, DELETE). Verbs in URLs signal a design problem.
|
|
20
|
+
- **Consistency above all.** If one endpoint uses `snake_case`, all endpoints use `snake_case`. If one endpoint paginates with `cursor`, all endpoints paginate with `cursor`.
|
|
21
|
+
- **Explicit over implicit.** Document every behavior. Default values, sort orders, pagination limits — if a consumer has to guess, the API is underspecified.
|
|
22
|
+
- **Idempotency by design.** GET, PUT, DELETE are idempotent. POST creates new resources. Design operations so repeating a request does not produce unexpected side effects.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Resource Naming
|
|
27
|
+
|
|
28
|
+
Use plural nouns for collections, singular identifiers for individual resources:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
GET /users → List users
|
|
32
|
+
POST /users → Create a user
|
|
33
|
+
GET /users/{id} → Get a specific user
|
|
34
|
+
PUT /users/{id} → Replace a user
|
|
35
|
+
PATCH /users/{id} → Partially update a user
|
|
36
|
+
DELETE /users/{id} → Delete a user
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Nested resources** for clear ownership:
|
|
40
|
+
```
|
|
41
|
+
GET /users/{id}/orders → List orders for a user
|
|
42
|
+
POST /users/{id}/orders → Create an order for a user
|
|
43
|
+
GET /users/{id}/orders/{oid} → Get a specific order
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Limit nesting to 2 levels. Beyond that, promote the resource to a top-level endpoint with a query filter: `/orders?user_id=123`.
|
|
47
|
+
|
|
48
|
+
**Naming rules:**
|
|
49
|
+
- Use `kebab-case` for multi-word paths: `/order-items`, not `/orderItems`
|
|
50
|
+
- Use `snake_case` for query parameters: `?sort_by=created_at`
|
|
51
|
+
- Use `snake_case` for JSON fields (aligns with Python/Ruby; for JavaScript-heavy APIs, `camelCase` is also acceptable — pick one and be consistent)
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## HTTP Method Semantics
|
|
56
|
+
|
|
57
|
+
| Method | Purpose | Idempotent | Request Body | Success Code |
|
|
58
|
+
|--------|---------|-----------|-------------|-------------|
|
|
59
|
+
| **GET** | Read resource(s) | Yes | No | 200 |
|
|
60
|
+
| **POST** | Create resource | No | Yes | 201 |
|
|
61
|
+
| **PUT** | Full replace | Yes | Yes | 200 |
|
|
62
|
+
| **PATCH** | Partial update | No* | Yes | 200 |
|
|
63
|
+
| **DELETE** | Remove resource | Yes | No | 204 |
|
|
64
|
+
| **HEAD** | Headers only (like GET) | Yes | No | 200 |
|
|
65
|
+
| **OPTIONS** | Describe capabilities | Yes | No | 204 |
|
|
66
|
+
|
|
67
|
+
*PATCH is idempotent if using JSON Merge Patch; not idempotent with JSON Patch operations.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Pagination Patterns
|
|
72
|
+
|
|
73
|
+
### Cursor-Based (Recommended)
|
|
74
|
+
|
|
75
|
+
Best for real-time data, large datasets, and stable traversal:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
GET /users?cursor=eyJpZCI6MTIzfQ&limit=20
|
|
79
|
+
|
|
80
|
+
{
|
|
81
|
+
"data": [...],
|
|
82
|
+
"pagination": {
|
|
83
|
+
"next_cursor": "eyJpZCI6MTQzfQ",
|
|
84
|
+
"has_more": true
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Cursors are opaque tokens (base64-encoded state). Consumers pass them back unchanged.
|
|
90
|
+
|
|
91
|
+
### Offset-Based
|
|
92
|
+
|
|
93
|
+
Simpler but unstable under concurrent writes:
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
GET /users?offset=40&limit=20
|
|
97
|
+
|
|
98
|
+
{
|
|
99
|
+
"data": [...],
|
|
100
|
+
"pagination": {
|
|
101
|
+
"offset": 40,
|
|
102
|
+
"limit": 20,
|
|
103
|
+
"total": 156
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Decision Framework
|
|
109
|
+
|
|
110
|
+
| Factor | Cursor | Offset |
|
|
111
|
+
|--------|--------|--------|
|
|
112
|
+
| Data stability | Handles inserts/deletes during pagination | Rows shift when data changes |
|
|
113
|
+
| Performance at scale | O(1) per page | O(n) for large offsets |
|
|
114
|
+
| "Jump to page N" | Not supported | Supported |
|
|
115
|
+
| Implementation complexity | Higher | Lower |
|
|
116
|
+
|
|
117
|
+
**Default**: Cursor pagination for new APIs. Offset only when consumers explicitly need page-number navigation.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Versioning
|
|
122
|
+
|
|
123
|
+
### URL Path Versioning (Recommended)
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
/v1/users
|
|
127
|
+
/v2/users
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Visible in every request. Easy to route, test, and document. Most widely understood.
|
|
131
|
+
|
|
132
|
+
### Header Versioning
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
Accept: application/vnd.api+json; version=2
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Cleaner URLs but harder to test (can't bookmark/share versioned URLs) and harder to route.
|
|
139
|
+
|
|
140
|
+
### Decision Framework
|
|
141
|
+
|
|
142
|
+
| Factor | URL Path | Header |
|
|
143
|
+
|--------|----------|--------|
|
|
144
|
+
| Discoverability | High — visible in URL | Low — hidden in headers |
|
|
145
|
+
| Cacheability | Easy — URL-based caching | Requires Vary header |
|
|
146
|
+
| Testing | Easy — curl/browser | Requires setting headers |
|
|
147
|
+
| Aesthetics | "Ugly" URLs | Clean URLs |
|
|
148
|
+
|
|
149
|
+
**Default**: URL path versioning. It is the most pragmatic choice for most APIs.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Authentication Patterns
|
|
154
|
+
|
|
155
|
+
| Pattern | Best For | Considerations |
|
|
156
|
+
|---------|----------|---------------|
|
|
157
|
+
| **API Keys** | Server-to-server, simple integrations | Easy to implement. No expiry by default — rotate regularly. Send via header (`X-API-Key` or `Authorization: Bearer`), never in URL. |
|
|
158
|
+
| **JWT (Bearer Tokens)** | Stateless auth, microservices | Self-contained claims. Set short expiry (15-60 min) + refresh tokens. Verify signature and expiry on every request. |
|
|
159
|
+
| **OAuth 2.0** | Third-party integrations, user consent | Authorization Code flow for web apps, Client Credentials for machine-to-machine. Use PKCE for public clients. |
|
|
160
|
+
| **Session Cookies** | Browser-based web apps | Set `HttpOnly`, `Secure`, `SameSite=Strict`. CSRF protection required. |
|
|
161
|
+
|
|
162
|
+
**Default**: JWT for APIs consumed by multiple clients. API keys for simple server-to-server integrations.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Rate Limiting
|
|
167
|
+
|
|
168
|
+
### Token Bucket (Recommended)
|
|
169
|
+
|
|
170
|
+
Allows bursts up to bucket size, then enforces sustained rate:
|
|
171
|
+
- Bucket holds N tokens (e.g., 100)
|
|
172
|
+
- Tokens refill at R per second (e.g., 10/s)
|
|
173
|
+
- Each request costs 1 token (or more for expensive operations)
|
|
174
|
+
|
|
175
|
+
### Response Headers
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
X-RateLimit-Limit: 100
|
|
179
|
+
X-RateLimit-Remaining: 42
|
|
180
|
+
X-RateLimit-Reset: 1640000000
|
|
181
|
+
Retry-After: 30
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Return `429 Too Many Requests` with `Retry-After` header when limit is exceeded.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## API Design Checklist
|
|
189
|
+
|
|
190
|
+
Before implementing, verify:
|
|
191
|
+
|
|
192
|
+
- [ ] Every endpoint uses a plural noun (not a verb) in the URL
|
|
193
|
+
- [ ] HTTP methods match their semantic purpose
|
|
194
|
+
- [ ] Response format is consistent across all endpoints
|
|
195
|
+
- [ ] Error responses follow a standard format (see reference)
|
|
196
|
+
- [ ] Pagination strategy is consistent across all list endpoints
|
|
197
|
+
- [ ] Authentication mechanism is documented
|
|
198
|
+
- [ ] Rate limits are defined and communicated via headers
|
|
199
|
+
- [ ] Versioning strategy is chosen and applied
|
|
200
|
+
- [ ] All parameters have documented types, constraints, and defaults
|
|
201
|
+
- [ ] Idempotency behavior is documented for each endpoint
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Ambiguity Policy
|
|
206
|
+
|
|
207
|
+
| Ambiguity | Default |
|
|
208
|
+
|-----------|---------|
|
|
209
|
+
| **API style** | REST with JSON request/response bodies |
|
|
210
|
+
| **Pagination** | Cursor-based with `limit` parameter (default 20, max 100) |
|
|
211
|
+
| **Versioning** | URL path versioning (`/v1/`) |
|
|
212
|
+
| **Naming convention** | `snake_case` for JSON fields, `kebab-case` for URL paths |
|
|
213
|
+
| **Auth pattern** | JWT Bearer tokens (unless server-to-server, then API keys) |
|
|
214
|
+
| **Error format** | RFC 7807 Problem Details |
|
|
215
|
+
| **Rate limiting** | Token bucket with standard headers |
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Reference Files
|
|
220
|
+
|
|
221
|
+
| File | Contents |
|
|
222
|
+
|------|----------|
|
|
223
|
+
| [REST Conventions](references/rest-conventions.md) | Complete HTTP method semantics, status code reference by category, resource naming examples, query parameter patterns, content negotiation, and HATEOAS guidance |
|
|
224
|
+
| [Error Handling](references/error-handling.md) | RFC 7807 Problem Details format, error code taxonomy, consistency rules, client-vs-server error exposure, and retry guidance headers |
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# API Error Handling Reference
|
|
2
|
+
|
|
3
|
+
## RFC 7807 Problem Details
|
|
4
|
+
|
|
5
|
+
The standard format for HTTP API error responses. Use `application/problem+json` as the content type.
|
|
6
|
+
|
|
7
|
+
### Format
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"type": "https://api.example.com/errors/validation-error",
|
|
12
|
+
"title": "Validation Error",
|
|
13
|
+
"status": 422,
|
|
14
|
+
"detail": "The 'email' field must be a valid email address.",
|
|
15
|
+
"instance": "/users/signup",
|
|
16
|
+
"errors": [
|
|
17
|
+
{
|
|
18
|
+
"field": "email",
|
|
19
|
+
"message": "Must be a valid email address",
|
|
20
|
+
"value": "not-an-email"
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Fields
|
|
27
|
+
|
|
28
|
+
| Field | Required | Description |
|
|
29
|
+
|-------|----------|-------------|
|
|
30
|
+
| `type` | Yes | URI reference identifying the error type. Use a stable URL (can be a documentation page). |
|
|
31
|
+
| `title` | Yes | Short human-readable summary. Same for all instances of this error type. |
|
|
32
|
+
| `status` | Yes | HTTP status code (repeated from response for convenience). |
|
|
33
|
+
| `detail` | Yes | Human-readable explanation specific to this occurrence. |
|
|
34
|
+
| `instance` | No | URI identifying the specific occurrence (request path or trace ID). |
|
|
35
|
+
|
|
36
|
+
Extension fields (like `errors` for validation) are allowed and encouraged for structured detail.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Error Code Taxonomy
|
|
41
|
+
|
|
42
|
+
Organize errors into categories with consistent type URIs:
|
|
43
|
+
|
|
44
|
+
### Validation Errors (400 / 422)
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"type": "https://api.example.com/errors/validation-error",
|
|
49
|
+
"title": "Validation Error",
|
|
50
|
+
"status": 422,
|
|
51
|
+
"detail": "Request body contains invalid fields.",
|
|
52
|
+
"errors": [
|
|
53
|
+
{ "field": "email", "message": "Required field is missing" },
|
|
54
|
+
{ "field": "age", "message": "Must be a positive integer", "value": -5 }
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Use `422` for semantic validation failures (valid JSON but invalid data). Use `400` for malformed requests (invalid JSON, wrong content type).
|
|
60
|
+
|
|
61
|
+
### Authentication Errors (401)
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"type": "https://api.example.com/errors/authentication-required",
|
|
66
|
+
"title": "Authentication Required",
|
|
67
|
+
"status": 401,
|
|
68
|
+
"detail": "The access token has expired. Request a new token."
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Always include `WWW-Authenticate` header with 401 responses.
|
|
73
|
+
|
|
74
|
+
### Authorization Errors (403)
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"type": "https://api.example.com/errors/insufficient-permissions",
|
|
79
|
+
"title": "Insufficient Permissions",
|
|
80
|
+
"status": 403,
|
|
81
|
+
"detail": "Your API key does not have access to the 'admin' scope."
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Not Found (404)
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"type": "https://api.example.com/errors/resource-not-found",
|
|
90
|
+
"title": "Resource Not Found",
|
|
91
|
+
"status": 404,
|
|
92
|
+
"detail": "No user found with ID '999'."
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Conflict (409)
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"type": "https://api.example.com/errors/resource-conflict",
|
|
101
|
+
"title": "Resource Conflict",
|
|
102
|
+
"status": 409,
|
|
103
|
+
"detail": "A user with email 'jane@example.com' already exists."
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Rate Limit (429)
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"type": "https://api.example.com/errors/rate-limit-exceeded",
|
|
112
|
+
"title": "Rate Limit Exceeded",
|
|
113
|
+
"status": 429,
|
|
114
|
+
"detail": "You have exceeded 100 requests per minute. Try again in 30 seconds."
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Always include `Retry-After` header (seconds or HTTP-date).
|
|
119
|
+
|
|
120
|
+
### Internal Error (500)
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"type": "https://api.example.com/errors/internal-error",
|
|
125
|
+
"title": "Internal Server Error",
|
|
126
|
+
"status": 500,
|
|
127
|
+
"detail": "An unexpected error occurred. Reference: trace-abc123."
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Error Response Consistency Rules
|
|
134
|
+
|
|
135
|
+
1. **Same shape, always.** Every error response uses the same top-level structure. Consumers should never need to handle different error formats.
|
|
136
|
+
2. **Match status code to error.** The `status` field in the body matches the HTTP status code. Never return `200 OK` with an error body.
|
|
137
|
+
3. **Human-readable details.** The `detail` field should help the consumer fix the problem. "Invalid request" is useless. "The 'email' field must be a valid email address" is actionable.
|
|
138
|
+
4. **Machine-readable type.** The `type` URI enables programmatic error handling. Consumers can switch on the type without parsing the detail string.
|
|
139
|
+
5. **No stack traces in production.** Internal error details (stack traces, database errors, internal paths) are logged server-side. Clients receive a reference ID to correlate with server logs.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Error Logging vs. Error Exposure
|
|
144
|
+
|
|
145
|
+
| Information | Log Server-Side | Return to Client |
|
|
146
|
+
|-------------|----------------|-----------------|
|
|
147
|
+
| Stack trace | Yes | No |
|
|
148
|
+
| Database error messages | Yes | No |
|
|
149
|
+
| Internal file paths | Yes | No |
|
|
150
|
+
| Request ID / trace ID | Yes | Yes (in `instance` or `detail`) |
|
|
151
|
+
| Validation errors | Yes | Yes (specific field-level errors) |
|
|
152
|
+
| Rate limit status | Yes | Yes (via headers + body) |
|
|
153
|
+
| Business rule violations | Yes | Yes (as actionable `detail`) |
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Retry Guidance Headers
|
|
158
|
+
|
|
159
|
+
| Header | Purpose | Format |
|
|
160
|
+
|--------|---------|--------|
|
|
161
|
+
| `Retry-After` | When to retry after 429 or 503 | Seconds (`30`) or HTTP-date (`Wed, 21 Oct 2025 07:28:00 GMT`) |
|
|
162
|
+
| `X-RateLimit-Limit` | Maximum requests allowed in window | Integer (`100`) |
|
|
163
|
+
| `X-RateLimit-Remaining` | Requests remaining in current window | Integer (`42`) |
|
|
164
|
+
| `X-RateLimit-Reset` | Unix timestamp when window resets | Integer (`1640000000`) |
|
|
165
|
+
|
|
166
|
+
Include all rate limit headers on **every response** (not just 429s) so clients can proactively manage their request rate.
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# REST Conventions Reference
|
|
2
|
+
|
|
3
|
+
## HTTP Method Semantics
|
|
4
|
+
|
|
5
|
+
### GET — Read Resources
|
|
6
|
+
|
|
7
|
+
- Retrieves a resource or collection. Never modifies state.
|
|
8
|
+
- **Cacheable** by default. Use `Cache-Control` and `ETag` headers.
|
|
9
|
+
- Collection: `GET /users` → `200 OK` with array
|
|
10
|
+
- Single: `GET /users/123` → `200 OK` with object, or `404 Not Found`
|
|
11
|
+
|
|
12
|
+
### POST — Create Resources
|
|
13
|
+
|
|
14
|
+
- Creates a new resource. The server assigns the ID.
|
|
15
|
+
- **Not idempotent** — repeating the request creates duplicate resources.
|
|
16
|
+
- Response: `201 Created` with `Location` header pointing to the new resource.
|
|
17
|
+
- Include the created resource in the response body.
|
|
18
|
+
|
|
19
|
+
### PUT — Full Replace
|
|
20
|
+
|
|
21
|
+
- Replaces the entire resource. Client sends the complete representation.
|
|
22
|
+
- **Idempotent** — repeating the request produces the same state.
|
|
23
|
+
- If the resource doesn't exist: return `404` (don't auto-create unless designed for upsert).
|
|
24
|
+
- Response: `200 OK` with the updated resource.
|
|
25
|
+
|
|
26
|
+
### PATCH — Partial Update
|
|
27
|
+
|
|
28
|
+
- Modifies specific fields without replacing the entire resource.
|
|
29
|
+
- Use JSON Merge Patch (`Content-Type: application/merge-patch+json`) for simplicity.
|
|
30
|
+
- Response: `200 OK` with the complete updated resource.
|
|
31
|
+
- Omitted fields remain unchanged.
|
|
32
|
+
|
|
33
|
+
### DELETE — Remove Resources
|
|
34
|
+
|
|
35
|
+
- Removes a resource.
|
|
36
|
+
- **Idempotent** — deleting an already-deleted resource returns `204` or `404` (both are valid, be consistent).
|
|
37
|
+
- Response: `204 No Content` (no body).
|
|
38
|
+
|
|
39
|
+
### HEAD — Headers Only
|
|
40
|
+
|
|
41
|
+
- Identical to GET but returns no body. Used for checking existence, content length, or cache validity.
|
|
42
|
+
|
|
43
|
+
### OPTIONS — Capabilities
|
|
44
|
+
|
|
45
|
+
- Returns allowed methods and CORS headers. Response: `204 No Content` with `Allow` header.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Status Code Reference
|
|
50
|
+
|
|
51
|
+
### 2xx — Success
|
|
52
|
+
|
|
53
|
+
| Code | Name | When to Use |
|
|
54
|
+
|------|------|------------|
|
|
55
|
+
| `200` | OK | GET, PUT, PATCH succeeded. General success. |
|
|
56
|
+
| `201` | Created | POST created a resource. Include `Location` header. |
|
|
57
|
+
| `202` | Accepted | Request accepted for async processing. Include status URL. |
|
|
58
|
+
| `204` | No Content | DELETE succeeded. OPTIONS response. No body. |
|
|
59
|
+
|
|
60
|
+
### 3xx — Redirection
|
|
61
|
+
|
|
62
|
+
| Code | Name | When to Use |
|
|
63
|
+
|------|------|------------|
|
|
64
|
+
| `301` | Moved Permanently | Resource URL changed permanently. Clients should update. |
|
|
65
|
+
| `302` | Found | Temporary redirect. Original URL still valid. |
|
|
66
|
+
| `304` | Not Modified | Cache is still valid. Response to conditional GET. |
|
|
67
|
+
|
|
68
|
+
### 4xx — Client Errors
|
|
69
|
+
|
|
70
|
+
| Code | Name | When to Use |
|
|
71
|
+
|------|------|------------|
|
|
72
|
+
| `400` | Bad Request | Malformed syntax, invalid JSON, missing required fields. |
|
|
73
|
+
| `401` | Unauthorized | No credentials or invalid/expired credentials. |
|
|
74
|
+
| `403` | Forbidden | Valid credentials but insufficient permissions. |
|
|
75
|
+
| `404` | Not Found | Resource doesn't exist. |
|
|
76
|
+
| `405` | Method Not Allowed | HTTP method not supported for this URL. Include `Allow` header. |
|
|
77
|
+
| `409` | Conflict | State conflict (duplicate, version mismatch, concurrent modification). |
|
|
78
|
+
| `410` | Gone | Resource existed but was permanently deleted. |
|
|
79
|
+
| `415` | Unsupported Media Type | Content-Type not supported. |
|
|
80
|
+
| `422` | Unprocessable Entity | Valid syntax but semantic errors (validation failures). |
|
|
81
|
+
| `429` | Too Many Requests | Rate limit exceeded. Include `Retry-After` header. |
|
|
82
|
+
|
|
83
|
+
### 5xx — Server Errors
|
|
84
|
+
|
|
85
|
+
| Code | Name | When to Use |
|
|
86
|
+
|------|------|------------|
|
|
87
|
+
| `500` | Internal Server Error | Unhandled exception. Log the error, return generic message. |
|
|
88
|
+
| `502` | Bad Gateway | Upstream service returned invalid response. |
|
|
89
|
+
| `503` | Service Unavailable | Server overloaded or in maintenance. Include `Retry-After`. |
|
|
90
|
+
| `504` | Gateway Timeout | Upstream service did not respond in time. |
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Resource Naming Conventions
|
|
95
|
+
|
|
96
|
+
### Collection Patterns
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
/users → User collection
|
|
100
|
+
/users/{id} → Specific user
|
|
101
|
+
/users/{id}/orders → Orders belonging to a user
|
|
102
|
+
/users/{id}/orders/{oid} → Specific order of a user
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Naming Rules
|
|
106
|
+
|
|
107
|
+
- **Plural nouns** for collections: `/users`, not `/user`
|
|
108
|
+
- **Lowercase with hyphens** for multi-word: `/order-items`, not `/orderItems` or `/order_items`
|
|
109
|
+
- **No trailing slashes**: `/users`, not `/users/`
|
|
110
|
+
- **No file extensions**: `/users/123`, not `/users/123.json`
|
|
111
|
+
- **No verbs**: `/users/{id}/activate` is acceptable as an action endpoint (RPC-style), but prefer state changes via PATCH when possible
|
|
112
|
+
|
|
113
|
+
### Action Endpoints (RPC-Style)
|
|
114
|
+
|
|
115
|
+
When a RESTful mapping is awkward, use action sub-resources:
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
POST /users/{id}/activate → Activate a user
|
|
119
|
+
POST /orders/{id}/cancel → Cancel an order
|
|
120
|
+
POST /emails/{id}/resend → Resend an email
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Action endpoints are always POST (they change state and are not idempotent).
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Query Parameter Patterns
|
|
128
|
+
|
|
129
|
+
### Filtering
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
GET /users?status=active
|
|
133
|
+
GET /users?role=admin&status=active
|
|
134
|
+
GET /orders?created_after=2024-01-01&created_before=2024-12-31
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Use `snake_case` for parameter names. Support multiple values with comma separation or repeated params:
|
|
138
|
+
```
|
|
139
|
+
GET /users?role=admin,editor (comma-separated)
|
|
140
|
+
GET /users?role=admin&role=editor (repeated)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Sorting
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
GET /users?sort_by=created_at&sort_order=desc
|
|
147
|
+
GET /users?sort=-created_at,name (prefix - for descending)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Field Selection
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
GET /users?fields=id,name,email
|
|
154
|
+
GET /users/{id}?fields=id,name,email,orders
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Reduces payload size. Particularly valuable for mobile clients or list views.
|
|
158
|
+
|
|
159
|
+
### Search
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
GET /users?q=john (full-text search)
|
|
163
|
+
GET /users?name_contains=john (field-specific search)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Content Negotiation
|
|
169
|
+
|
|
170
|
+
### Request Headers
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
Content-Type: application/json → Request body format
|
|
174
|
+
Accept: application/json → Desired response format
|
|
175
|
+
Accept-Language: en-US → Preferred language
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Response Headers
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
Content-Type: application/json; charset=utf-8
|
|
182
|
+
Content-Length: 1234
|
|
183
|
+
ETag: "abc123"
|
|
184
|
+
Cache-Control: max-age=3600
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Versioned Media Types
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
Accept: application/vnd.myapi.v2+json
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
An alternative to URL path versioning. The server reads the Accept header to determine which version to serve.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## HATEOAS (Hypermedia)
|
|
198
|
+
|
|
199
|
+
Include links to related resources and actions in responses:
|
|
200
|
+
|
|
201
|
+
```json
|
|
202
|
+
{
|
|
203
|
+
"id": 123,
|
|
204
|
+
"name": "Jane Doe",
|
|
205
|
+
"links": {
|
|
206
|
+
"self": "/users/123",
|
|
207
|
+
"orders": "/users/123/orders",
|
|
208
|
+
"activate": "/users/123/activate"
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**When it is worth it**: Public APIs consumed by many third-party clients. The links enable discoverability without hardcoding URL patterns.
|
|
214
|
+
|
|
215
|
+
**When it is over-engineering**: Internal APIs where clients are maintained by the same team. The added payload and complexity rarely justify the benefit.
|