codeforge-dev 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/.devcontainer/.env +4 -6
  2. package/.devcontainer/.env.example +29 -0
  3. package/.devcontainer/.gitignore +8 -0
  4. package/.devcontainer/.secrets.example +12 -0
  5. package/.devcontainer/CHANGELOG.md +130 -0
  6. package/.devcontainer/CLAUDE.md +56 -19
  7. package/.devcontainer/README.md +111 -56
  8. package/.devcontainer/config/{main-system-prompt.md → defaults/main-system-prompt.md} +72 -0
  9. package/.devcontainer/config/file-manifest.json +20 -0
  10. package/.devcontainer/devcontainer.json +20 -0
  11. package/.devcontainer/docs/configuration-reference.md +90 -0
  12. package/.devcontainer/docs/keybindings.md +100 -0
  13. package/.devcontainer/docs/optional-features.md +129 -0
  14. package/.devcontainer/docs/plugins.md +154 -0
  15. package/.devcontainer/docs/troubleshooting.md +128 -0
  16. package/.devcontainer/features/agent-browser/install.sh +6 -0
  17. package/.devcontainer/features/ast-grep/install.sh +6 -0
  18. package/.devcontainer/features/biome/README.md +27 -0
  19. package/.devcontainer/features/biome/install.sh +6 -0
  20. package/.devcontainer/features/ccburn/install.sh +6 -0
  21. package/.devcontainer/features/ccstatusline/devcontainer-feature.json +5 -0
  22. package/.devcontainer/features/ccstatusline/install.sh +7 -0
  23. package/.devcontainer/features/ccusage/install.sh +6 -0
  24. package/.devcontainer/features/claude-monitor/install.sh +6 -0
  25. package/.devcontainer/features/dprint/README.md +30 -0
  26. package/.devcontainer/features/dprint/devcontainer-feature.json +18 -0
  27. package/.devcontainer/features/dprint/install.sh +131 -0
  28. package/.devcontainer/features/hadolint/README.md +35 -0
  29. package/.devcontainer/features/hadolint/devcontainer-feature.json +13 -0
  30. package/.devcontainer/features/hadolint/install.sh +86 -0
  31. package/.devcontainer/features/lsp-servers/devcontainer-feature.json +5 -0
  32. package/.devcontainer/features/lsp-servers/install.sh +7 -0
  33. package/.devcontainer/features/mcp-qdrant/devcontainer-feature.json +5 -0
  34. package/.devcontainer/features/mcp-qdrant/install.sh +13 -6
  35. package/.devcontainer/features/mcp-reasoner/devcontainer-feature.json +5 -0
  36. package/.devcontainer/features/mcp-reasoner/install.sh +8 -1
  37. package/.devcontainer/features/notify-hook/devcontainer-feature.json +5 -0
  38. package/.devcontainer/features/notify-hook/install.sh +7 -0
  39. package/.devcontainer/features/ruff/README.md +26 -0
  40. package/.devcontainer/features/ruff/devcontainer-feature.json +21 -0
  41. package/.devcontainer/features/ruff/install.sh +74 -0
  42. package/.devcontainer/features/shellcheck/README.md +38 -0
  43. package/.devcontainer/features/shellcheck/devcontainer-feature.json +13 -0
  44. package/.devcontainer/features/shellcheck/install.sh +24 -0
  45. package/.devcontainer/features/shfmt/README.md +37 -0
  46. package/.devcontainer/features/shfmt/devcontainer-feature.json +13 -0
  47. package/.devcontainer/features/shfmt/install.sh +85 -0
  48. package/.devcontainer/features/splitrail/devcontainer-feature.json +5 -0
  49. package/.devcontainer/features/splitrail/install.sh +7 -0
  50. package/.devcontainer/features/tmux/install.sh +8 -0
  51. package/.devcontainer/features/tree-sitter/install.sh +6 -0
  52. package/.devcontainer/plugins/devs-marketplace/.claude-plugin/marketplace.json +3 -10
  53. package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/.claude-plugin/plugin.json +1 -1
  54. package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/__pycache__/format-on-stop.cpython-314.pyc +0 -0
  55. package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/format-on-stop.py +114 -9
  56. package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/.claude-plugin/plugin.json +1 -1
  57. package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/hooks/hooks.json +4 -5
  58. package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/scripts/__pycache__/lint-file.cpython-314.pyc +0 -0
  59. package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/scripts/lint-file.py +478 -76
  60. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/.claude-plugin/plugin.json +1 -1
  61. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/AGENT-REDIRECTION.md +226 -0
  62. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/architect.md +17 -0
  63. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/bash-exec.md +4 -4
  64. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/claude-guide.md +14 -23
  65. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/debug-logs.md +2 -0
  66. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/dependency-analyst.md +2 -0
  67. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/doc-writer.md +13 -0
  68. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/explorer.md +2 -0
  69. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/generalist.md +10 -1
  70. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/migrator.md +6 -0
  71. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/refactorer.md +4 -0
  72. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/spec-writer.md +36 -23
  73. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/statusline-config.md +3 -3
  74. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/test-writer.md +3 -0
  75. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/hooks/hooks.json +39 -0
  76. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/advisory-test-runner.cpython-314.pyc +0 -0
  77. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/collect-edited-files.cpython-314.pyc +0 -0
  78. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/commit-reminder.cpython-314.pyc +0 -0
  79. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/git-state-injector.cpython-314.pyc +0 -0
  80. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/redirect-builtin-agents.cpython-314.pyc +0 -0
  81. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/ticket-linker.cpython-314.pyc +0 -0
  82. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/todo-harvester.cpython-314.pyc +0 -0
  83. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/advisory-test-runner.py +174 -0
  84. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/collect-edited-files.py +8 -6
  85. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/commit-reminder.py +90 -0
  86. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/git-state-injector.py +114 -0
  87. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/skill-suggester.py +61 -0
  88. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/ticket-linker.py +137 -0
  89. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/todo-harvester.py +130 -0
  90. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/api-design/SKILL.md +224 -0
  91. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/api-design/references/error-handling.md +166 -0
  92. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/api-design/references/rest-conventions.md +215 -0
  93. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/ast-grep-patterns/SKILL.md +211 -0
  94. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/ast-grep-patterns/references/language-patterns.md +327 -0
  95. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/dependency-management/SKILL.md +134 -0
  96. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/dependency-management/references/ecosystem-commands.md +264 -0
  97. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/dependency-management/references/license-compliance.md +80 -0
  98. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/documentation-patterns/SKILL.md +153 -0
  99. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/documentation-patterns/references/api-doc-templates.md +221 -0
  100. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/documentation-patterns/references/docstring-formats.md +296 -0
  101. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/migration-patterns/SKILL.md +150 -0
  102. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/migration-patterns/references/javascript-migrations.md +179 -0
  103. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/migration-patterns/references/python-migrations.md +141 -0
  104. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/specification-writing/SKILL.md +32 -0
  105. package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/scripts/__pycache__/block-dangerous.cpython-314.pyc +0 -0
  106. package/.devcontainer/plugins/devs-marketplace/plugins/notify-hook/hooks/hooks.json +1 -1
  107. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/__pycache__/guard-protected.cpython-314.pyc +0 -0
  108. package/.devcontainer/scripts/check-setup.sh +72 -0
  109. package/.devcontainer/scripts/setup-aliases.sh +43 -3
  110. package/.devcontainer/scripts/setup-auth.sh +74 -0
  111. package/.devcontainer/scripts/setup-config.sh +112 -22
  112. package/.devcontainer/scripts/setup-update-claude.sh +8 -0
  113. package/.devcontainer/scripts/setup.sh +46 -13
  114. package/README.md +23 -190
  115. package/package.json +1 -1
  116. package/setup.js +245 -71
  117. package/.devcontainer/features/claude-code/README.md +0 -498
  118. package/.devcontainer/features/claude-code/config/settings.json +0 -72
  119. package/.devcontainer/features/claude-code/config/system-prompt.md +0 -118
  120. package/.devcontainer/features/claude-code/config/world-building-sp.md +0 -1432
  121. package/.devcontainer/features/claude-code/devcontainer-feature.json +0 -42
  122. package/.devcontainer/features/claude-code/install.sh +0 -466
  123. package/.devcontainer/plugins/devs-marketplace/plugins/planning-reminder/.claude-plugin/plugin.json +0 -7
  124. package/.devcontainer/plugins/devs-marketplace/plugins/planning-reminder/hooks/hooks.json +0 -17
  125. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/.claude-plugin/plugin.json +0 -6
  126. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/config/planning-instructions.md +0 -14
  127. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/functional-conjuring-map.md +0 -989
  128. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/hooks/hooks.json +0 -33
  129. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/__pycache__/post-enhance-task.cpython-314.pyc +0 -0
  130. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhance-planning.py +0 -71
  131. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhancers/enhance-plan.sh +0 -68
  132. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhancers/enhance-task.sh +0 -120
  133. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/post-enhance-plan.py +0 -133
  134. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/post-enhance-task.py +0 -253
  135. /package/.devcontainer/config/{keybindings.json → defaults/keybindings.json} +0 -0
  136. /package/.devcontainer/config/{settings.json → defaults/settings.json} +0 -0
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ TODO/FIXME harvester — SessionStart hook that surfaces tech debt markers.
4
+
5
+ Greps the codebase for TODO/FIXME/HACK/XXX comments and injects a count
6
+ plus the top items as additionalContext so Claude can proactively mention
7
+ tech debt when relevant.
8
+
9
+ Reads hook input from stdin (JSON). Returns JSON on stdout.
10
+ Always exits 0 (advisory, never blocking).
11
+ """
12
+
13
+ import json
14
+ import os
15
+ import subprocess
16
+ import sys
17
+
18
+ GREP_TIMEOUT = 5
19
+ MAX_ITEMS = 10
20
+ TOTAL_OUTPUT_CAP = 800
21
+
22
+ SOURCE_INCLUDES = [
23
+ "--include=*.py",
24
+ "--include=*.ts",
25
+ "--include=*.tsx",
26
+ "--include=*.js",
27
+ "--include=*.jsx",
28
+ "--include=*.go",
29
+ "--include=*.rs",
30
+ "--include=*.sh",
31
+ "--include=*.svelte",
32
+ "--include=*.vue",
33
+ "--include=*.rb",
34
+ "--include=*.java",
35
+ "--include=*.kt",
36
+ ]
37
+
38
+ EXCLUDE_DIRS = [
39
+ "--exclude-dir=node_modules",
40
+ "--exclude-dir=.git",
41
+ "--exclude-dir=__pycache__",
42
+ "--exclude-dir=.venv",
43
+ "--exclude-dir=venv",
44
+ "--exclude-dir=dist",
45
+ "--exclude-dir=build",
46
+ "--exclude-dir=vendor",
47
+ "--exclude-dir=.next",
48
+ "--exclude-dir=.nuxt",
49
+ "--exclude-dir=target",
50
+ "--exclude-dir=.mypy_cache",
51
+ "--exclude-dir=.pytest_cache",
52
+ ]
53
+
54
+
55
+ def main():
56
+ try:
57
+ json.load(sys.stdin)
58
+ except (json.JSONDecodeError, ValueError):
59
+ pass
60
+
61
+ cwd = os.getcwd()
62
+
63
+ cmd = (
64
+ ["grep", "-rn", "-E", r"\b(TODO|FIXME|HACK|XXX)\b"]
65
+ + SOURCE_INCLUDES
66
+ + EXCLUDE_DIRS
67
+ + [cwd]
68
+ )
69
+
70
+ try:
71
+ result = subprocess.run(
72
+ cmd,
73
+ capture_output=True,
74
+ text=True,
75
+ timeout=GREP_TIMEOUT,
76
+ )
77
+ except (FileNotFoundError, OSError, subprocess.TimeoutExpired):
78
+ sys.exit(0)
79
+
80
+ # grep returns 1 for no matches — that's fine
81
+ output = result.stdout.strip()
82
+ if not output:
83
+ sys.exit(0)
84
+
85
+ lines = output.splitlines()
86
+ total_count = len(lines)
87
+
88
+ # Count unique files
89
+ files_seen: set[str] = set()
90
+ items: list[str] = []
91
+
92
+ for line in lines:
93
+ # Format: filepath:linenum:content
94
+ parts = line.split(":", 2)
95
+ if len(parts) >= 3:
96
+ filepath = parts[0]
97
+ files_seen.add(filepath)
98
+
99
+ if len(items) < MAX_ITEMS:
100
+ # Make path relative to cwd for readability
101
+ rel_path = os.path.relpath(filepath, cwd)
102
+ line_num = parts[1]
103
+ content = parts[2].strip()
104
+
105
+ # Trim long lines
106
+ if len(content) > 80:
107
+ content = content[:77] + "..."
108
+
109
+ items.append(f" {rel_path}:{line_num}: {content}")
110
+
111
+ file_count = len(files_seen)
112
+ header = (
113
+ f"[Tech Debt] {total_count} TODO/FIXME items found across {file_count} files"
114
+ )
115
+
116
+ if items:
117
+ body = header + "\nTop items:\n" + "\n".join(items)
118
+ else:
119
+ body = header
120
+
121
+ # Cap total output
122
+ if len(body) > TOTAL_OUTPUT_CAP:
123
+ body = body[:TOTAL_OUTPUT_CAP] + "\n...(truncated)"
124
+
125
+ json.dump({"additionalContext": body}, sys.stdout)
126
+ sys.exit(0)
127
+
128
+
129
+ if __name__ == "__main__":
130
+ main()
@@ -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.