--- name: be-api-design description: "Backend Agent 使用此技能設計 API 規格。根據 PRD 產出 OpenAPI 3.0 規格,包含端點、請求/回應結構、錯誤處理。觸發時機:PRD 通過後(Stage 4)。" --- # /be-api-design — API 設計 Backend Agent 使用此技能設計 API 規格。 ## 職責 1. 分析 PRD 中的功能性需求 2. 使用 `design-an-interface` 探索多種 API 設計方案 3. 設計 RESTful API 端點 4. 定義請求/回應 schema 5. 設計錯誤處理機制 6. 產出 OpenAPI 3.0 規格 ## 輸入 - PRD 文件 (`docs/prd/{date}-{feature}.md`) - 現有 API 風格 (專案中現有的 API 規格) - 資料模型上下文 ## 輸出 - API 規格文件: `docs/api/{date}-{feature}.yaml` (OpenAPI 3.0) ## 流程 ``` 讀取 PRD ↓ 識別資源與操作 ↓ 呼叫 design-an-interface 探索 2-3 種設計方案 ↓ 選定最佳方案 ↓ 定義 OpenAPI Schema ↓ 設計錯誤處理 ↓ 安全性審查 ↓ 產出 OpenAPI 文件 ``` ### 步驟說明 **1. 讀取 PRD** 從 PRD 中提取所有功能性需求,識別: - 資源(名詞):使用者、訂單、商品等 - 操作(動詞):建立、讀取、更新、刪除等 - 關係:資源之間的關聯(一對多、多對多) - 非功能性需求:分頁、速率限制、認證等 **2. 識別資源與操作** 將功能性需求映射為 RESTful 資源: - 每個名詞 → 潛在資源 - 每個動詞 → HTTP method - 每個關係 → 巢狀資源或獨立端點 **3. 呼叫 design-an-interface** 使用 `design-an-interface` 技能,產生 2-3 種截然不同的 API 設計方案: - 方案 A:最小化方法數(每個資源 1-3 個端點) - 方案 B:最大化彈性(支援多種使用情境) - 方案 C:最佳化最常見的操作 比較各方案的優劣,選定最佳設計。 **4. 定義 OpenAPI Schema** 使用下方模板產出完整的 OpenAPI 3.0 規格。 **5. 安全性審查** 確認所有端點都有適當的認證機制和權限控制。 **6. 產出文件** 儲存至 `docs/api/{date}-{feature}.yaml`。 ## 設計原則 ### RESTful 設計 ```yaml 資源導向: - URL 代表資源,而非動作 - HTTP 方法代表動作 範例: GET /api/v1/users # 列出使用者 GET /api/v1/users/{id} # 取得特定使用者 POST /api/v1/users # 建立使用者 PUT /api/v1/users/{id} # 完整更新 PATCH /api/v1/users/{id} # 部分更新 DELETE /api/v1/users/{id} # 刪除使用者 巢狀資源: GET /api/v1/users/{id}/orders # 取得使用者的訂單 POST /api/v1/users/{id}/orders # 為使用者建立訂單 ``` ### HTTP 狀態碼 ```yaml 成功: 200: OK # GET, PUT, PATCH, DELETE 成功 201: Created # POST 成功建立資源 204: No Content # DELETE 成功,無回應內容 客戶端錯誤: 400: Bad Request # 請求格式錯誤 401: Unauthorized # 未認證 403: Forbidden # 無權限 404: Not Found # 資源不存在 409: Conflict # 資源衝突 (如重複) 422: Unprocessable Entity # 驗證錯誤 429: Too Many Requests # 速率限制 伺服器錯誤: 500: Internal Server Error # 伺服器內部錯誤 502: Bad Gateway # 上游服務錯誤 503: Service Unavailable # 服務暫時不可用 ``` ### 回應格式 ```yaml 成功回應: type: object properties: data: type: object meta: type: object properties: page: type: integer limit: type: integer total: type: integer total_pages: type: integer 錯誤回應: 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 ``` ## OpenAPI 3.0 模板 ```yaml openapi: 3.0.3 info: title: {API 名稱} version: 1.0.0 description: | {描述} Related PRD: {PRD 連結} servers: - url: https://api.example.com/v1 description: Production - url: https://staging-api.example.com/v1 description: Staging paths: /users: get: summary: 列出使用者 tags: - Users parameters: - name: page in: query schema: type: integer default: 1 - name: limit in: query schema: type: integer default: 20 maximum: 100 - name: search in: query schema: type: string responses: '200': description: 成功 content: application/json: schema: $ref: '#/components/schemas/UserListResponse' '401': $ref: '#/components/responses/Unauthorized' '500': $ref: '#/components/responses/InternalError' post: summary: 建立使用者 tags: - Users requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateUserRequest' responses: '201': description: 建立成功 content: application/json: schema: $ref: '#/components/schemas/UserResponse' '400': $ref: '#/components/responses/BadRequest' '422': $ref: '#/components/responses/ValidationError' /users/{id}: parameters: - name: id in: path required: true schema: type: string get: summary: 取得使用者 tags: - Users responses: '200': description: 成功 content: application/json: schema: $ref: '#/components/schemas/UserResponse' '404': $ref: '#/components/responses/NotFound' put: summary: 完整更新使用者 tags: - Users requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateUserRequest' responses: '200': description: 更新成功 content: application/json: schema: $ref: '#/components/schemas/UserResponse' '404': $ref: '#/components/responses/NotFound' '422': $ref: '#/components/responses/ValidationError' patch: summary: 部分更新使用者 tags: - Users requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PatchUserRequest' responses: '200': description: 更新成功 content: application/json: schema: $ref: '#/components/schemas/UserResponse' '404': $ref: '#/components/responses/NotFound' delete: summary: 刪除使用者 tags: - Users responses: '204': description: 刪除成功 '404': $ref: '#/components/responses/NotFound' components: schemas: User: type: object properties: id: type: string example: "usr_123456" email: type: string format: email example: "user@example.com" name: type: string example: "John Doe" status: type: string enum: [active, inactive, suspended] example: "active" created_at: type: string format: date-time updated_at: type: string format: date-time required: - id - email - name - status - created_at - updated_at CreateUserRequest: type: object properties: email: type: string format: email password: type: string minLength: 8 name: type: string minLength: 1 maxLength: 100 required: - email - password - name UpdateUserRequest: type: object properties: email: type: string format: email name: type: string minLength: 1 maxLength: 100 status: type: string enum: [active, inactive] PatchUserRequest: type: object properties: name: type: string minLength: 1 maxLength: 100 status: type: string enum: [active, inactive] UserResponse: type: object properties: data: $ref: '#/components/schemas/User' UserListResponse: type: object properties: data: type: array items: $ref: '#/components/schemas/User' meta: type: object properties: page: type: integer limit: type: integer total: type: integer total_pages: type: integer 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: BadRequest: description: 請求格式錯誤 content: application/json: schema: $ref: '#/components/schemas/Error' Unauthorized: description: 未認證 content: application/json: schema: $ref: '#/components/schemas/Error' NotFound: description: 資源不存在 content: application/json: schema: $ref: '#/components/schemas/Error' ValidationError: description: 驗證錯誤 content: application/json: schema: $ref: '#/components/schemas/Error' InternalError: description: 伺服器內部錯誤 content: application/json: schema: $ref: '#/components/schemas/Error' securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT security: - bearerAuth: [] ``` ## 設計檢查清單 ### 安全性 - [ ] 所有端點都有適當的認證機制 - [ ] 輸入驗證完整 - [ ] 速率限制設計 - [ ] CORS 配置 ### 效能 - [ ] 分頁支援 - [ ] 快取策略 - [ ] 批次操作支援 ### 可靠性 - [ ] 錯誤回應格式統一 - [ ] 重試機制建議 - [ ] 冪等性設計 ### 一致性 - [ ] 命名規範一致 (資源用名詞複數) - [ ] 回應格式一致 (data/meta/error 結構) - [ ] 篩選/排序/分頁參數一致 ## 相依技能 - **前置**: `write-a-prd` (PRD 通過後) - **輔助**: `design-an-interface` (探索多種設計方案) - **後續**: `dba-schema` (DB Schema 設計) - **退回**: 可退回 `write-a-prd` 修改需求 ## 退回機制 ``` Design Review 退回 API 設計 ↓ 修改 OpenAPI 規格 ↓ 重新提交 (或重新呼叫 design-an-interface) DBA Agent 發現 Schema 衝突 ↓ 協商調整 domain model 或 API 回應格式 ↓ 更新 OpenAPI 規格 ```