feat(bmm): add API design workflow with OpenAPI 3.0 support

- Add workflow.yaml for contract-first API design
- Add instructions.md with detailed design process
- Add openapi.template.yaml as starting template
- Add api-checklist.md for design validation
This commit is contained in:
Ibrahim Elsahafy 2025-12-31 21:07:29 +04:00
parent 4284f80a9a
commit 8a3ba98f16
4 changed files with 932 additions and 0 deletions

View File

@ -0,0 +1,117 @@
# API Design Checklist
## Resource Design
- [ ] Resources use plural nouns (users, orders, products)
- [ ] Resource names are lowercase with hyphens (user-profiles)
- [ ] Relationships expressed via nesting or links
- [ ] No verbs in resource paths (use HTTP methods instead)
## HTTP Methods
- [ ] GET for reading (no side effects)
- [ ] POST for creating new resources
- [ ] PUT for full resource replacement
- [ ] PATCH for partial updates
- [ ] DELETE for removing resources
- [ ] HEAD for metadata requests (if needed)
- [ ] OPTIONS for CORS preflight (automatic)
## Status Codes
- [ ] 200 OK for successful GET/PUT/PATCH
- [ ] 201 Created for successful POST
- [ ] 204 No Content for successful DELETE
- [ ] 400 Bad Request for malformed requests
- [ ] 401 Unauthorized for missing/invalid auth
- [ ] 403 Forbidden for insufficient permissions
- [ ] 404 Not Found for missing resources
- [ ] 409 Conflict for state conflicts
- [ ] 422 Unprocessable Entity for validation errors
- [ ] 429 Too Many Requests for rate limiting
- [ ] 500 Internal Server Error (avoid exposing details)
## Request Design
- [ ] Content-Type headers required for POST/PUT/PATCH
- [ ] Accept headers for content negotiation
- [ ] Query parameters for filtering/sorting/pagination
- [ ] Path parameters for resource identifiers
- [ ] Request body validation documented
## Response Design
- [ ] Consistent envelope structure (data, meta, links, error)
- [ ] Timestamps in ISO 8601 format
- [ ] IDs as strings (UUIDs recommended)
- [ ] Pagination for list endpoints
- [ ] HATEOAS links where appropriate
## Pagination
- [ ] Page-based or cursor-based pagination
- [ ] Default and maximum limits defined
- [ ] Total count available
- [ ] Navigation links included
## Filtering & Sorting
- [ ] Filter syntax documented
- [ ] Sortable fields specified
- [ ] Default sort order defined
- [ ] Multiple sort fields supported
## Authentication
- [ ] Auth method documented (Bearer, API Key, OAuth2)
- [ ] Token format specified (JWT structure)
- [ ] Token expiration documented
- [ ] Refresh token flow if applicable
## Authorization
- [ ] Per-endpoint permissions documented
- [ ] Role-based access defined
- [ ] Resource ownership rules clear
## Versioning
- [ ] Versioning strategy chosen (URL, header, parameter)
- [ ] Major version in URL (/v1/, /v2/)
- [ ] Deprecation policy documented
- [ ] Breaking changes defined
## Error Handling
- [ ] Error response format consistent
- [ ] Error codes meaningful and documented
- [ ] Validation errors include field details
- [ ] No sensitive info in error messages
## Security
- [ ] HTTPS required
- [ ] Rate limiting implemented
- [ ] CORS properly configured
- [ ] Input validation on all fields
- [ ] SQL injection prevention
- [ ] No sensitive data in URLs
## Documentation
- [ ] OpenAPI 3.0+ specification complete
- [ ] All endpoints documented
- [ ] Request/response examples provided
- [ ] Authentication documented
- [ ] Error codes listed
## Testing
- [ ] Mock server available
- [ ] Example requests for each endpoint
- [ ] Postman/Insomnia collection exported
- [ ] SDK generation tested
---
## Quick Validation
```bash
# Validate OpenAPI spec
npx @stoplight/spectral-cli lint api-spec.yaml
# Alternative validation
npx swagger-cli validate api-spec.yaml
# Generate types (TypeScript)
npx openapi-typescript api-spec.yaml -o types.d.ts
# Start mock server
npx @stoplight/prism-cli mock api-spec.yaml
```

View File

