@martinffx/atelier 0.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.
Files changed (130) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/LICENSE +21 -0
  3. package/README.md +285 -0
  4. package/agents/architect.md +38 -0
  5. package/agents/oracle.md +40 -0
  6. package/agents/recon.md +39 -0
  7. package/dist/atelier.js +33082 -0
  8. package/package.json +44 -0
  9. package/skills/code-conventional-commit/SKILL.md +134 -0
  10. package/skills/code-conventional-commit/evals/evals.json +23 -0
  11. package/skills/code-conventional-commit/workspace/iteration-1/eval-0/with_skill/outputs/commit-message.txt +4 -0
  12. package/skills/code-conventional-commit/workspace/iteration-1/eval-0/with_skill/outputs/eval_metadata.json +6 -0
  13. package/skills/code-conventional-commit/workspace/iteration-1/eval-1/with_skill/outputs/eval_metadata.json +6 -0
  14. package/skills/code-conventional-commit/workspace/iteration-1/eval-1/with_skill/outputs/validation-result.txt +16 -0
  15. package/skills/code-conventional-commit/workspace/iteration-1/eval-2/with_skill/outputs/commit-message.txt +8 -0
  16. package/skills/code-conventional-commit/workspace/iteration-1/eval-2/with_skill/outputs/eval_metadata.json +6 -0
  17. package/skills/code-conventional-commit/workspace/iteration-1/report.html +1325 -0
  18. package/skills/code-debug/SKILL.md +271 -0
  19. package/skills/code-debug/references/language-tools.md +139 -0
  20. package/skills/code-debug/references/techniques.md +117 -0
  21. package/skills/code-docs/SKILL.md +171 -0
  22. package/skills/code-docs/references/api-docs.md +116 -0
  23. package/skills/code-docs/references/changelog.md +64 -0
  24. package/skills/code-docs/references/readme-structure.md +94 -0
  25. package/skills/code-git-worktrees/SKILL.md +218 -0
  26. package/skills/code-perf/SKILL.md +163 -0
  27. package/skills/code-perf/references/common-bottlenecks.md +124 -0
  28. package/skills/code-perf/references/optimization-patterns.md +167 -0
  29. package/skills/code-perf/references/profiling-tools.md +126 -0
  30. package/skills/code-review/SKILL.md +78 -0
  31. package/skills/code-review/references/output.md +200 -0
  32. package/skills/code-review/references/reviewers.md +719 -0
  33. package/skills/code-review/references/rq.md +357 -0
  34. package/skills/code-review/references/rs.md +30 -0
  35. package/skills/code-security/SKILL.md +183 -0
  36. package/skills/code-security/references/owasp-top-10.md +129 -0
  37. package/skills/code-security/references/security-tools.md +102 -0
  38. package/skills/code-security/references/vulnerability-patterns.md +129 -0
  39. package/skills/code-stacked-commit/SKILL.md +155 -0
  40. package/skills/code-subagents/SKILL.md +184 -0
  41. package/skills/code-subagents/references/code-quality-reviewer-prompt.md +48 -0
  42. package/skills/code-subagents/references/implementor-prompt.md +79 -0
  43. package/skills/code-subagents/references/spec-reviewer-prompt.md +62 -0
  44. package/skills/oracle-architect/SKILL.md +246 -0
  45. package/skills/oracle-architect/references/api-design.md +345 -0
  46. package/skills/oracle-architect/references/data-modeling.md +318 -0
  47. package/skills/oracle-architect/references/ddd-patterns.md +247 -0
  48. package/skills/oracle-challenge/SKILL.md +126 -0
  49. package/skills/oracle-testing/SKILL.md +237 -0
  50. package/skills/oracle-testing/references/anti-patterns.md +618 -0
  51. package/skills/oracle-testing/references/boundaries.md +579 -0
  52. package/skills/oracle-testing/references/core-testing.md +691 -0
  53. package/skills/oracle-testing/references/edge-testing.md +794 -0
  54. package/skills/oracle-testing/references/stub-driven-tdd.md +322 -0
  55. package/skills/oracle-thinkdeep/SKILL.md +164 -0
  56. package/skills/python-architecture/SKILL.md +148 -0
  57. package/skills/python-architecture/references/data-modeling.md +558 -0
  58. package/skills/python-architecture/references/ddd.md +569 -0
  59. package/skills/python-architecture/references/functional-core.md +337 -0
  60. package/skills/python-build-tools/SKILL.md +153 -0
  61. package/skills/python-build-tools/references/basedpyright.md +321 -0
  62. package/skills/python-build-tools/references/ruff.md +225 -0
  63. package/skills/python-build-tools/references/uv.md +257 -0
  64. package/skills/python-fastapi/SKILL.md +184 -0
  65. package/skills/python-fastapi/references/api-design.md +563 -0
  66. package/skills/python-fastapi/references/dependencies.md +479 -0
  67. package/skills/python-fastapi/references/middleware.md +475 -0
  68. package/skills/python-fastapi/references/validation.md +497 -0
  69. package/skills/python-modern-python/SKILL.md +201 -0
  70. package/skills/python-modern-python/references/async.md +76 -0
  71. package/skills/python-modern-python/references/pattern-matching.md +89 -0
  72. package/skills/python-modern-python/references/typing.md +96 -0
  73. package/skills/python-monorepo/SKILL.md +146 -0
  74. package/skills/python-monorepo/references/docker.md +515 -0
  75. package/skills/python-monorepo/references/namespace-packages.md +426 -0
  76. package/skills/python-monorepo/references/workspace-config.md +341 -0
  77. package/skills/python-sqlalchemy/SKILL.md +119 -0
  78. package/skills/python-sqlalchemy/references/async.md +51 -0
  79. package/skills/python-sqlalchemy/references/models.md +67 -0
  80. package/skills/python-sqlalchemy/references/queries.md +57 -0
  81. package/skills/python-temporal/SKILL.md +128 -0
  82. package/skills/python-temporal/references/patterns.md +87 -0
  83. package/skills/python-temporal/references/testing.md +54 -0
  84. package/skills/python-testing/SKILL.md +161 -0
  85. package/skills/python-testing/references/boundaries.md +449 -0
  86. package/skills/python-testing/references/mocking.md +449 -0
  87. package/skills/python-testing/references/pytest.md +524 -0
  88. package/skills/spec-brainstorm/SKILL.md +325 -0
  89. package/skills/spec-finish/SKILL.md +159 -0
  90. package/skills/spec-implement/SKILL.md +296 -0
  91. package/skills/spec-orchestrator/SKILL.md +156 -0
  92. package/skills/spec-plan/SKILL.md +248 -0
  93. package/skills/typescript-api-design/SKILL.md +396 -0
  94. package/skills/typescript-api-design/references/error-responses.md +469 -0
  95. package/skills/typescript-build-tools/SKILL.md +447 -0
  96. package/skills/typescript-build-tools/references/biome.md +436 -0
  97. package/skills/typescript-build-tools/references/bun.md +432 -0
  98. package/skills/typescript-build-tools/references/turborepo.md +426 -0
  99. package/skills/typescript-build-tools/references/vitest.md +518 -0
  100. package/skills/typescript-drizzle-orm/SKILL.md +398 -0
  101. package/skills/typescript-drizzle-orm/references/cloudflare.md +392 -0
  102. package/skills/typescript-drizzle-orm/references/entity-pattern.md +412 -0
  103. package/skills/typescript-drizzle-orm/references/postgresql.md +191 -0
  104. package/skills/typescript-drizzle-orm/references/repository-pattern.md +479 -0
  105. package/skills/typescript-drizzle-orm/references/sqlite.md +291 -0
  106. package/skills/typescript-dynamodb-toolbox/SKILL.md +370 -0
  107. package/skills/typescript-dynamodb-toolbox/references/entity-layer.md +574 -0
  108. package/skills/typescript-dynamodb-toolbox/references/error-handling.md +495 -0
  109. package/skills/typescript-dynamodb-toolbox/references/modeling.md +332 -0
  110. package/skills/typescript-dynamodb-toolbox/references/repository-layer.md +631 -0
  111. package/skills/typescript-dynamodb-toolbox/references/testing.md +718 -0
  112. package/skills/typescript-dynamodb-toolbox/references/transactions.md +423 -0
  113. package/skills/typescript-effect-ts/SKILL.md +341 -0
  114. package/skills/typescript-effect-ts/references/core.md +412 -0
  115. package/skills/typescript-effect-ts/references/error-handling.md +468 -0
  116. package/skills/typescript-effect-ts/references/resources.md +476 -0
  117. package/skills/typescript-effect-ts/references/schema.md +536 -0
  118. package/skills/typescript-effect-ts/references/services.md +461 -0
  119. package/skills/typescript-fastify/SKILL.md +405 -0
  120. package/skills/typescript-fastify/references/plugins.md +329 -0
  121. package/skills/typescript-fastify/references/typeid.md +315 -0
  122. package/skills/typescript-functional-patterns/SKILL.md +402 -0
  123. package/skills/typescript-functional-patterns/references/adts.md +497 -0
  124. package/skills/typescript-functional-patterns/references/branded-types.md +542 -0
  125. package/skills/typescript-functional-patterns/references/migration-guide.md +695 -0
  126. package/skills/typescript-functional-patterns/references/option-result.md +585 -0
  127. package/skills/typescript-testing/SKILL.md +353 -0
  128. package/skills/typescript-testing/references/mocking.md +675 -0
  129. package/skills/typescript-testing/references/msw.md +852 -0
  130. package/skills/typescript-testing/references/snapshot-testing.md +774 -0
