


GoのAPIとReactのSPAを、OpenAPIの仕様を先に直してから変える
GoのバックエンドとReactのSPAを、OpenAPIの仕様でつないでいるリポジトリで使う。生成ファイルを手で直さず仕様を直して作り直し、設定・エラー・ログイン・ダウンロード・更新を決まりどおりに扱い、テストしてから報告する。
このAIルールを使うには
## OpenAPIの仕様を正本にし、層ごとの受け持ちを分ける
- ルート、リクエスト・レスポンススキーマ、共有モデルについて、OpenAPI仕様を正本として扱う。
- 開発環境では、GoバックエンドとReact SPAをそれぞれ独立してビルド可能に保つ。
- 本番では、ビルド済みSPAをバックエンドバイナリへ埋め込み、APIとUIを同一オリジンから配信する構成を優先する。
- 開発サーバーはプロキシの利便性のためだけに使い、開発専用のポートやホストを本番コードへ漏らさない。
- 所有権を明確に保つ。API層は通信、サービスはドメイン動作、ストアは永続化、フロントエンドは表示を担当する。
- 並行するルート、設定ストア、イベントチャネル、状態モデルを新設する前に、既存の契約を拡張する。
- 範囲が定まった要件とアーキテクチャ判断なしに、明示的に先送りされたサブシステムを追加しない。
- 文書と実装が食い違う場合は、影響する変更を止め、先に正本の矛盾を解消する。
## 生成ファイルは手で直さず、仕様を直してから作り直す
1. 仕様、生成インターフェース、実装、テスト、関連する運用文書を調べる。
2. 正本を編集する。API形状はOpenAPIファイル、設定は設定構造体、UI文言はメッセージカタログで変更する。
3. リポジトリ所定のコマンドでバックエンドとフロントエンドの成果物を再生成する。
4. 生成インターフェースを実装し、直接影響するサービスとUIラッパーだけを更新する。
5. フォーマット、静的解析、対象を絞ったテスト、関連する最小限の実行時確認を行う。
6. 生成差分を見直し、仕様から意図した契約が生成されたことを確認する。
- 生成ファイルを決して手作業で編集しない。代わりに仕様またはジェネレーター設定を直す。
- 生成されたサーバーインターフェースを迂回する場当たり的なルートを決して登録しない。
- operation identifierは生成メソッド名になるため、一意かつ安定した状態を保つ。
## 共通のスキーマを1か所にまとめ、生成した型をAPIと合わせる
- パス定義はドメイン別に分割し、共有スキーマ、パラメーター、レスポンスは単一の正規componentsセクションへ置く。
- パスファイル間でほぼ同じスキーマを複製せず、共有参照を再利用する。
- ファイルをまたぐ参照に必要な、ジェネレーター固有のimport mappingとpruning制御を維持する。
- スキーマが上流ライブラリの型を反映する場合は、機械的な型対応とJSONプロパティを同期させる。
- シリアライズされる全フィールドを宣言し、常に存在する全フィールドを非Go利用者向けにもrequiredとする。
- nullable参照はOpenAPIの版とジェネレーターが要求する形式で表し、生成結果をテストする。
- 実行時との一致が重要な場合は、バックエンドが実際に配信するAPI文書からフロントエンド型を生成する。
- リポジトリ方針で差分を契約レビューの証拠に使う場合は、生成API型をコミットする。
- コンポーネントが通信詳細へ依存しないよう、APIクライアントをドメインラッパーの内側に置く。
## 中のエラー文を漏らさず、決まった形でエラーを返す
- 生成されたサーバーインターフェースを通してエンドポイントを実装し、ハンドラーメソッドをドメイン別にまとめる。
- 共有JSONレスポンスヘルパーを1つ、中央エラー分類器を1つだけ使う。
- 安定した機械可読コード、表示種別、安全な任意フィールド、リクエスト識別子を持つ構造化エラーを返す。
- 内部または上流の生のエラー文をクライアントレスポンスへ決してコピーしない。
- フィールド検証の詳細は専用mapへ入れ、フィールド外の失敗用に汎用キーを予約する。
- 上流の失敗を安定した理由識別子へ変換し、生のbodyは保護されたログにだけ残す。
- 動的な文言が意図的に安全に表示できる場合に限り、型付きのユーザー向けエラーを使う。
- 分類器の外で通信エラーエンベロープを組み立てない。
- 制御フローにpanicを使わず、ステータスコードとJSONエラーを返す。
- panic回復は通常動作ではなく、構造化して記録される安全網として扱う。
## 設定は1か所で決め、再起動が要る設定を分ける
- 型付き設定構造体で設定を一度だけ定義し、既定値、検証、スキーマメタデータ、環境変数キーをそこから導出する。
- 優先順位を一貫して適用する。既定値、設定ファイル、環境変数による上書きの順とする。
- 組み込み既定値と異なる値だけを永続化する。
- 新しい設定ごとに、既定値、検証、UIカテゴリ、機密性、可視性、再起動時の動作を定義する。
- hot reload可能な設定には、稼働中の利用箇所またはreload hookが必要である。ない場合は再起動必須とする。
- 再起動必須の値は直ちに永続化してよいが、再起動までは実効runtime viewの値を固定する。
- APIレスポンスでは機密値をmaskし、伏せられたplaceholderを更新時のno-opとして扱う。
- プログラム専用設定はruntime APIからread-onlyにし、非表示設定は反映されたUI schemaへ含めない。
- 保存した設定が次回起動を壊さないよう、起動時と永続化前に同じvalidatorを実行する。
- 設定はatomicに書き込み、管理対象の相対パスを起動directoryではなく安定したdata rootへ固定する。
## ログの形をそろえ、処理を残さずにサーバーを止める
- HTTPリクエスト、lifecycle event、background workerで同じschemaの構造化ログを使う。
- リクエストごとのeventを重複発行せず、handlerのfieldとerrorを現在のrequest logへ付加する。
- backend logの運用言語を1つに統一し、UIのlocalizationはfrontendが担当する。
- request ID、実client address、request logging、panic recoveryが依存するmiddleware順序を保つ。
- request loggingの開始前にfieldを変える必要がない限り、新しいmiddlewareはrecovery境界の内側に置く。
- shutdown時は、HTTP serverをdrainする前に長時間接続のevent subscriberを閉じる。
- 処理中requestのdrainに上限時間を設け、期限切れ時の動作を明示する。
- restartでは、processを置換または生成する前にservice cleanupを完了する。
- streaming handlerはhubのcloseまたはrequest cancellationで復帰させる。
- すべてのbackground workerを同じshutdown sequenceへ登録し、処理を取り残さない。
## クエリキーを安定させ、ユーザーが変わったらキャッシュを空にする
- 後段のproviderがquery、locale、authentication、event contextへ依存する場合は、provider順序を明示する。
- feature moduleからquery-option factoryを公開し、生のAPI callはdomain wrapper内に留める。
- identityを変える全parameterを含む安定したquery keyを使う。
- 以前のlist dataは実際のpage遷移でだけ維持し、filter、user、tab、search identityが変わった時は破棄する。
- authentication済みsessionが変わったら、account単位のcacheを空にする。
- entityのcache済みコピーすべてを整合させるため、optimistic update、rollback snapshot、invalidationを一元化する。
- server eventはrefreshの合図として扱い、正本のstateは引き続きqueryまたはstate endpointから取得する。
- render path内では、reactive contextを通してlocalization済みmessage functionを読む。
- 動的translation keyは明示的なstatic resolverで対応させ、locale間でplaceholder shapeを同一に保つ。
- 人が読む設定labelはbackend schemaではなくfrontend catalogへ置く。
## ログイン情報を別ファイルに分け、一時的な失敗ではログアウトさせない
- session credentialは権限を制限した専用state fileへ保存し、一般設定へ決して混在させない。
- refresh credentialをsession authorityとして扱い、短命なaccess credentialは交換可能なものとして扱う。
- 有効期限が近づいたら先回りして更新し、認証失敗後はsingle-flight制御で1回だけ再試行する。
- 一時的な失敗ではsessionを維持し、恒久的な拒否を確認した後に限りsessionをclearする。
- authorization verifierは短命、容量上限付き、1回限りの使用にする。
- 貼り付けられたcallback valueを上流へ送る前に検証し、localization済みで実行可能なerrorを返す。
- proxy discovery結果からcredentialを取り除き、discoveryはread-onlyに保つ。
- 未認証onboardingの書き込みをguardし、login後に設定を変更できないようにする。
- 機密性の高いmutation endpointをauthenticationとapplication固有のCSRF headerで保護する。
- 上流のauthentication body、credential、内部package errorをclientへ決して露出しない。
## ダウンロードは一時ファイルを通して保存し、アプリが作っていないファイルは消さない
- jobをtransaction boundaryとし、意味のあるstate transitionをすべてatomicに永続化する。
- 高頻度のprogressは、tickごとにpersistent stateを書き換えずeventで送る。
- payloadは一意な名前のtemporary fileへ書き、成功後にだけrenameする。cancelまたはfailure時にはpartial fileを消去する。
- 再試行可能なfailureだけを、上限付きexponential backoffで再試行する。
- cleanup前にapplicationが各final fileを作ったか記録し、予想した名前だけを根拠にpathを絶対に消去しない。
- disk contentと処理中reservationの両方に対してcollisionを解決し、上限付きfallback strategyを持たせる。
- 完了済みpayloadが既にdestinationを所有する場合を除き、restart recovery時にpathを再解決する。
- 起動時にpath templateをparseし、設定変更を受理する前にも再検証する。
- すべてのpath segmentをsanitizeし、明示されたrootを保ち、filenameをbyte数で制限し、表示上の切り詰めは文字数で数える。
- hot reloadされた設定が進行中の処理を変えないよう、conversionとnamingの判断をjob単位で固定する。
## つなぎ直した時に、取りこぼしたイベントを送り直す
- persistent stateを正本に保ち、eventは最適化手段として扱う。
- eventに安定したID、timestamp、topic、type、再構築可能なpayloadを持たせる。
- reconnect時、bufferに残っていればclientが最後に確認したIDより後のeventをreplayする。
- replayできない場合はresynchronization eventを1回発行し、clientに正本stateの再取得を要求する。
- keepaliveを使い、中継機器がidle streamを黙って閉じることを防ぐ。
- aggregate job statusを設定するのはjob-level eventだけとし、task eventはserver所有のruleを再計算せずtask stateだけを更新する。
- reconnect後とresynchronization signal後に、影響するviewをrefreshする。
- progress notificationをthrottleするが、terminal transitionと最後のprogress updateはthrottleを迂回する。
- 小さなpublisher interfaceを介し、event transportをdomain managerから独立させる。
## プロキシ先を絞り、署名を確かめてからアプリを更新する
- 厳密なhost policyでproxy targetを許可し、server-side request forgeryを防ぐためredirectごとに再確認する。
- 同じresourceへの同時cache missを共有し、上限を超えるbodyはcache前に拒否する。
- filesystemをcacheの正本として扱い、定期的および書き込み後に、最終accessが古い順のevictionでsizeを調整する。
- cache storageを移動可能にし、永続的なuser stateから分離する。
- release build時にupdate feed locationとtrusted signing keyを注入し、trust materialがなければfail closedにする。
- version、URL、checksum、release noteの各fieldを信頼する前に、署名済みmanifestを検証する。
- binaryを置換する前に、download済みarchiveを署名済みmanifestと照合する。
- update適用をsingle-flight化し、development buildでは拒否し、authenticationとCSRF protectionを必須にする。
- 置換対象のexecutableを決定的に解決し、曖昧なarchiveは拒否する。
- 検証済みreplacementの準備が整った後にだけ、serviceをdrainしてrestartする。
## 動いているアプリで確かめ、リリースや本番の変更の前で止まる
- 失敗したstepを飛ばさず、generation、implementation、focused test、直接のruntime verificationまで進める。
- health endpoint、配信中のOpenAPI document、影響するAPI behavior、直接影響するUI pathを検証する。
- 変更が関係する場合は、format、static analysis、race-sensitive backend test、frontend check、production buildを実行する。
- atomic persistence、restart semantics、secret masking、error non-disclosureを対象を絞ったtestで確認する。
- release作業では、厳密なsemantic versioning、signed-feed continuity、checksum、platform archive resolutionを検証する。
- 現在の要件が明示的に範囲へ含めない限り、先送りされたfeatureは先送りのままにする。
- 無関係なrefactor、並行state store、重複error system、投機的infrastructureを避ける。
- 明示的な承認がない限り、外部release、破壊的migration、credential変更、本番mutationの前で停止する。
- 変更内容、検証内容、範囲外として残したもの、未解決の契約矛盾を報告する。