@ -0,0 +1,309 @@
# API Design Workflow Instructions
## Overview
Design APIs using a contract-first approach. This workflow produces OpenAPI 3.0+ specifications, mock server configurations, and client SDK generation guidance.
## Workflow Steps
### Step 1: Context Loading
**Load existing documentation:**
1. Load PRD for feature requirements
2. Load Architecture document for system design
3. Load project-context.md for coding standards
4. Identify existing API patterns (if any)
### Step 2: API Style Selection
**Ask user for API style:**
```
API Style Selection
Available styles:
1. [rest] RESTful API (OpenAPI 3.0+)
2. [graphql] GraphQL Schema
3. [grpc] gRPC/Protocol Buffers
4. [websocket] WebSocket Event Schema
Select style [1-4]:
```
### Step 3: Resource Identification
**For REST APIs, identify resources:**
1. Extract nouns from PRD (users, orders, products, etc.)
2. Map to REST resources
3. Identify relationships (1:1, 1:N, N:N)
4. Determine resource hierarchy
**Questions to ask:**
- What are the main entities in this system?
- How do entities relate to each other?
- What operations are needed for each entity?
- Are there any batch operations required?
### Step 4: Endpoint Design
**For each resource, design endpoints:**
| Operation | Method | Path Pattern | Example |
|-----------|--------|--------------|---------|
| List | GET | /resources | GET /users |
| Create | POST | /resources | POST /users |
| Read | GET | /resources/{id} | GET /users/123 |
| Update | PUT/PATCH | /resources/{id} | PATCH /users/123 |
| Delete | DELETE | /resources/{id} | DELETE /users/123 |
| Nested | GET | /resources/{id}/subs | GET /users/123/orders |
**Naming conventions:**
- Use plural nouns for resources
- Use kebab-case for multi-word resources
- Use path parameters for identifiers
- Use query parameters for filtering/pagination
### Step 5: Request/Response Design
**For each endpoint, define:**
1. **Request body schema** (POST/PUT/PATCH)
- Required vs optional fields
- Data types and formats
- Validation rules (min/max, pattern, enum)
2. **Response schema**
- Success response structure
- Error response structure
- Pagination format
3. **Headers**
- Authentication headers
- Content-Type
- Custom headers
**Standard response format:**
```json
{
"data": { ... },
"meta": {
"page": 1,
"limit": 20,
"total": 100
},
"links": {
"self": "/users?page=1",
"next": "/users?page=2"
}
}
```
**Standard error format:**
```json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{ "field": "email", "message": "Invalid email format" }
]
}
}
```
### Step 6: Authentication & Authorization
**Define security scheme:**
```yaml
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
apiKey:
type: apiKey
in: header
name: X-API-Key
oauth2:
type: oauth2
flows:
authorizationCode:
authorizationUrl: /oauth/authorize
tokenUrl: /oauth/token
scopes:
read: Read access
write: Write access
```
**Apply security to endpoints:**
- Public endpoints (no auth)
- Authenticated endpoints (user token)
- Admin-only endpoints (role-based)
### Step 7: Generate OpenAPI Specification
**Create OpenAPI 3.0+ document:**
```yaml
openapi: 3.0.3
info:
title: {project_name} API
version: 1.0.0
description: |
{api_description}
servers:
- url: https://api.example.com/v1
description: Production
- url: https://staging-api.example.com/v1
description: Staging
- url: http://localhost:3000/v1
description: Development
paths:
/resources:
get:
summary: List resources
operationId: listResources
tags:
- Resources
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/limit'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/ResourceList'
components:
schemas:
Resource:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
required:
- id
- name
parameters:
page:
name: page
in: query
schema:
type: integer
default: 1
limit:
name: limit
in: query
schema:
type: integer
default: 20
maximum: 100
```
### Step 8: API Documentation
**Generate API design document with:**
1. **Overview**
- API purpose and scope
- Base URL and versioning strategy
- Authentication methods
2. **Quick Start**
- Getting API credentials
- Making first request
- Common patterns
3. **Resource Reference**
- Detailed endpoint documentation
- Request/response examples
- Error codes
4. **Best Practices**
- Rate limiting guidance
- Pagination recommendations
- Error handling
### Step 9: Mock Server Guidance
**Provide mock server setup:**
```bash
# Using Prism (OpenAPI)
npm install -g @stoplight/prism-cli
prism mock api-spec.yaml
# Using json-server (simple)
npm install -g json-server
json-server --watch db.json
# Using MSW (frontend mocking)
npm install msw --save-dev
```
**Include sample mock data:**
```json
{
"users": [
{ "id": "1", "name": "Alice", "email": "alice@example.com" },
{ "id": "2", "name": "Bob", "email": "bob@example.com" }
]
}
```
### Step 10: SDK Generation Guidance
**Client SDK generation options:**
```bash
# OpenAPI Generator
npx @openapitools/openapi-generator-cli generate \
-i api-spec.yaml \
-g typescript-axios \
-o ./sdk
# Available generators:
# - typescript-axios
# - typescript-fetch
# - python
# - go
# - java
# - csharp
```
**Type generation (TypeScript):**
```bash
# Using openapi-typescript
npx openapi-typescript api-spec.yaml -o types.d.ts
```
### Step 11: Validation Checklist
Before completing:
- [ ] All PRD features have corresponding endpoints
- [ ] Resource naming follows conventions
- [ ] Request/response schemas complete
- [ ] Authentication defined for protected endpoints
- [ ] Error responses documented
- [ ] Pagination implemented for list endpoints
- [ ] OpenAPI spec validates (use swagger-cli validate)
- [ ] Examples provided for complex endpoints
### Step 12: Output Files
**Save to:**
- OpenAPI spec: `{output_file}` (api-spec.yaml)
- API design doc: `{output_doc}` (api-design.md)
**Notify user with:**
- Summary of endpoints created
- Link to specification file
- Mock server quick start
- Next steps (implementation, SDK generation)

