Claude-skill-registry design-api
API設計エージェント - リファクタリング後のマイクロサービスAPI設計。REST/GraphQL/gRPC/AsyncAPIの仕様書、API Gateway設計、認証・認可設計を策定。/design-api [対象パス] で呼び出し。
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/design-api" ~/.claude/skills/majiayu000-claude-skill-registry-design-api && rm -rf "$T"
manifest:
skills/data/design-api/SKILL.mdsource content
API Design Agent
リファクタリング後のマイクロサービスAPIを設計するエージェントです。
概要
このエージェントは、マイクロサービス設計の結果をもとに、以下を策定します:
- API仕様設計 - REST/GraphQL/gRPC/AsyncAPIの仕様書
- API Gateway設計 - ルーティング、認証、レート制限
- 認証・認可設計 - OAuth2/OIDC、RBAC/ABAC
- API管理戦略 - バージョニング、ドキュメント、テスト
前提条件
以下の中間ファイルが存在すること:
配下の分析結果01_analysis/03_design/target-architecture.md
(存在する場合)03_design/scalardb-schema.md
出力先ディレクトリ
設計結果は
reports/03_design/ に出力します。
重要: 各ステップ完了時に即座にファイルを出力してください。
reports/03_design/ ├── api-design-overview.md # API設計概要 ├── api-specifications/ # API仕様書ディレクトリ │ ├── openapi/ # OpenAPI (REST) 仕様 │ │ └── [service]-api.yaml │ ├── graphql/ # GraphQL スキーマ │ │ └── [service]-schema.graphql │ ├── grpc/ # gRPC プロトコル定義 │ │ └── [service].proto │ └── asyncapi/ # AsyncAPI (イベント) 仕様 │ └── [service]-events.yaml ├── api-gateway-design.md # API Gateway設計 └── api-security-design.md # 認証・認可設計
実行プロンプト
あなたはAPI設計の専門家です。以下の手順で設計を実行してください。
Step 1: API設計原則の確認
API設計の基本原則:
| 原則 | 説明 |
|---|---|
| Contract First | 実装前にAPI仕様を定義 |
| Consumer Driven | 利用者のニーズを優先 |
| Consistency | 命名規則、エラー形式の統一 |
| Versioning | 後方互換性を保つバージョン管理 |
| Security by Design | セキュリティを最初から考慮 |
| Documentation | 常に最新のドキュメント |
| Observability | トレーシング、ログ、メトリクス |
Step 2: API通信パターンの選定
各サービス・ユースケースに適した通信パターンを選定:
## API通信パターン選定 ### サービス別API方式 | サービス | 外部API | 内部API | イベント | 選定理由 | |---------|--------|--------|---------|---------| | Order Service | REST | gRPC | Kafka | CRUDメイン、高性能内部通信 | | Product Service | GraphQL | gRPC | - | 柔軟なクエリ要件 | | Notification Service | - | gRPC | Kafka | イベント駆動 | ### 通信パターン判断基準 | パターン | 適用条件 | メリット | デメリット | |---------|---------|---------|----------| | REST | CRUD操作、外部公開 | 標準的、ツール豊富 | オーバーフェッチ | | GraphQL | 複雑なクエリ、BFF | 柔軟、効率的 | 学習コスト | | gRPC | 内部通信、高性能 | 高速、型安全 | ブラウザ非対応 | | AsyncAPI | イベント駆動 | 疎結合、スケーラブル | 複雑性 |
Step 3: REST API設計(OpenAPI)
3.1 URL設計
# URL設計規則 paths: # リソース(複数形) /orders: get: 注文一覧取得 post: 注文作成 /orders/{orderId}: get: 注文詳細取得 put: 注文更新 delete: 注文削除 # サブリソース /orders/{orderId}/items: get: 注文明細一覧 post: 注文明細追加 # アクション(動詞が必要な場合) /orders/{orderId}/actions/cancel: post: 注文キャンセル
3.2 OpenAPI仕様テンプレート
openapi: 3.1.0 info: title: "[Service Name] API" version: "1.0.0" description: | [サービスの説明] contact: name: API Support email: api-support@example.com servers: - url: https://api.example.com/v1 description: Production - url: https://api-staging.example.com/v1 description: Staging tags: - name: orders description: 注文関連API paths: /orders: get: summary: 注文一覧取得 operationId: listOrders tags: [orders] parameters: - $ref: '#/components/parameters/PageSize' - $ref: '#/components/parameters/PageToken' - name: status in: query schema: $ref: '#/components/schemas/OrderStatus' responses: '200': description: 成功 content: application/json: schema: $ref: '#/components/schemas/OrderListResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' post: summary: 注文作成 operationId: createOrder tags: [orders] security: - bearerAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateOrderRequest' responses: '201': description: 作成成功 content: application/json: schema: $ref: '#/components/schemas/Order' '400': $ref: '#/components/responses/BadRequest' '409': $ref: '#/components/responses/Conflict' components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT parameters: PageSize: name: pageSize in: query schema: type: integer minimum: 1 maximum: 100 default: 20 PageToken: name: pageToken in: query schema: type: string schemas: Order: type: object required: [id, customerId, status, createdAt] properties: id: type: string format: uuid customerId: type: string format: uuid status: $ref: '#/components/schemas/OrderStatus' items: type: array items: $ref: '#/components/schemas/OrderItem' totalAmount: type: integer description: 合計金額(円) createdAt: type: string format: date-time updatedAt: type: string format: date-time OrderStatus: type: string enum: [PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED] Error: type: object required: [code, message] properties: code: type: string description: エラーコード message: type: string description: エラーメッセージ details: type: array items: type: object properties: field: type: string reason: type: string responses: BadRequest: description: リクエスト不正 content: application/json: schema: $ref: '#/components/schemas/Error' Unauthorized: description: 認証エラー content: application/json: schema: $ref: '#/components/schemas/Error' Conflict: description: 競合エラー content: application/json: schema: $ref: '#/components/schemas/Error'
3.3 エラーレスポンス設計
## エラーレスポンス標準 ### HTTPステータスコード | コード | 意味 | 使用場面 | |-------|-----|---------| | 400 | Bad Request | バリデーションエラー | | 401 | Unauthorized | 認証エラー | | 403 | Forbidden | 認可エラー | | 404 | Not Found | リソース不在 | | 409 | Conflict | 競合(楽観ロック失敗等) | | 422 | Unprocessable Entity | ビジネスルール違反 | | 429 | Too Many Requests | レート制限超過 | | 500 | Internal Server Error | サーバーエラー | | 503 | Service Unavailable | サービス一時停止 | ### エラーレスポンス形式 ```json { "code": "ORDER_ALREADY_CANCELLED", "message": "注文は既にキャンセルされています", "details": [ { "field": "orderId", "reason": "Order with id '123' is already in CANCELLED status" } ], "traceId": "abc123xyz", "timestamp": "2024-01-15T10:30:00Z" }
### Step 4: GraphQL設計 #### 4.1 スキーマ設計 ```graphql # schema.graphql """ 注文サービス GraphQL スキーマ """ type Query { """注文を取得""" order(id: ID!): Order """注文一覧を取得""" orders( filter: OrderFilter pagination: PaginationInput ): OrderConnection! """顧客の注文を取得""" ordersByCustomer(customerId: ID!): [Order!]! } type Mutation { """注文を作成""" createOrder(input: CreateOrderInput!): CreateOrderPayload! """注文をキャンセル""" cancelOrder(input: CancelOrderInput!): CancelOrderPayload! """注文ステータスを更新""" updateOrderStatus(input: UpdateOrderStatusInput!): UpdateOrderStatusPayload! } type Subscription { """注文ステータス変更を購読""" orderStatusChanged(orderId: ID!): OrderStatusChangedEvent! } # Types type Order implements Node { id: ID! customer: Customer! status: OrderStatus! items: [OrderItem!]! totalAmount: Money! createdAt: DateTime! updatedAt: DateTime! } type OrderItem { id: ID! product: Product! quantity: Int! unitPrice: Money! subtotal: Money! } type OrderConnection { edges: [OrderEdge!]! pageInfo: PageInfo! totalCount: Int! } type OrderEdge { node: Order! cursor: String! } enum OrderStatus { PENDING CONFIRMED SHIPPED DELIVERED CANCELLED } # Inputs input CreateOrderInput { customerId: ID! items: [OrderItemInput!]! shippingAddress: AddressInput! } input OrderItemInput { productId: ID! quantity: Int! } input OrderFilter { status: [OrderStatus!] customerId: ID createdAfter: DateTime createdBefore: DateTime } # Payloads type CreateOrderPayload { order: Order errors: [UserError!]! } type UserError { field: [String!] message: String! code: String! } # Scalars scalar DateTime scalar Money
4.2 GraphQL設計原則
## GraphQL設計原則 ### 命名規則 - Query: `order`, `orders`, `ordersByCustomer`(名詞) - Mutation: `createOrder`, `updateOrder`, `cancelOrder`(動詞+名詞) - Subscription: `orderStatusChanged`(過去分詞+Event) ### ペイロードパターン - Mutation結果は専用Payloadタイプを返す - errorsフィールドでユーザー向けエラーを返す - 成功時もエラー時も同じ型で返す ### ページネーション - Relay Connection仕様に準拠 - edges, pageInfo, totalCountを含む ### N+1問題対策 - DataLoaderパターンを使用 - @defer, @streamディレクティブの活用
Step 5: gRPC設計
5.1 Protocol Buffers定義
// order_service.proto syntax = "proto3"; package order.v1; option java_multiple_files = true; option java_package = "com.example.order.v1"; option go_package = "github.com/example/order/v1;orderv1"; import "google/protobuf/timestamp.proto"; import "google/protobuf/empty.proto"; // 注文サービス service OrderService { // 注文を作成 rpc CreateOrder(CreateOrderRequest) returns (CreateOrderResponse); // 注文を取得 rpc GetOrder(GetOrderRequest) returns (Order); // 注文一覧を取得 rpc ListOrders(ListOrdersRequest) returns (ListOrdersResponse); // 注文をキャンセル rpc CancelOrder(CancelOrderRequest) returns (Order); // 注文ステータスをストリーミング rpc WatchOrderStatus(WatchOrderStatusRequest) returns (stream OrderStatusEvent); } // メッセージ定義 message Order { string id = 1; string customer_id = 2; OrderStatus status = 3; repeated OrderItem items = 4; int64 total_amount = 5; // 金額は最小単位(円) google.protobuf.Timestamp created_at = 6; google.protobuf.Timestamp updated_at = 7; } message OrderItem { string id = 1; string product_id = 2; int32 quantity = 3; int64 unit_price = 4; } enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; ORDER_STATUS_CANCELLED = 5; } // リクエスト/レスポンス message CreateOrderRequest { string customer_id = 1; repeated CreateOrderItem items = 2; Address shipping_address = 3; } message CreateOrderItem { string product_id = 1; int32 quantity = 2; } message CreateOrderResponse { Order order = 1; } message GetOrderRequest { string id = 1; } message ListOrdersRequest { int32 page_size = 1; string page_token = 2; OrderFilter filter = 3; } message OrderFilter { repeated OrderStatus statuses = 1; string customer_id = 2; } message ListOrdersResponse { repeated Order orders = 1; string next_page_token = 2; int32 total_count = 3; } message CancelOrderRequest { string id = 1; string reason = 2; } message WatchOrderStatusRequest { string order_id = 1; } message OrderStatusEvent { string order_id = 1; OrderStatus previous_status = 2; OrderStatus current_status = 3; google.protobuf.Timestamp changed_at = 4; } message Address { string postal_code = 1; string prefecture = 2; string city = 3; string street = 4; string building = 5; }
5.2 gRPC設計原則
## gRPC設計原則 ### バージョニング - パッケージ名にバージョンを含める: `order.v1` - 破壊的変更時は新バージョン作成: `order.v2` ### フィールド番号 - 1-15: 頻繁に使用するフィールド(1バイト) - 16以降: それ以外のフィールド - 削除したフィールド番号は再利用しない ### エラーハンドリング - google.rpc.Statusを使用 - 詳細エラーはdetailsフィールドで返す ### ストリーミング - Server Streaming: 大量データ、リアルタイム更新 - Client Streaming: バッチ処理 - Bidirectional: チャット、リアルタイム同期
Step 6: AsyncAPI設計(イベント駆動)
# order-events.asyncapi.yaml asyncapi: 3.0.0 info: title: Order Events API version: 1.0.0 description: 注文サービスが発行するイベント servers: production: host: kafka.example.com:9092 protocol: kafka description: Production Kafka channels: order.created: address: order.created messages: orderCreated: $ref: '#/components/messages/OrderCreated' order.status.changed: address: order.status.changed messages: orderStatusChanged: $ref: '#/components/messages/OrderStatusChanged' order.cancelled: address: order.cancelled messages: orderCancelled: $ref: '#/components/messages/OrderCancelled' operations: publishOrderCreated: action: send channel: $ref: '#/channels/order.created' summary: 注文作成イベントを発行 publishOrderStatusChanged: action: send channel: $ref: '#/channels/order.status.changed' summary: 注文ステータス変更イベントを発行 components: messages: OrderCreated: name: OrderCreated title: 注文作成イベント contentType: application/json payload: $ref: '#/components/schemas/OrderCreatedPayload' headers: $ref: '#/components/schemas/EventHeaders' OrderStatusChanged: name: OrderStatusChanged title: 注文ステータス変更イベント contentType: application/json payload: $ref: '#/components/schemas/OrderStatusChangedPayload' headers: $ref: '#/components/schemas/EventHeaders' OrderCancelled: name: OrderCancelled title: 注文キャンセルイベント contentType: application/json payload: $ref: '#/components/schemas/OrderCancelledPayload' headers: $ref: '#/components/schemas/EventHeaders' schemas: EventHeaders: type: object required: [eventId, eventType, timestamp, source] properties: eventId: type: string format: uuid eventType: type: string timestamp: type: string format: date-time source: type: string correlationId: type: string format: uuid OrderCreatedPayload: type: object required: [orderId, customerId, items, totalAmount] properties: orderId: type: string format: uuid customerId: type: string format: uuid items: type: array items: $ref: '#/components/schemas/OrderItemPayload' totalAmount: type: integer OrderStatusChangedPayload: type: object required: [orderId, previousStatus, currentStatus] properties: orderId: type: string format: uuid previousStatus: $ref: '#/components/schemas/OrderStatus' currentStatus: $ref: '#/components/schemas/OrderStatus' reason: type: string OrderCancelledPayload: type: object required: [orderId, reason] properties: orderId: type: string format: uuid reason: type: string cancelledBy: type: string OrderItemPayload: type: object properties: productId: type: string quantity: type: integer unitPrice: type: integer OrderStatus: type: string enum: [PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED]
Step 7: API Gateway設計
このステップ完了時に出力:
reports/03_design/api-gateway-design.md
## API Gateway設計 ### アーキテクチャ ```mermaid graph TB subgraph External["外部"] Web[Web Client] Mobile[Mobile App] Partner[Partner System] end subgraph Gateway["API Gateway Layer"] Kong[Kong Gateway] subgraph Plugins Auth[認証プラグイン] RateLimit[レート制限] Transform[変換] Logging[ログ] end end subgraph Internal["内部サービス"] BFF[BFF Service] Order[Order Service] Product[Product Service] User[User Service] end Web --> Kong Mobile --> Kong Partner --> Kong Kong --> BFF Kong --> Order Kong --> Product Kong --> User
ルーティング設計
| パス | バックエンド | 認証 | レート制限 |
|---|---|---|---|
| Order Service | JWT | 100 req/min |
| Product Service | API Key | 1000 req/min |
| User Service | JWT | 50 req/min |
| BFF Service | JWT | 200 req/min |
| Partner API | mTLS | 500 req/min |
Kong設定例(DB-less)
# kong.yml _format_version: "3.0" services: - name: order-service url: http://order-service:8080 routes: - name: order-route paths: - /api/v1/orders strip_path: false plugins: - name: jwt - name: rate-limiting config: minute: 100 policy: local - name: correlation-id config: header_name: X-Correlation-ID generator: uuid - name: graphql-service url: http://bff-service:8080 routes: - name: graphql-route paths: - /graphql methods: - POST plugins: - name: jwt - name: request-size-limiting config: allowed_payload_size: 1 # MB consumers: - username: web-app jwt_secrets: - key: web-app-key algorithm: RS256 - username: partner-system keyauth_credentials: - key: partner-api-key-xxx
レート制限戦略
| クライアント種別 | 制限 | 超過時の対応 |
|---|---|---|
| 一般ユーザー | 100 req/min | 429 + Retry-After |
| プレミアムユーザー | 500 req/min | 429 + Retry-After |
| パートナー | 1000 req/min | 429 + 担当者通知 |
| 内部サービス | 制限なし | - |
### Step 8: 認証・認可設計 **このステップ完了時に出力**: `reports/03_design/api-security-design.md` ```markdown ## 認証・認可設計 ### 認証方式 | 方式 | 用途 | 実装 | |-----|-----|-----| | JWT (OAuth2) | ユーザー認証 | Keycloak | | API Key | パートナー認証 | Kong | | mTLS | サービス間認証 | Istio | | Service Account | 内部バッチ | Kubernetes SA | ### OAuth2フロー ```mermaid sequenceDiagram participant User participant WebApp participant Gateway as API Gateway participant Keycloak participant Service User->>WebApp: ログイン要求 WebApp->>Keycloak: 認可コードフロー開始 Keycloak->>User: ログイン画面 User->>Keycloak: 認証情報入力 Keycloak->>WebApp: 認可コード WebApp->>Keycloak: トークン要求 Keycloak->>WebApp: Access Token + Refresh Token WebApp->>Gateway: API要求 + Bearer Token Gateway->>Gateway: JWT検証 Gateway->>Service: 要求転送 + クレーム Service->>Gateway: レスポンス Gateway->>WebApp: レスポンス
JWTクレーム設計
{ "sub": "user-123", "iss": "https://auth.example.com", "aud": ["order-service", "product-service"], "exp": 1704067200, "iat": 1704063600, "roles": ["customer", "premium"], "permissions": ["orders:read", "orders:create"], "tenant_id": "tenant-abc", "metadata": { "customer_tier": "gold" } }
認可(RBAC)設計
| ロール | 権限 | 説明 |
|---|---|---|
| admin | | 全権限 |
| operator | , | 運用担当 |
| customer | , | 一般顧客 |
| partner | , | パートナー |
| viewer | | 閲覧のみ |
スコープ設計
scopes: orders:read: 注文の参照 orders:create: 注文の作成 orders:update: 注文の更新 orders:delete: 注文の削除 orders:read:own: 自分の注文のみ参照 products:read: 商品の参照 products:write: 商品の作成・更新 users:read: ユーザー情報の参照 users:write: ユーザー情報の更新
### Step 9: API バージョニング戦略 ```markdown ## APIバージョニング戦略 ### バージョニング方式 | 方式 | 例 | 採用 | |-----|---|-----| | URLパス | `/api/v1/orders` | ✅ 推奨 | | クエリパラメータ | `?version=1` | - | | ヘッダー | `Accept-Version: v1` | - | | Accept | `Accept: application/vnd.example.v1+json` | - | ### 採用方式: URLパスバージョニング **理由:** - 明示的で分かりやすい - キャッシュしやすい - ドキュメント化しやすい - API Gatewayでルーティングしやすい ### バージョン管理ルール | ルール | 説明 | |-------|------| | メジャーバージョン | 破壊的変更時にインクリメント(v1 → v2) | | 後方互換性 | フィールド追加は同一バージョン内で可 | | 非推奨期間 | 旧バージョンは最低6ヶ月間サポート | | サンセット | Sunset ヘッダーで廃止日を通知 | ### 非推奨通知 ```http HTTP/1.1 200 OK Deprecation: true Sunset: Sat, 01 Jul 2025 00:00:00 GMT Link: </api/v2/orders>; rel="successor-version"
### Step 10: API設計概要の出力 **最終出力**: `reports/03_design/api-design-overview.md` ### Step 11: Mermaid図の検証 出力したファイルのMermaid図を検証し、エラーがあれば修正: ```bash # 出力ファイルのMermaid検証 /fix-mermaid ./reports/03_design
検証項目:
- サブグラフ名が引用符で囲まれている(例:
)subgraph "API Gateway Layer" - sequenceDiagramの参加者名が有効(スペースを含む場合はエイリアス使用)
- 日本語ラベルが引用符で囲まれている
- sequenceDiagramの予約語(BOX等)が回避されている
## API設計概要 ### サービス別API一覧 | サービス | REST | GraphQL | gRPC | Events | 仕様書 | |---------|------|---------|------|--------|-------| | Order Service | ✅ | - | ✅ | ✅ | [OpenAPI](./api-specifications/openapi/order-api.yaml) | | Product Service | ✅ | ✅ | ✅ | - | [GraphQL](./api-specifications/graphql/product-schema.graphql) | | User Service | ✅ | - | ✅ | ✅ | [OpenAPI](./api-specifications/openapi/user-api.yaml) | | Notification Service | - | - | ✅ | ✅ | [AsyncAPI](./api-specifications/asyncapi/notification-events.yaml) | ### エンドポイント総覧 | エンドポイント | メソッド | サービス | 認証 | 説明 | |--------------|--------|---------|-----|------| | `/api/v1/orders` | GET | Order | JWT | 注文一覧 | | `/api/v1/orders` | POST | Order | JWT | 注文作成 | | `/api/v1/orders/{id}` | GET | Order | JWT | 注文詳細 | | `/api/v1/products` | GET | Product | API Key | 商品一覧 | | `/graphql` | POST | BFF | JWT | GraphQLエンドポイント | ### 共通仕様 - 認証: OAuth2 (JWT) - エラー形式: RFC 7807 Problem Details - ページネーション: Cursor-based - 日時形式: ISO 8601 (UTC) - 言語: Accept-Languageヘッダーで切り替え
出力フォーマット
api-design-overview.md
API設計概要(設計原則、サービス別API一覧、エンドポイント総覧、共通仕様)
api-specifications/
各サービスのAPI仕様書(OpenAPI、GraphQL、gRPC、AsyncAPI)
api-gateway-design.md
API Gateway設計(アーキテクチャ、ルーティング、レート制限、Kong設定)
api-security-design.md
認証・認可設計(認証方式、OAuth2フロー、JWT設計、RBAC)
ツール活用ガイドライン
コード解析
# 既存APIの抽出 mcp__serena__find_symbol で Controller/Handler クラスを検索 mcp__serena__get_symbols_overview でエンドポイント一覧を取得
仕様書検証
# OpenAPI検証 npx @stoplight/spectral-cli lint openapi.yaml # GraphQLスキーマ検証 npx graphql-inspector validate schema.graphql # AsyncAPI検証 npx @asyncapi/cli validate asyncapi.yaml
ドキュメント生成
# OpenAPI → HTML npx @redocly/cli build-docs openapi.yaml # GraphQL → ドキュメント npx graphql-markdown schema.graphql # AsyncAPI → HTML npx @asyncapi/cli generate fromTemplate asyncapi.yaml @asyncapi/html-template
アンチパターン
| アンチパターン | 問題 | 推奨 |
|---|---|---|
| 動詞URL | , | リソース名 + HTTPメソッド |
| ネストが深いURL | | 最大2階層まで |
| バージョンなし | 破壊的変更時に問題 | URLパスでバージョン管理 |
| 曖昧なエラー | | 構造化エラーレスポンス |
| 認証情報をURLに | | Authorizationヘッダー |