


証明書を自動で発行・更新するモノレポを、機密情報を守りながら直す
ACMEで証明書の申請・更新・デプロイをする、自分のサーバーで動かすツールをAIに直させる時に使う。変更を担当のパッケージやプラグインに収め、先にテストを書き、SQLのマイグレーションを付け、今あるUIの作り方に合わせ、証明書や秘密鍵をコードとログに残さない。
このAIルールを使うには
## 証明書の申請からデプロイまでの流れと、どんな機密情報を保存しているかをつかむ
このsystemは、証明書の申請、更新、deployment、monitoring、通知、API integrationを管理する、privateなself-host型製品として扱う。中核pipelineはACMEを通じて証明書を申請し、DNS-01、HTTP-01、CNAME proxy、またはprovider固有のvalidationを完了し、PEM、PFX、DER、JKS、P7Bなどのformatへexportしたうえで、server、proxy、cluster、CDN、cloud service、control panelなどへdeployする場合がある。
このsystemは、証明書、cloud認証情報、SSH情報、API keyなどの機密設定を保存する。local dataやsecretを、source変更、log、fixture、screenshot、report、生成metadataへ決して露出させてはならない。
## モノレポのワークスペースを分けて扱い、実行時のデータに触らない
repository指定のpackage manager、workspace定義、lockfileを使用し、別のpackage managerのlockfileを導入してはならない。packageが独立したversion control workspaceである場合は、そのworkspace内からstatusとdiffを確認し、変更をroot repositoryの変更と分離する。
taskが明示的に対象としていない限り、runtime data、log、一時出力、生成metadata、distribution、export済みplugin manifestを変更またはcommitしてはならない。動的にinstallされたSDKを理解する必要がある場合はruntime dependency directoryをread-onlyで調べてもよいが、そこはsourceではなく、変更対象へ含めてはならない。
## 変更を、その動作を受け持つパッケージやプラグインに入れる
編集前に所有範囲を特定する。protocol clientはaccount、order、challengeの動作を所有し、pipeline packageは実行modelとtask lifecycleを所有する。server moduleはentity、service、controller、permission、migrationを所有し、client moduleはview、form、route、API adapterを所有する。provider pluginはprovider固有のDNS、deployment、通知動作を所有する。
単一providerの不具合は、そのproviderのplugin内に留める。provider間で一貫して必要となる再利用可能な意味を表す場合に限り、動作をpipeline coreまたはshared plugin libraryへ移す。並行する別実装を作るより、確立されたmodule、service、component、plugin patternを優先する。
## パッケージ自身のコマンドを使い、依存関係を勝手に入れない
validationを実行する前に、文書化されたcommandを読む。影響を受けるpackage自身のunit test、lint、format、build commandを使用し、変更が明確にpackage境界を越える場合に限り、より広いcheckへ拡張する。既知の壊れたtype checkや仮置きのtest scriptを、対応しているfile単位のvalidationの代わりに使用してはならない。
dependencyを先回りしてinstallしてはならない。dependency不足、terminal要件、network accessによって必要なcheckを実行できない場合は、その試行を止めて環境上の制約を報告する。versionに依存するSDKの動作は、記憶や別versionではなく、実際にinstallされているruntime dependencyと同梱documentationを調べる。
## 処理を名前付きの手順に分け、理由を書いたコメントで読みやすくする
短い構文より読みやすさを優先する。複雑な条件、入れ子のternary、長いchain、inline object、多層のhelper callは、明確な名前を持つ中間値または役割を絞ったmethodへ分ける。意味のあるlocal variableによって処理の移行を示せる場合は、あるmethod callを別のmethodのargument内へ直接置いてはならない。
methodのargumentが3個を超える場合はobject parameterを使用する。business rule、compatibility制約、protocolの詳細、隠れたriskについては、その判断が存在する理由をcommentで説明する。小さなlogicは使用箇所に留めるが、business rule、field変換、permission check、repository選択、transaction伝播、計算の複製を同期し続ける必要がある場合は共通化する。
## 先に失敗するテストを書き、最小の変更で直す
主要なbusiness動作には、焦点を絞ったunit testを追加する。新機能または不具合修正では、実装前に期待動作を再現して失敗するtestを優先し、その後で最小の変更を加えてpackage単位のtestを再実行する。後から追加するtestのために既存動作を変える必要がある場合は、変更前に、その動作が既存要件ではなく不具合であることを確認する。
pure unit testはsourceの近くに置き、production buildへ含めない。testだけのためにproduction codeを組み替えず、static ESM importには適切なmodule mocking toolを使用する。packageのunit-test environmentを明示的に設定し、package間の影響によって必要になる場合に限り、より広いbuildを実行する。
## テーブルの変更にはSQLのマイグレーションを付け、トランザクションを正しく渡す
table構造の変更には必ず明示的なSQL migrationを組み合わせ、ORM schema synchronizationには決して依存しない。一時upload keyは、永続保存する前に承認済みfile serviceを通じて正式なkeyへ移行し、必要なownerと公開または非公開の可視性を維持する。
transactionを伝播する場合は、任意のtransaction managerを含むcontextをrequest objectより先に渡し、shared repository helperとtransaction helperを使用する。単純なqueryやpure functionへtransaction contextを追加してはならない。nullまたはundefinedが不正な等価条件にならないよう、任意のtenantまたはproject predicateは正規のquery helperで構築する。
継承したbase methodと衝突するservice method名やsignatureは避ける。base contractを維持し、operationの範囲が明確になる具体的な名前を選ぶ。
## 管理画面は、今あるCRUDフレームワークとフォームのダイアログで作る
編集前に、担当するfeature viewとそのAPI moduleを特定する。通常の管理、record検索、table中心の管理には、承認済みCRUD frameworkを使用する。軽量なread-only表示、操作性の高いinterface、または標準frameworkが適合しないことが文書化されている場合に限り、custom listを構築する。
埋め込みdata gridには、安定した高さ、または子要素を縮小できる途切れのないflex chainが必要となる。検索可能なidentity fieldには、確立されたremote dictionaryを再利用する。単純な確認にはconfirmation dialogを使用してもよいが、fieldを収集する、inputをvalidationする、または追加の値をsubmitするdialogには、承認済みform-dialog abstractionを使用しなければならない。
repository全体のtype checkまたはunit commandが無効であることが分かっている場合は、変更したclient fileに対して、対応しているformatterとlinterだけを実行する。
## 証明書の不具合を正しい層で直し、アカウントの秘密鍵を守る
shared pipeline codeを変更する前にprovider pluginを調べ、providerの動作がversionに依存する場合は、実際に動的installされたSDKを調べる。修正を適用する前に、証明書の問題がACME client、pipeline実行、server service、provider plugin、shared certificate utility、client formのどこに属するかを判断する。
protocol clientが新しいexternal account bindingの材料を消費せずに既存account URLを取得できる場合は、既存account秘密鍵を使ったlookup専用のaccount operationを使用する。external account bindingのidentifierを変更した場合は、そのidentifierにbindされた新しいaccount秘密鍵を生成する。それができない場合は証明書発行を停止し、account keyの更新を要求する。
認証情報の値をcode、log、test、report、commit対象のartifactへ含めてはならない。upload、deployment、通知、open APIのflowを拡張する場合も、validationとauthorizationの境界を維持する。
## 古い設定でも前と同じ動きを保ち、実行した確認を報告する
plugin parameterを追加する場合は、保存済みのlegacy configにその値がない場合を扱い、migrationが明示的に変更しない限り従来の動作を維持する。定義済みのcompatibility branchなしに、欠けている値を新しいmodeとして解釈してはならない。
完了前に、対象を絞ったdiffを調べ、rootと入れ子workspaceを別々に検証し、直接影響を受けるtestとfile単位のformatまたはlint checkを実行し、必要なmigrationを確認する。runtime dataと生成物が変更対象の外にあることを確認する。
変更内容、通過したcheck、実行できなかったcheck、より広いvalidationを範囲外とした理由を報告する。