View File

@ -0,0 +1,467 @@
openapi: 3.0.3
info:
title: "{{project_name}} API"
version: "{{api_version}}"
description: |
{{api_description}}
## Authentication
{{auth_description}}
## Rate Limiting
{{rate_limit_description}}
contact:
name: API Support
email: api@example.com
license:
name: MIT
url: https://opensource.org/licenses/MIT
servers:
- url: https://api.{{domain}}/v{{major_version}}
description: Production
- url: https://staging-api.{{domain}}/v{{major_version}}
description: Staging
- url: http://localhost:{{port}}/v{{major_version}}
description: Development
tags:
# Define tags for each resource group
- name: Authentication
description: Authentication and authorization endpoints
- name: Users
description: User management operations
# Add more tags as needed
paths:
# Authentication endpoints
/auth/login:
post:
summary: Authenticate user
operationId: login
tags:
- Authentication
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LoginRequest'
responses:
'200':
description: Authentication successful
content:
application/json:
schema:
$ref: '#/components/schemas/AuthResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'422':
$ref: '#/components/responses/ValidationError'
/auth/logout:
post:
summary: Logout user
operationId: logout
tags:
- Authentication
security:
- bearerAuth: []
responses:
'204':
description: Logout successful
'401':
$ref: '#/components/responses/Unauthorized'
# Resource template - copy and customize
/resources:
get:
summary: List resources
operationId: listResources
tags:
- Resources
security:
- bearerAuth: []
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/limit'
- $ref: '#/components/parameters/sort'
- $ref: '#/components/parameters/filter'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/ResourceListResponse'
'401':
$ref: '#/components/responses/Unauthorized'
post:
summary: Create resource
operationId: createResource
tags:
- Resources
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateResourceRequest'
responses:
'201':
description: Resource created
content:
application/json:
schema:
$ref: '#/components/schemas/ResourceResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'422':
$ref: '#/components/responses/ValidationError'
/resources/{id}:
parameters:
- $ref: '#/components/parameters/resourceId'
get:
summary: Get resource by ID
operationId: getResource
tags:
- Resources
security:
- bearerAuth: []
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/ResourceResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
patch:
summary: Update resource
operationId: updateResource
tags:
- Resources
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateResourceRequest'
responses:
'200':
description: Resource updated
content:
application/json:
schema:
$ref: '#/components/schemas/ResourceResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationError'
delete:
summary: Delete resource
operationId: deleteResource
tags:
- Resources
security:
- bearerAuth: []
responses:
'204':
description: Resource deleted
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: JWT authentication token
apiKey:
type: apiKey
in: header
name: X-API-Key
description: API key for service-to-service calls
parameters:
page:
name: page
in: query
description: Page number for pagination
schema:
type: integer
minimum: 1
default: 1
limit:
name: limit
in: query
description: Number of items per page
schema:
type: integer
minimum: 1
maximum: 100
default: 20
sort:
name: sort
in: query
description: Sort field and direction (e.g., -createdAt for descending)
schema:
type: string
example: "-createdAt"
filter:
name: filter
in: query
description: Filter expression
schema:
type: string
example: "status:active"
resourceId:
name: id
in: path
required: true
description: Resource identifier
schema:
type: string
format: uuid
schemas:
# Authentication schemas
LoginRequest:
type: object
required:
- email
- password
properties:
email:
type: string
format: email
password:
type: string
format: password
minLength: 8
AuthResponse:
type: object
properties:
accessToken:
type: string
refreshToken:
type: string
expiresIn:
type: integer
description: Token expiry in seconds
tokenType:
type: string
default: Bearer
# Resource schemas (template)
Resource:
type: object
properties:
id:
type: string
format: uuid
readOnly: true
name:
type: string
minLength: 1
maxLength: 255
description:
type: string
status:
type: string
enum: [active, inactive, archived]
default: active
createdAt:
type: string
format: date-time
readOnly: true
updatedAt:
type: string
format: date-time
readOnly: true
required:
- name
CreateResourceRequest:
allOf:
- $ref: '#/components/schemas/Resource'
- type: object
required:
- name
UpdateResourceRequest:
type: object
properties:
name:
type: string
description:
type: string
status:
type: string
enum: [active, inactive, archived]
ResourceResponse:
type: object
properties:
data:
$ref: '#/components/schemas/Resource'
ResourceListResponse:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Resource'
meta:
$ref: '#/components/schemas/PaginationMeta'
links:
$ref: '#/components/schemas/PaginationLinks'
# Pagination
PaginationMeta:
type: object
properties:
page:
type: integer
limit:
type: integer
total:
type: integer
totalPages:
type: integer
PaginationLinks:
type: object
properties:
self:
type: string
format: uri
first:
type: string
format: uri
prev:
type: string
format: uri
nullable: true
next:
type: string
format: uri
nullable: true
last:
type: string
format: uri
# Error schemas
Error:
type: object
properties:
error:
type: object
properties:
code:
type: string
message:
type: string
details:
type: array
items:
type: object
properties:
field:
type: string
message:
type: string
responses:
Unauthorized:
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: UNAUTHORIZED
message: Authentication required
Forbidden:
description: Permission denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: FORBIDDEN
message: Permission denied
NotFound:
description: Resource not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: NOT_FOUND
message: Resource not found
ValidationError:
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: VALIDATION_ERROR
message: Request validation failed
details:
- field: email
message: Invalid email format
RateLimitExceeded:
description: Rate limit exceeded
headers:
X-RateLimit-Limit:
schema:
type: integer
X-RateLimit-Remaining:
schema:
type: integer
X-RateLimit-Reset:
schema:
type: integer
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: RATE_LIMIT_EXCEEDED
message: Too many requests

