digiqagent 1.2.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/.cursor-plugin/plugin.json +29 -0
- package/README.md +197 -0
- package/agents/code-reviewer.md +48 -0
- package/bin/cli.js +210 -0
- package/package.json +41 -0
- package/skills/playwright-test-generator/SKILL.md +563 -0
- package/skills/playwright-test-generator/interaction-test-patterns.md +987 -0
- package/skills/playwright-test-generator/page-object-patterns.md +833 -0
- package/skills/postman-collection-generator/SKILL.md +310 -0
- package/skills/postman-collection-generator/collection-patterns.md +493 -0
- package/skills/postman-test-suite-generator/SKILL.md +653 -0
- package/skills/postman-test-suite-generator/test-scenario-patterns.md +612 -0
- package/skills/receiving-code-review/SKILL.md +213 -0
- package/skills/requesting-code-review/SKILL.md +105 -0
- package/skills/requesting-code-review/code-reviewer.md +146 -0
- package/skills/review-prompts/code-quality-reviewer-prompt.md +26 -0
- package/skills/review-prompts/spec-reviewer-prompt.md +61 -0
- package/skills/swagger-generator/SKILL.md +238 -0
- package/skills/swagger-generator/openapi-patterns.md +667 -0
- package/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/skills/systematic-debugging/SKILL.md +296 -0
- package/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/skills/systematic-debugging/find-polluter.sh +63 -0
- package/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/skills/systematic-debugging/test-academic.md +14 -0
- package/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/skills/test-driven-development/SKILL.md +371 -0
- package/skills/test-driven-development/testing-anti-patterns.md +299 -0
- package/skills/verification-before-completion/SKILL.md +139 -0
|
@@ -0,0 +1,667 @@
|
|
|
1
|
+
# OpenAPI Reusable Patterns
|
|
2
|
+
|
|
3
|
+
Reference patterns for common API constructs. Copy and adapt these into generated specs.
|
|
4
|
+
|
|
5
|
+
## Standard Error Response Schema
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
components:
|
|
9
|
+
schemas:
|
|
10
|
+
ErrorResponse:
|
|
11
|
+
type: object
|
|
12
|
+
required:
|
|
13
|
+
- statusCode
|
|
14
|
+
- message
|
|
15
|
+
- error
|
|
16
|
+
properties:
|
|
17
|
+
statusCode:
|
|
18
|
+
type: integer
|
|
19
|
+
example: 400
|
|
20
|
+
message:
|
|
21
|
+
oneOf:
|
|
22
|
+
- type: string
|
|
23
|
+
- type: array
|
|
24
|
+
items:
|
|
25
|
+
type: string
|
|
26
|
+
example: "Validation failed"
|
|
27
|
+
error:
|
|
28
|
+
type: string
|
|
29
|
+
example: "Bad Request"
|
|
30
|
+
timestamp:
|
|
31
|
+
type: string
|
|
32
|
+
format: date-time
|
|
33
|
+
example: "2025-01-15T10:30:00Z"
|
|
34
|
+
path:
|
|
35
|
+
type: string
|
|
36
|
+
example: "/api/users"
|
|
37
|
+
|
|
38
|
+
responses:
|
|
39
|
+
BadRequest:
|
|
40
|
+
description: Invalid request parameters or body
|
|
41
|
+
content:
|
|
42
|
+
application/json:
|
|
43
|
+
schema:
|
|
44
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
45
|
+
example:
|
|
46
|
+
statusCode: 400
|
|
47
|
+
message: ["email must be a valid email", "name must not be empty"]
|
|
48
|
+
error: "Bad Request"
|
|
49
|
+
|
|
50
|
+
Unauthorized:
|
|
51
|
+
description: Missing or invalid authentication token
|
|
52
|
+
content:
|
|
53
|
+
application/json:
|
|
54
|
+
schema:
|
|
55
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
56
|
+
example:
|
|
57
|
+
statusCode: 401
|
|
58
|
+
message: "Invalid or expired token"
|
|
59
|
+
error: "Unauthorized"
|
|
60
|
+
|
|
61
|
+
Forbidden:
|
|
62
|
+
description: Insufficient permissions for this operation
|
|
63
|
+
content:
|
|
64
|
+
application/json:
|
|
65
|
+
schema:
|
|
66
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
67
|
+
example:
|
|
68
|
+
statusCode: 403
|
|
69
|
+
message: "You do not have permission to access this resource"
|
|
70
|
+
error: "Forbidden"
|
|
71
|
+
|
|
72
|
+
NotFound:
|
|
73
|
+
description: Requested resource not found
|
|
74
|
+
content:
|
|
75
|
+
application/json:
|
|
76
|
+
schema:
|
|
77
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
78
|
+
example:
|
|
79
|
+
statusCode: 404
|
|
80
|
+
message: "Resource with id '123' not found"
|
|
81
|
+
error: "Not Found"
|
|
82
|
+
|
|
83
|
+
Conflict:
|
|
84
|
+
description: Resource already exists or state conflict
|
|
85
|
+
content:
|
|
86
|
+
application/json:
|
|
87
|
+
schema:
|
|
88
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
89
|
+
example:
|
|
90
|
+
statusCode: 409
|
|
91
|
+
message: "A user with this email already exists"
|
|
92
|
+
error: "Conflict"
|
|
93
|
+
|
|
94
|
+
UnprocessableEntity:
|
|
95
|
+
description: Request understood but semantically invalid
|
|
96
|
+
content:
|
|
97
|
+
application/json:
|
|
98
|
+
schema:
|
|
99
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
100
|
+
example:
|
|
101
|
+
statusCode: 422
|
|
102
|
+
message: "Cannot assign task to a deactivated user"
|
|
103
|
+
error: "Unprocessable Entity"
|
|
104
|
+
|
|
105
|
+
InternalError:
|
|
106
|
+
description: Unexpected server error
|
|
107
|
+
content:
|
|
108
|
+
application/json:
|
|
109
|
+
schema:
|
|
110
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
111
|
+
example:
|
|
112
|
+
statusCode: 500
|
|
113
|
+
message: "An unexpected error occurred"
|
|
114
|
+
error: "Internal Server Error"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Pagination — Offset/Limit
|
|
118
|
+
|
|
119
|
+
```yaml
|
|
120
|
+
# Query parameters for list endpoints
|
|
121
|
+
parameters:
|
|
122
|
+
PageParam:
|
|
123
|
+
name: page
|
|
124
|
+
in: query
|
|
125
|
+
description: Page number (1-based)
|
|
126
|
+
schema:
|
|
127
|
+
type: integer
|
|
128
|
+
minimum: 1
|
|
129
|
+
default: 1
|
|
130
|
+
|
|
131
|
+
LimitParam:
|
|
132
|
+
name: limit
|
|
133
|
+
in: query
|
|
134
|
+
description: Number of items per page
|
|
135
|
+
schema:
|
|
136
|
+
type: integer
|
|
137
|
+
minimum: 1
|
|
138
|
+
maximum: 100
|
|
139
|
+
default: 20
|
|
140
|
+
|
|
141
|
+
SortByParam:
|
|
142
|
+
name: sortBy
|
|
143
|
+
in: query
|
|
144
|
+
description: Field to sort by
|
|
145
|
+
schema:
|
|
146
|
+
type: string
|
|
147
|
+
default: createdAt
|
|
148
|
+
|
|
149
|
+
SortOrderParam:
|
|
150
|
+
name: sortOrder
|
|
151
|
+
in: query
|
|
152
|
+
description: Sort direction
|
|
153
|
+
schema:
|
|
154
|
+
type: string
|
|
155
|
+
enum: [asc, desc]
|
|
156
|
+
default: desc
|
|
157
|
+
|
|
158
|
+
# Wrap list responses with pagination metadata
|
|
159
|
+
schemas:
|
|
160
|
+
PaginationMeta:
|
|
161
|
+
type: object
|
|
162
|
+
properties:
|
|
163
|
+
page:
|
|
164
|
+
type: integer
|
|
165
|
+
example: 1
|
|
166
|
+
limit:
|
|
167
|
+
type: integer
|
|
168
|
+
example: 20
|
|
169
|
+
totalItems:
|
|
170
|
+
type: integer
|
|
171
|
+
example: 150
|
|
172
|
+
totalPages:
|
|
173
|
+
type: integer
|
|
174
|
+
example: 8
|
|
175
|
+
hasNextPage:
|
|
176
|
+
type: boolean
|
|
177
|
+
example: true
|
|
178
|
+
hasPreviousPage:
|
|
179
|
+
type: boolean
|
|
180
|
+
example: false
|
|
181
|
+
|
|
182
|
+
# Usage: compose with resource list
|
|
183
|
+
PaginatedUserList:
|
|
184
|
+
type: object
|
|
185
|
+
properties:
|
|
186
|
+
data:
|
|
187
|
+
type: array
|
|
188
|
+
items:
|
|
189
|
+
$ref: '#/components/schemas/User'
|
|
190
|
+
meta:
|
|
191
|
+
$ref: '#/components/schemas/PaginationMeta'
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Pagination — Cursor-Based
|
|
195
|
+
|
|
196
|
+
```yaml
|
|
197
|
+
schemas:
|
|
198
|
+
CursorPaginationMeta:
|
|
199
|
+
type: object
|
|
200
|
+
properties:
|
|
201
|
+
cursor:
|
|
202
|
+
type: string
|
|
203
|
+
nullable: true
|
|
204
|
+
description: Cursor for next page, null if no more pages
|
|
205
|
+
example: "eyJpZCI6MTAwfQ=="
|
|
206
|
+
hasMore:
|
|
207
|
+
type: boolean
|
|
208
|
+
example: true
|
|
209
|
+
limit:
|
|
210
|
+
type: integer
|
|
211
|
+
example: 20
|
|
212
|
+
|
|
213
|
+
parameters:
|
|
214
|
+
CursorParam:
|
|
215
|
+
name: cursor
|
|
216
|
+
in: query
|
|
217
|
+
description: Pagination cursor from previous response
|
|
218
|
+
schema:
|
|
219
|
+
type: string
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Authentication Schemes
|
|
223
|
+
|
|
224
|
+
```yaml
|
|
225
|
+
components:
|
|
226
|
+
securitySchemes:
|
|
227
|
+
# JWT Bearer Token
|
|
228
|
+
bearerAuth:
|
|
229
|
+
type: http
|
|
230
|
+
scheme: bearer
|
|
231
|
+
bearerFormat: JWT
|
|
232
|
+
description: JWT token obtained from /api/auth/login
|
|
233
|
+
|
|
234
|
+
# API Key in Header
|
|
235
|
+
apiKeyAuth:
|
|
236
|
+
type: apiKey
|
|
237
|
+
in: header
|
|
238
|
+
name: X-API-Key
|
|
239
|
+
description: API key provided during registration
|
|
240
|
+
|
|
241
|
+
# API Key in Query (less secure, use sparingly)
|
|
242
|
+
apiKeyQuery:
|
|
243
|
+
type: apiKey
|
|
244
|
+
in: query
|
|
245
|
+
name: api_key
|
|
246
|
+
|
|
247
|
+
# OAuth2 Authorization Code
|
|
248
|
+
oauth2Auth:
|
|
249
|
+
type: oauth2
|
|
250
|
+
flows:
|
|
251
|
+
authorizationCode:
|
|
252
|
+
authorizationUrl: https://auth.example.com/authorize
|
|
253
|
+
tokenUrl: https://auth.example.com/token
|
|
254
|
+
refreshUrl: https://auth.example.com/token
|
|
255
|
+
scopes:
|
|
256
|
+
read:users: Read user profiles
|
|
257
|
+
write:users: Create and update users
|
|
258
|
+
admin: Full administrative access
|
|
259
|
+
|
|
260
|
+
# Basic Auth
|
|
261
|
+
basicAuth:
|
|
262
|
+
type: http
|
|
263
|
+
scheme: basic
|
|
264
|
+
|
|
265
|
+
# Apply globally (override per-operation with empty security: [])
|
|
266
|
+
security:
|
|
267
|
+
- bearerAuth: []
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Common Headers
|
|
271
|
+
|
|
272
|
+
```yaml
|
|
273
|
+
parameters:
|
|
274
|
+
AcceptLanguageHeader:
|
|
275
|
+
name: Accept-Language
|
|
276
|
+
in: header
|
|
277
|
+
description: Preferred response language
|
|
278
|
+
schema:
|
|
279
|
+
type: string
|
|
280
|
+
default: en
|
|
281
|
+
example: en-US
|
|
282
|
+
|
|
283
|
+
IdempotencyKeyHeader:
|
|
284
|
+
name: Idempotency-Key
|
|
285
|
+
in: header
|
|
286
|
+
description: Unique key to ensure idempotent request processing
|
|
287
|
+
required: true
|
|
288
|
+
schema:
|
|
289
|
+
type: string
|
|
290
|
+
format: uuid
|
|
291
|
+
example: "550e8400-e29b-41d4-a716-446655440000"
|
|
292
|
+
|
|
293
|
+
CorrelationIdHeader:
|
|
294
|
+
name: X-Correlation-ID
|
|
295
|
+
in: header
|
|
296
|
+
description: Request correlation ID for tracing
|
|
297
|
+
schema:
|
|
298
|
+
type: string
|
|
299
|
+
format: uuid
|
|
300
|
+
|
|
301
|
+
# Response headers
|
|
302
|
+
headers:
|
|
303
|
+
X-Request-Id:
|
|
304
|
+
description: Unique request identifier for debugging
|
|
305
|
+
schema:
|
|
306
|
+
type: string
|
|
307
|
+
format: uuid
|
|
308
|
+
|
|
309
|
+
X-RateLimit-Limit:
|
|
310
|
+
description: Maximum requests allowed per window
|
|
311
|
+
schema:
|
|
312
|
+
type: integer
|
|
313
|
+
example: 100
|
|
314
|
+
|
|
315
|
+
X-RateLimit-Remaining:
|
|
316
|
+
description: Requests remaining in current window
|
|
317
|
+
schema:
|
|
318
|
+
type: integer
|
|
319
|
+
example: 95
|
|
320
|
+
|
|
321
|
+
X-RateLimit-Reset:
|
|
322
|
+
description: Unix timestamp when the rate limit resets
|
|
323
|
+
schema:
|
|
324
|
+
type: integer
|
|
325
|
+
example: 1700000000
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## File Upload
|
|
329
|
+
|
|
330
|
+
```yaml
|
|
331
|
+
# Single file upload
|
|
332
|
+
paths:
|
|
333
|
+
/api/uploads:
|
|
334
|
+
post:
|
|
335
|
+
tags: [Uploads]
|
|
336
|
+
summary: Upload a file
|
|
337
|
+
operationId: uploadFile
|
|
338
|
+
requestBody:
|
|
339
|
+
required: true
|
|
340
|
+
content:
|
|
341
|
+
multipart/form-data:
|
|
342
|
+
schema:
|
|
343
|
+
type: object
|
|
344
|
+
required:
|
|
345
|
+
- file
|
|
346
|
+
properties:
|
|
347
|
+
file:
|
|
348
|
+
type: string
|
|
349
|
+
format: binary
|
|
350
|
+
description: File to upload (max 10MB)
|
|
351
|
+
description:
|
|
352
|
+
type: string
|
|
353
|
+
description: Optional file description
|
|
354
|
+
encoding:
|
|
355
|
+
file:
|
|
356
|
+
contentType: image/png, image/jpeg, application/pdf
|
|
357
|
+
responses:
|
|
358
|
+
'201':
|
|
359
|
+
description: File uploaded successfully
|
|
360
|
+
content:
|
|
361
|
+
application/json:
|
|
362
|
+
schema:
|
|
363
|
+
type: object
|
|
364
|
+
properties:
|
|
365
|
+
id:
|
|
366
|
+
type: string
|
|
367
|
+
format: uuid
|
|
368
|
+
url:
|
|
369
|
+
type: string
|
|
370
|
+
format: uri
|
|
371
|
+
example: "https://cdn.example.com/uploads/abc123.png"
|
|
372
|
+
size:
|
|
373
|
+
type: integer
|
|
374
|
+
description: File size in bytes
|
|
375
|
+
example: 204800
|
|
376
|
+
mimeType:
|
|
377
|
+
type: string
|
|
378
|
+
example: "image/png"
|
|
379
|
+
'400':
|
|
380
|
+
$ref: '#/components/responses/BadRequest'
|
|
381
|
+
'413':
|
|
382
|
+
description: File too large
|
|
383
|
+
content:
|
|
384
|
+
application/json:
|
|
385
|
+
schema:
|
|
386
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
387
|
+
|
|
388
|
+
# Multiple file upload
|
|
389
|
+
/api/uploads/batch:
|
|
390
|
+
post:
|
|
391
|
+
tags: [Uploads]
|
|
392
|
+
summary: Upload multiple files
|
|
393
|
+
operationId: uploadFiles
|
|
394
|
+
requestBody:
|
|
395
|
+
required: true
|
|
396
|
+
content:
|
|
397
|
+
multipart/form-data:
|
|
398
|
+
schema:
|
|
399
|
+
type: object
|
|
400
|
+
required:
|
|
401
|
+
- files
|
|
402
|
+
properties:
|
|
403
|
+
files:
|
|
404
|
+
type: array
|
|
405
|
+
items:
|
|
406
|
+
type: string
|
|
407
|
+
format: binary
|
|
408
|
+
maxItems: 5
|
|
409
|
+
responses:
|
|
410
|
+
'201':
|
|
411
|
+
description: Files uploaded successfully
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
## File Download
|
|
415
|
+
|
|
416
|
+
```yaml
|
|
417
|
+
paths:
|
|
418
|
+
/api/uploads/{fileId}/download:
|
|
419
|
+
get:
|
|
420
|
+
tags: [Uploads]
|
|
421
|
+
summary: Download a file
|
|
422
|
+
operationId: downloadFile
|
|
423
|
+
parameters:
|
|
424
|
+
- name: fileId
|
|
425
|
+
in: path
|
|
426
|
+
required: true
|
|
427
|
+
schema:
|
|
428
|
+
type: string
|
|
429
|
+
format: uuid
|
|
430
|
+
responses:
|
|
431
|
+
'200':
|
|
432
|
+
description: File content
|
|
433
|
+
headers:
|
|
434
|
+
Content-Disposition:
|
|
435
|
+
schema:
|
|
436
|
+
type: string
|
|
437
|
+
example: 'attachment; filename="report.pdf"'
|
|
438
|
+
content:
|
|
439
|
+
application/octet-stream:
|
|
440
|
+
schema:
|
|
441
|
+
type: string
|
|
442
|
+
format: binary
|
|
443
|
+
'404':
|
|
444
|
+
$ref: '#/components/responses/NotFound'
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
## CRUD Resource Template
|
|
448
|
+
|
|
449
|
+
Complete pattern for a typical resource:
|
|
450
|
+
|
|
451
|
+
```yaml
|
|
452
|
+
paths:
|
|
453
|
+
/api/resources:
|
|
454
|
+
get:
|
|
455
|
+
tags: [Resources]
|
|
456
|
+
summary: List all resources
|
|
457
|
+
operationId: listResources
|
|
458
|
+
parameters:
|
|
459
|
+
- $ref: '#/components/parameters/PageParam'
|
|
460
|
+
- $ref: '#/components/parameters/LimitParam'
|
|
461
|
+
- $ref: '#/components/parameters/SortByParam'
|
|
462
|
+
- $ref: '#/components/parameters/SortOrderParam'
|
|
463
|
+
- name: search
|
|
464
|
+
in: query
|
|
465
|
+
description: Search by name or description
|
|
466
|
+
schema:
|
|
467
|
+
type: string
|
|
468
|
+
- name: status
|
|
469
|
+
in: query
|
|
470
|
+
description: Filter by status
|
|
471
|
+
schema:
|
|
472
|
+
type: string
|
|
473
|
+
enum: [active, inactive, archived]
|
|
474
|
+
responses:
|
|
475
|
+
'200':
|
|
476
|
+
description: Paginated list of resources
|
|
477
|
+
content:
|
|
478
|
+
application/json:
|
|
479
|
+
schema:
|
|
480
|
+
$ref: '#/components/schemas/PaginatedResourceList'
|
|
481
|
+
'401':
|
|
482
|
+
$ref: '#/components/responses/Unauthorized'
|
|
483
|
+
|
|
484
|
+
post:
|
|
485
|
+
tags: [Resources]
|
|
486
|
+
summary: Create a new resource
|
|
487
|
+
operationId: createResource
|
|
488
|
+
requestBody:
|
|
489
|
+
required: true
|
|
490
|
+
content:
|
|
491
|
+
application/json:
|
|
492
|
+
schema:
|
|
493
|
+
$ref: '#/components/schemas/CreateResourceRequest'
|
|
494
|
+
responses:
|
|
495
|
+
'201':
|
|
496
|
+
description: Resource created
|
|
497
|
+
content:
|
|
498
|
+
application/json:
|
|
499
|
+
schema:
|
|
500
|
+
$ref: '#/components/schemas/Resource'
|
|
501
|
+
'400':
|
|
502
|
+
$ref: '#/components/responses/BadRequest'
|
|
503
|
+
'401':
|
|
504
|
+
$ref: '#/components/responses/Unauthorized'
|
|
505
|
+
'409':
|
|
506
|
+
$ref: '#/components/responses/Conflict'
|
|
507
|
+
|
|
508
|
+
/api/resources/{id}:
|
|
509
|
+
parameters:
|
|
510
|
+
- name: id
|
|
511
|
+
in: path
|
|
512
|
+
required: true
|
|
513
|
+
description: Resource unique identifier
|
|
514
|
+
schema:
|
|
515
|
+
type: string
|
|
516
|
+
format: uuid
|
|
517
|
+
|
|
518
|
+
get:
|
|
519
|
+
tags: [Resources]
|
|
520
|
+
summary: Get resource by ID
|
|
521
|
+
operationId: getResource
|
|
522
|
+
responses:
|
|
523
|
+
'200':
|
|
524
|
+
description: Resource details
|
|
525
|
+
content:
|
|
526
|
+
application/json:
|
|
527
|
+
schema:
|
|
528
|
+
$ref: '#/components/schemas/Resource'
|
|
529
|
+
'401':
|
|
530
|
+
$ref: '#/components/responses/Unauthorized'
|
|
531
|
+
'404':
|
|
532
|
+
$ref: '#/components/responses/NotFound'
|
|
533
|
+
|
|
534
|
+
put:
|
|
535
|
+
tags: [Resources]
|
|
536
|
+
summary: Update a resource
|
|
537
|
+
operationId: updateResource
|
|
538
|
+
requestBody:
|
|
539
|
+
required: true
|
|
540
|
+
content:
|
|
541
|
+
application/json:
|
|
542
|
+
schema:
|
|
543
|
+
$ref: '#/components/schemas/UpdateResourceRequest'
|
|
544
|
+
responses:
|
|
545
|
+
'200':
|
|
546
|
+
description: Resource updated
|
|
547
|
+
content:
|
|
548
|
+
application/json:
|
|
549
|
+
schema:
|
|
550
|
+
$ref: '#/components/schemas/Resource'
|
|
551
|
+
'400':
|
|
552
|
+
$ref: '#/components/responses/BadRequest'
|
|
553
|
+
'401':
|
|
554
|
+
$ref: '#/components/responses/Unauthorized'
|
|
555
|
+
'404':
|
|
556
|
+
$ref: '#/components/responses/NotFound'
|
|
557
|
+
|
|
558
|
+
delete:
|
|
559
|
+
tags: [Resources]
|
|
560
|
+
summary: Delete a resource
|
|
561
|
+
operationId: deleteResource
|
|
562
|
+
responses:
|
|
563
|
+
'204':
|
|
564
|
+
description: Resource deleted
|
|
565
|
+
'401':
|
|
566
|
+
$ref: '#/components/responses/Unauthorized'
|
|
567
|
+
'404':
|
|
568
|
+
$ref: '#/components/responses/NotFound'
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
## Webhook Callback Pattern
|
|
572
|
+
|
|
573
|
+
```yaml
|
|
574
|
+
paths:
|
|
575
|
+
/api/webhooks:
|
|
576
|
+
post:
|
|
577
|
+
tags: [Webhooks]
|
|
578
|
+
summary: Register a webhook
|
|
579
|
+
operationId: registerWebhook
|
|
580
|
+
requestBody:
|
|
581
|
+
required: true
|
|
582
|
+
content:
|
|
583
|
+
application/json:
|
|
584
|
+
schema:
|
|
585
|
+
type: object
|
|
586
|
+
required:
|
|
587
|
+
- url
|
|
588
|
+
- events
|
|
589
|
+
properties:
|
|
590
|
+
url:
|
|
591
|
+
type: string
|
|
592
|
+
format: uri
|
|
593
|
+
example: "https://your-app.com/webhook"
|
|
594
|
+
events:
|
|
595
|
+
type: array
|
|
596
|
+
items:
|
|
597
|
+
type: string
|
|
598
|
+
enum:
|
|
599
|
+
- resource.created
|
|
600
|
+
- resource.updated
|
|
601
|
+
- resource.deleted
|
|
602
|
+
secret:
|
|
603
|
+
type: string
|
|
604
|
+
description: Shared secret for HMAC signature verification
|
|
605
|
+
callbacks:
|
|
606
|
+
onEvent:
|
|
607
|
+
'{$request.body#/url}':
|
|
608
|
+
post:
|
|
609
|
+
summary: Webhook event payload
|
|
610
|
+
requestBody:
|
|
611
|
+
content:
|
|
612
|
+
application/json:
|
|
613
|
+
schema:
|
|
614
|
+
type: object
|
|
615
|
+
properties:
|
|
616
|
+
event:
|
|
617
|
+
type: string
|
|
618
|
+
example: "resource.created"
|
|
619
|
+
timestamp:
|
|
620
|
+
type: string
|
|
621
|
+
format: date-time
|
|
622
|
+
data:
|
|
623
|
+
type: object
|
|
624
|
+
responses:
|
|
625
|
+
'200':
|
|
626
|
+
description: Acknowledged
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
## Health Check Endpoint
|
|
630
|
+
|
|
631
|
+
```yaml
|
|
632
|
+
paths:
|
|
633
|
+
/health:
|
|
634
|
+
get:
|
|
635
|
+
tags: [System]
|
|
636
|
+
summary: Health check
|
|
637
|
+
operationId: healthCheck
|
|
638
|
+
security: []
|
|
639
|
+
responses:
|
|
640
|
+
'200':
|
|
641
|
+
description: Service is healthy
|
|
642
|
+
content:
|
|
643
|
+
application/json:
|
|
644
|
+
schema:
|
|
645
|
+
type: object
|
|
646
|
+
properties:
|
|
647
|
+
status:
|
|
648
|
+
type: string
|
|
649
|
+
enum: [healthy, degraded]
|
|
650
|
+
example: healthy
|
|
651
|
+
version:
|
|
652
|
+
type: string
|
|
653
|
+
example: "1.2.3"
|
|
654
|
+
uptime:
|
|
655
|
+
type: integer
|
|
656
|
+
description: Uptime in seconds
|
|
657
|
+
example: 86400
|
|
658
|
+
dependencies:
|
|
659
|
+
type: object
|
|
660
|
+
properties:
|
|
661
|
+
database:
|
|
662
|
+
type: string
|
|
663
|
+
enum: [connected, disconnected]
|
|
664
|
+
cache:
|
|
665
|
+
type: string
|
|
666
|
+
enum: [connected, disconnected]
|
|
667
|
+
```
|