@@ -0,0 +1,396 @@
1
+ ---
2
+ name: typescript-api-design
3
+ description: REST API design patterns. Use when designing endpoints, error responses, pagination, versioning, or API structure. Framework-agnostic principles for building consistent, maintainable APIs.
4
+ user-invocable: false
5
+ ---
6
+
7
+ # API Design Patterns
8
+
9
+ Best practices for designing REST APIs with consistent structure, error handling, and resource patterns.
10
+
11
+ ## Additional References
12
+
13
+ - [references/error-responses.md](./references/error-responses.md) - Detailed error handling examples
14
+
15
+ ## Resource Naming
16
+
17
+ Use consistent, predictable URL patterns:
18
+
19
+ ```
20
+ # Collection resources (plural nouns)
21
+ GET /api/v1/users # List users
22
+ POST /api/v1/users # Create user
23
+ GET /api/v1/users/:id # Get user
24
+ PUT /api/v1/users/:id # Update user (full)
25
+ PATCH /api/v1/users/:id # Update user (partial)
26
+ DELETE /api/v1/users/:id # Delete user
27
+
28
+ # Nested resources
29
+ GET /api/v1/users/:userId/posts # List user's posts
30
+ POST /api/v1/users/:userId/posts # Create post for user
31
+ GET /api/v1/users/:userId/posts/:postId # Get specific post
32
+
33
+ # Actions (use verbs sparingly)
34
+ POST /api/v1/users/:id/activate # Activate user
35
+ POST /api/v1/posts/:id/publish # Publish post
36
+ POST /api/v1/invoices/:id/send # Send invoice
37
+ ```
38
+
39
+ ### Guidelines
40
+
41
+ - Use plural nouns for collections (`/users`, not `/user`)
42
+ - Use lowercase with hyphens for multi-word resources (`/ledger-accounts`)
43
+ - Avoid deep nesting (max 2 levels: `/users/:id/posts/:id`)
44
+ - Use query parameters for filtering, sorting, pagination
45
+ - Use verbs only for actions that don't fit CRUD (activate, publish, send)
46
+
47
+ ## API Versioning
48
+
49
+ Version APIs in the URL path:
50
+
51
+ ```
52
+ /api/v1/users
53
+ /api/v2/users
54
+
55
+ # Not in headers (harder to test/debug)
56
+ # Not in query params (breaks caching)
57
+ ```
58
+
59
+ ### Version Strategy
60
+
61
+ ```typescript
62
+ // v1/routes.ts
63
+ export async function v1Routes(app: FastifyInstance) {
64
+ app.get('/users', getUsersV1)
65
+ app.post('/users', createUserV1)
66
+ }
67
+
68
+ // v2/routes.ts
69
+ export async function v2Routes(app: FastifyInstance) {
70
+ app.get('/users', getUsersV2) // Breaking change in response structure
71
+ app.post('/users', createUserV2)
72
+ }
73
+
74
+ // server.ts
75
+ app.register(v1Routes, { prefix: '/api/v1' })
76
+ app.register(v2Routes, { prefix: '/api/v2' })
77
+ ```
78
+
79
+ ## RFC 7807 Problem Details
80
+
81
+ Standardized error response format:
82
+
83
+ ```typescript
84
+ interface ProblemDetail {
85
+ type: string // Error type identifier
86
+ status: number // HTTP status code
87
+ title: string // Short, human-readable summary
88
+ detail: string // Specific explanation for this occurrence
89
+ instance: string // URI reference to specific occurrence
90
+ traceId: string // Request trace ID for debugging
91
+ }
92
+
93
+ // Example error response
94
+ {
95
+ "type": "NOT_FOUND",
96
+ "status": 404,
97
+ "title": "Not Found",
98
+ "detail": "User with ID usr_01h455vb4pex5vsknk084sn02q not found",
99
+ "instance": "/api/v1/users/usr_01h455vb4pex5vsknk084sn02q",
100
+ "traceId": "req_abc123xyz"
101
+ }
102
+ ```
103
+
104
+ ### Error Types
105
+
106
+ ```typescript
107
+ // Domain error base class
108
+ abstract class AppError extends Error {
109
+ abstract readonly status: number
110
+ abstract readonly type: string
111
+
112
+ constructor(message: string, public readonly context?: ErrorContext) {
113
+ super(message)
114
+ }
115
+
116
+ toResponse(instance: string, traceId: string): ProblemDetail {
117
+ return {
118
+ type: this.type,
119
+ status: this.status,
120
+ title: this.name,
121
+ detail: this.message,
122
+ instance,
123
+ traceId,
124
+ ...this.context,
125
+ }
126
+ }
127
+ }
128
+
129
+ // Specific error types
130
+ class NotFoundError extends AppError {
131
+ readonly status = 404
132
+ readonly type = 'NOT_FOUND'
133
+ }
134
+
135
+ class ConflictError extends AppError {
136
+ readonly status = 409
137
+ readonly type = 'CONFLICT'
138
+
139
+ constructor(
140
+ message: string,
141
+ public readonly retryable: boolean = false,
142
+ context?: ErrorContext
143
+ ) {
144
+ super(message, context)
145
+ }
146
+ }
147
+
148
+ class ServiceUnavailableError extends AppError {
149
+ readonly status = 503
150
+ readonly type = 'SERVICE_UNAVAILABLE'
151
+
152
+ constructor(
153
+ message: string,
154
+ public readonly retryable: boolean = true,
155
+ context?: ErrorContext
156
+ ) {
157
+ super(message, context)
158
+ }
159
+ }
160
+ ```
161
+
162
+ See [references/error-responses.md](./references/error-responses.md) for complete examples.
163
+
164
+ ## Pagination (Cursor-Based)
165
+
166
+ Use cursor-based pagination for large datasets:
167
+
168
+ ```typescript
169
+ // Request
170
+ GET /api/v1/posts?limit=20&cursor=pst_01h455vb4pex5vsknk084sn02q
171
+
172
+ // Response
173
+ {
174
+ "items": [
175
+ { "id": "pst_01h455w3x8k5z9y7q1m0n2b3c4", ... },
176
+ { "id": "pst_01h455x2y9l6a0z8r2n1o3c5d6", ... }
177
+ ],
178
+ "nextCursor": "pst_01h455z1a0m7b8y9s3o2p4d6e7",
179
+ "hasMore": true
180
+ }
181
+ ```
182
+
183
+ ### Implementation
184
+
185
+ ```typescript
186
+ interface PaginatedRequest {
187
+ limit?: number // Max items to return (default 20, max 100)
188
+ cursor?: string // Cursor for next page (opaque to client)
189
+ }
190
+
191
+ interface PaginatedResponse<T> {
192
+ items: T[]
193
+ nextCursor?: string
194
+ hasMore: boolean
195
+ }
196
+
197
+ async function listPosts(req: PaginatedRequest): Promise<PaginatedResponse<Post>> {
198
+ const limit = Math.min(req.limit ?? 20, 100)
199
+ const queryLimit = limit + 1 // Fetch one extra to check hasMore
200
+
201
+ const posts = await db.query.posts.findMany({
202
+ where: req.cursor ? gt(posts.id, req.cursor) : undefined,
203
+ orderBy: desc(posts.createdAt),
204
+ limit: queryLimit,
205
+ })
206
+
207
+ const hasMore = posts.length > limit
208
+ const items = posts.slice(0, limit)
209
+ const nextCursor = hasMore ? items[items.length - 1].id : undefined
210
+
211
+ return { items, nextCursor, hasMore }
212
+ }
213
+ ```
214
+
215
+ ### Why Cursor Over Offset
216
+
217
+ ```
218
+ ❌ Offset-based (/posts?offset=40&limit=20)
219
+ - Unstable: Items can shift if new records inserted
220
+ - Performance: DB must scan all previous rows
221
+ - Inaccurate: Can miss or duplicate items
222
+
223
+ ✅ Cursor-based (/posts?cursor=pst_xyz&limit=20)
224
+ - Stable: Cursor points to specific item
225
+ - Performant: DB uses index seek
226
+ - Accurate: No gaps or duplicates
227
+ ```
228
+
229
+ ## Filtering & Sorting
230
+
231
+ Use query parameters for filtering and sorting:
232
+
233
+ ```
234
+ # Filtering
235
+ GET /api/v1/users?status=active&role=admin
236
+ GET /api/v1/posts?author=usr_abc&published=true
237
+
238
+ # Sorting
239
+ GET /api/v1/posts?sort=-createdAt # Descending (- prefix)
240
+ GET /api/v1/users?sort=name # Ascending
241
+
242
+ # Combined
243
+ GET /api/v1/posts?author=usr_abc&status=published&sort=-createdAt&limit=20
244
+ ```
245
+
246
+ ### Implementation
247
+
248
+ ```typescript
249
+ interface ListPostsQuery {
250
+ author?: string
251
+ status?: 'draft' | 'published'
252
+ sort?: 'createdAt' | '-createdAt' | 'title' | '-title'
253
+ limit?: number
254
+ cursor?: string
255
+ }
256
+
257
+ async function listPosts(query: ListPostsQuery): Promise<PaginatedResponse<Post>> {
258
+ const conditions = []
259
+
260
+ if (query.author) {
261
+ conditions.push(eq(posts.authorId, query.author))
262
+ }
263
+ if (query.status) {
264
+ conditions.push(eq(posts.status, query.status))
265
+ }
266
+
267
+ const orderByColumn = query.sort?.startsWith('-')
268
+ ? query.sort.slice(1)
269
+ : query.sort ?? 'createdAt'
270
+ const orderByDirection = query.sort?.startsWith('-') ? desc : asc
271
+
272
+ return await db.query.posts.findMany({
273
+ where: conditions.length > 0 ? and(...conditions) : undefined,
274
+ orderBy: orderByDirection(posts[orderByColumn]),
275
+ limit: query.limit ?? 20,
276
+ })
277
+ }
278
+ ```
279
+
280
+ ## HTTP Status Codes
281
+
282
+ Use status codes consistently:
283
+
284
+ ```
285
+ # Success
286
+ 200 OK # Successful GET, PUT, PATCH
287
+ 201 Created # Successful POST (include Location header)
288
+ 204 No Content # Successful DELETE, PUT with no response body
289
+
290
+ # Client Errors
291
+ 400 Bad Request # Invalid request body/parameters
292
+ 401 Unauthorized # Missing or invalid authentication
293
+ 403 Forbidden # Valid auth, but lacks permission
294
+ 404 Not Found # Resource doesn't exist
295
+ 409 Conflict # Resource already exists, optimistic lock failure
296
+ 422 Unprocessable # Validation error (semantic)
297
+ 429 Too Many Requests # Rate limit exceeded
298
+
299
+ # Server Errors
300
+ 500 Internal Server Error # Unexpected error
301
+ 503 Service Unavailable # Temporary unavailability, retry later
302
+ ```
303
+
304
+ ## Response Envelope (When to Use)
305
+
306
+ **Don't use envelopes for simple CRUD:**
307
+
308
+ ```typescript
309
+ // ❌ Unnecessary wrapping
310
+ GET /api/v1/users/123
311
+ {
312
+ "success": true,
313
+ "data": { "id": "123", "name": "Alice" }
314
+ }
315
+
316
+ // ✅ Return resource directly
317
+ GET /api/v1/users/123
318
+ {
319
+ "id": "123",
320
+ "name": "Alice"
321
+ }
322
+ ```
323
+
324
+ **Use envelopes for pagination:**
325
+
326
+ ```typescript
327
+ // ✅ Envelope needed for metadata
328
+ GET /api/v1/users?limit=20
329
+ {
330
+ "items": [...],
331
+ "nextCursor": "usr_xyz",
332
+ "hasMore": true
333
+ }
334
+ ```
335
+
336
+ ## Timestamps
337
+
338
+ Use ISO 8601 format for all timestamps:
339
+
340
+ ```typescript
341
+ {
342
+ "createdAt": "2024-01-15T14:30:00.000Z", // ISO 8601 UTC
343
+ "updatedAt": "2024-01-16T09:15:30.123Z"
344
+ }
345
+
346
+ // In entities
347
+ toResponse(): UserResponse {
348
+ return {
349
+ ...
350
+ createdAt: this.createdAt.toISOString(), // Date → ISO string
351
+ updatedAt: this.updatedAt.toISOString(),
352
+ }
353
+ }
354
+ ```
355
+
356
+ ## Idempotency
357
+
358
+ Use idempotency keys for safe retries:
359
+
360
+ ```typescript
361
+ // Request
362
+ POST /api/v1/transactions
363
+ Headers:
364
+ Idempotency-Key: txn_abc123xyz
365
+ Body:
366
+ { "amount": 100, "from": "usr_123", "to": "usr_456" }
367
+
368
+ // Implementation
369
+ async function createTransaction(rq: CreateTransactionRequest, idempotencyKey: string) {
370
+ // Check if transaction with this key already exists
371
+ const existing = await db.query.transactions.findFirst({
372
+ where: eq(transactions.idempotencyKey, idempotencyKey),
373
+ })
374
+
375
+ if (existing) {
376
+ return TransactionEntity.fromRecord(existing) // Return existing
377
+ }
378
+
379
+ // Create new transaction
380
+ const transaction = TransactionEntity.fromRequest(rq, idempotencyKey)
381
+ return await transactionRepo.create(transaction)
382
+ }
383
+ ```
384
+
385
+ ## Guidelines
386
+
387
+ 1. **Plural nouns** - Collections use plural resource names
388
+ 2. **Lowercase with hyphens** - Multi-word resources like `ledger-accounts`
389
+ 3. **Version in URL** - `/api/v1/`, `/api/v2/` for breaking changes
390
+ 4. **RFC 7807 errors** - Standardized error response format
391
+ 5. **Cursor pagination** - For large datasets (more stable than offset)
392
+ 6. **Query params** - For filtering, sorting, pagination (not in path)
393
+ 7. **HTTP status codes** - Use correct codes (200, 201, 204, 400, 404, 409, 500, 503)
394
+ 8. **ISO 8601 timestamps** - Always use `.toISOString()` for dates
395
+ 9. **Idempotency keys** - For non-idempotent operations (POST, PATCH)
396
+ 10. **No unnecessary envelopes** - Return resources directly unless pagination needed