APIライニングと静解析
1)なぜリンクAPI
API-チームと外部インテグレータ間の契約。リンティングおよび静的解析:- 互換性のない変更と暗黙的な変更を防ぐ
- ステータス、エラー、ページネーション、セキュリティを統一する。
- 仕様を機械検証可能にし、予測可能にリリースします。
- レビューとオンボーディング時間のコストを削減します。
原則: "契約は自動的にチェックされます。グリーンリンティングのないPRは保持しません"
2)リンティング設備
1.契約:OpenAPI/AsyncAPI/GraphQL SDL、 Protobuf/Avro/JSONスキーマ。
2.実装:REST/gRPCペン、ミドルウェア、ステータスコード/ヘッダー。
3.インフラストラクチャ:セキュリティヘッダー、制限、キャッシュポリシー。
4.関連するアーティファクト:例、ポストマンコレクション、エラースキーム。
3) HTTP APIの基本ルール(推奨プロファイル)
3.1表記とURL
JSONボディのsnake_case、パスのkebab-case、またはkebab-case/'/v1/……'.
リソース-複数形:'/v1/payments'、ネスト-'/v1/wallets/{ id }/transactions'。
path-paramsとしての識別子:'/v1/payments/{ payment_id} '(type: string、 format: uuid)。
3.2メソッドとステータス
'GET'-200/206;'POST'-201(+'場所')、競合-409;検証-422;limits-429(+'Retry-After')。
エラーのために200を返さないでください。条件付きクエリ-304 by 'If-None-Match'。
3.3エラー(シングルフォーマット)
json
{ "code":"validation_error", "message":"amount must be ≥ 1", "trace_id":"...", "details":[{"field":"amount","reason":"min:1"}] }
必須:'code'、 'message'、 'trace_id';locale-'Content-Language'を使用します。
3.4ペジネーション/フィルタ
カーソルベース:'page_size'、 'page_token'、 'next_page_token'。
フィルタとソート-'parameters'で文書化されたホワイトリスト。
3.5安全性
均一なセキュリティスキーム:OAuth2/OIDCスコープまたはmTLS;'http' ('https'のみ)を拒否します。
センシティブなヘッダー、例のマスクトークンを返さないでください。
3.6制限と寸法
タイトル/ボディリミット:413/414/431;許可されている最大値を文書化します。
4)ツールとエコシステム
4.1 OpenAPI
Spectral (JSON/YAML lint)、 Redocly linter、 oas-diff/openapi-diff (semantic diff)、 schemathesis/dredd (checks in progress)。
4.2 Protobuf/gRPC
buf (lint+breaking check)、 protolint、 SDKジェネレータ;分析のためのgnostic。
4.3 GraphQL
graphql-schema-linter、 graphql-inspector(壊れている)。
4.4コードリンタとSAST
ESLint、 golangci-lint、 Detekt/Ktlint、 Pylint/Flake8、 Semgrep (API臭いとセキュリティテンプレート)。
5)規則の例: Spectral/Redocly
5.1スペクトル(例'スペクトル。yaml')
yaml extends: ["spectral:oas", "spectral:asyncapi"]
rules:
openapi-tags: off info-contact: error no-http: error path-kebab-case:
description: "Paths must be kebab-case"
given: "$.paths[]~"
severity: error then:
function: pattern functionOptions: { match: "^/(?:[a-z0-9]+(?--[a-z0-9]+)/?)+$" }
response-error-schema:
description: "Error responses must use standard schema"
given: "$.paths[][].responses[?(@property >= '400')]"
then:
field: "content.application/json.schema.$ref"
function: truthy id-as-uuid:
given: "$..parameters[?(@.name =~ /.id$/i)]"
then:
field: schema.format function: enumeration functionOptions: { values: ["uuid"] }
5.2 Redocly (fragment '。redocly。yaml')
yaml apis:
main: openapi.yaml lint:
extends:
- recommended rules:
no-ambiguous-paths: error operation-2xx-only: off operation-success-response:
severity: error where:
subject: response filterInParentKeys: ["200","201","204"]
operation-security-defined: error no-plain-http: error
6) Protobuf/gRPC: bufのプロフィール
6.1 'buf。yaml'
yaml version: v2 modules:
- path: proto lint:
use:
- DEFAULT except:
- PACKAGE_VERSION_SUFFIX # используем v1 в package breaking:
use:
- WIRE_JSON deps: []
推奨事項:
- フィールド番号を再利用しないでください。deleted-'reserved'
- 新しいフィールド-'optional'またはデフォルトで;型/セマンティクスを変更しないでください。
7) セマンティックdiffと「破る」変更
7.1 HTTP
例を破る:- フィールドの種類を変更する/必須
- ステータス/ルート/パラメータの削除
- enum/range narrowing;
- id (uuid→string)形式の変更。
- オプションフィールドの追加
- ハッピーパスに影響を与えない新しいステータス(例:'422')
- enum extension。
7.2 gRPC/Protobuf
'reserved '/renumbering-breakingのないフィールドを削除します。
Type change (int32→string)-breaking。
オプションとして新しいタグを追加することは通常安全です。
8)契約とコードリンク
一貫性は2つのスレッドによって提供されます:1.Contract→code: SDK/サーバスタブの生成、テストの負の例。
2.契約→コード:仕様テスト、ステータス/ヘッダーの自動チェック。
Semgrepのアイデア:- 'return 200'を'error!=nil'とする;
- 書込み支払いルートの必須'Idempotency-Key';
- ログのトークンをマスキングします。
9) CI/CDのパイプライン(参照)
pre-commit: spectral lint, redocly lint
PR gate: openapi-diff (base..PR), buf breaking-check, graphql-inspector build: schemathesis smoke, unit/integration linters (ESLint/golangci-lint)
release: publish contracts (artifact/broker), sign & tag
PRは落ちます:
- breaking-diffがあります。
- 基本ルール違反(ステータス/セキュリティ/エラー)
- パラメータの例/説明はありません。
10)規則のカタログ(あなたの組織のためのテンプレート)
識別子とタイプ
'_id'-'string'、 'format: uuid'。
マネーフィールド-'string'/'decimal'スケール付き;通貨-ISO-4217。
Misses(ミス)
統一されたスキーム(第3章を参照。3)のコード:'400/401/403/404/409/422/429/5xx'。
常に'trace_id';'429/503の再試行後。
ページネーション
カーソルのみ;max 'page_size'はドキュメント化されています。
安全性について
すべての操作-'security'ブロック;'scopes'を記述します。
'http: 'リンクはありません。TLS 1。2+.
キャッシュ/idempotency
GET-'ETag/Last-Modified';for write-'Idempotency-Key'(該当する場合)。
ドキュメント
'summary'、 'description'、リクエスト/レスポンスの例(有効)。
11)自動化されたチェックの例
11.1必須セキュリティヘッダの検証(スペクトル)
yaml security-headers:
given: "$.paths[][].responses['200'].headers"
then:
function: truthy
11.2 openapi-diff(疑似CIステップ)
openapi-diff --fail-on-incompatible base.yaml pr.yaml
11.3 buf breaking-check
buf breaking --against '.git#branch=main'
12)契約の質の観察可能性
メトリクス:リンクエラーとのPRの共有、時間の修正、破棄試行回数、ルールに従って「負債」。
ダッシュボード:統合エラースキームへの移行の進捗状況、例を含むカバレッジ、バージョンの安定性。
13) Antipatterns
「Doc」はコード→非同期から別々に生きます。契約をサービスの近くに保ち、バージョン管理されたアーティファクトをリリースします。
リンターは手作業のみ。ハードPRゲートが必要です。
ランダムな例(非決定的)-チェックのフレーク。
負の例とエラーコードはありません。
各サービスのエラースキームの再発明。
Protobufがチェックを破るのを無視する(「目で」タグを変更する)。
14) iGaming/Financeの詳細
通貨フィールド-固定スケール/丸め;浮遊物禁止。
必須ヘッダー'X-Tenant'、 'X-Region'、トレース'traceparent'。
支払書込みハンドル:'Idempotency-Key'、 'Retry-After'をチェックし、409/201セマンティクスを修正します。
Webhooks PSP/KYC: HMAC/mTLSは'securitySchemes'に記述されています。アンチリプレイ('X-Timestamp'、ウィンドウ)。
地域の制限とエラーのローカライズ('Content-Language')。
15) Prod Readinessチェックリスト
- Spectral/Redoclyプロファイルは、プリコミットおよびPRゲートで設計および接続されています。
- 単一のエラーパターンとステータス-コミットおよびチェック。
- openapi-diff/GraphQL Inspector/buf-分割変更をブロックします。
- リクエスト/レスポンスの例は有効です。ページネーション/フィルタがドキュメント化されました。
- SecuritySchemeとスコープが入力されます。httpリンクはありません。
- Protobufの場合:削除されたタグの'reserved';新しいフィールド-オプション。
- Semgrep/コードリンタが有効になっています。マスキングの秘密を記録しています。
- CIは契約アーティファクトとリンティングレポートを公開します。
- Playbook: breaking-diffa(ロールバック、ホットフィックス、インテグレータへの通知)を実行する方法。
16) TL;DR(ドクター)
コントラクトの自動リンク(Spectral/Redocly、 buf/GraphQL Inspector)とセマンティック差分を実装し、単一のエラー/ステータス/ページネーション/セキュリティスキームを修正し、PRゲートを接続してコントラクトをアーティファクトとして公開します。どのブレーキデフもブレーキライトです。お金/支払いの場合-特別なルール(idempotency、 'Retry-After'、 HMAC/mTLS)。