View File

@ -0,0 +1,39 @@
# API Design Workflow
name: create-api-spec
description: "Contract-first API design workflow producing OpenAPI 3.0+ specifications with mock server guidance and client SDK generation recommendations"
author: "BMAD"
version: "1.0.0"
# Configuration sources
config_source: "{project-root}/_bmad/bmm/config.yaml"
user_name: "{config_source}:user_name"
communication_language: "{config_source}:communication_language"
user_skill_level: "{config_source}:user_skill_level"
document_output_language: "{config_source}:document_output_language"
planning_artifacts: "{config_source}:planning_artifacts"
output_folder: "{planning_artifacts}"
date: system-generated
# Workflow components
installed_path: "{project-root}/_bmad/bmm/workflows/3-solutioning/create-api-spec"
instructions: "{installed_path}/instructions.md"
template: "{installed_path}/openapi.template.yaml"
checklist: "{installed_path}/api-checklist.md"
# Input references
prd_doc: "{planning_artifacts}/*prd*.md"
architecture_doc: "{planning_artifacts}/*architecture*.md"
project_context: "**/project-context.md"
# Output
output_file: "{output_folder}/api-spec.yaml"
output_doc: "{output_folder}/api-design.md"
# API styles supported
api_styles:
- rest # RESTful API
- graphql # GraphQL schema
- grpc # Protocol Buffers
- websocket # WebSocket events
standalone: true