mcpField
A
add-server-logic

add-server-logic

github.com/microsoft開発1.1k214 回インストール今日更新
リポジトリ

add-server-logic について

Web ロールとテーブル権限で保護されたサーバーサイド JavaScript、Power Pages Server Logic を作成・管理するスキルです。Dataverse 操作、外部 API、独自の業務ロジックの計画、実装、設定、フロントエンド連携を支援します。

主な機能

  1. 01Server Logic の JavaScript とメタデータ作成
  2. 02get、post、put、patch、del ハンドラーの実装
  3. 03テーブル権限とサイト設定の構成
  4. 04シークレットの安全な管理の案内
  5. 05エンドポイントのフロントエンド連携
  6. 06実装の検証とテスト案内

活用シーン

  1. 01外部 API の認証情報をブラウザーから隠す
  2. 02Dataverse の書き込みにサーバー側の業務ルールを適用
  3. 03Power Pages SPA をサーバー側ロジックに接続

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/microsoft/power-platform-skills --skill add-server-logic

インストール後、Claude Code で/add-server-logicを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

assets/
serverlogic-plan.html
references/
frontend-integration-reference.md
server-logic-docs.md
server-logic-plan-data-format.md
scripts/
create-serverlogic-metadata.js
validate-serverlogic.js

詳細

プラグインのチェック:node "${PLUGIN_ROOT}/scripts/check-version.js" を実行します。メッセージが出力された場合は、続行する前にユーザーに表示してください。

サーバーロジックの追加

Power Pages Server Logic ファイルを 1 つ以上作成、管理します。これは、Power Pages ランタイム上で安全に実行されるサーバーサイド JavaScript で、ブラウザーからは隠され、Web ロールとテーブル権限によって保護されます。Server Logic を使用すると、機密性の高いコードや認証情報をクライアントに公開することなく、安全な外部 API 連携、Dataverse 操作、カスタムビジネスロジックを実装できます。

基本原則

  • Microsoft Learn を信頼できる情報源とする:コードを記述する前に、必ず最新のドキュメントを取得してください。Server Logic 機能はプレビュー段階であり、SDK は変更される可能性があるため、キャッシュされた知識だけに頼らないでください。
  • ブラウザー API も依存関係も使用しない:Server Logic は ECMAScript 2023 をサポートするサンドボックス化されたサーバー環境で実行されます。fetch、XMLHttpRequest、setTimeout、DOM API は使用できません。npm パッケージも利用できません。
  • 使用できる関数は 5 つのみ:サーバーロジックファイルでトップレベルにエクスポートできる関数は、get、post、put、patch、del のみです。delete は JavaScript の予約語であり、使用できません。
  • 必ず文字列を返す:すべての関数は文字列を返す必要があります。オブジェクトや配列を返す場合は、JSON.stringify() を使用してください。
  • TaskCreate/TaskUpdate を使用する:すべてのフェーズを通じて進捗を記録します。作業を開始する前に、すべてのフェーズを含む ToDo リストを作成してください。
  • フロントエンドの整合性を保つ:フェーズ 9 で SPA の UI を追加または変更する場合は、まず ${PLUGIN_ROOT}/references/site-modification-integrity.md を読んでください。設定済みのロケールリソース間で表示状態を同期し、UI の双方向性と拡張時の安全性を保ってください。バックエンドのみの作業では、ローカライズの変更は必要ありません。

前提条件:

  • 既存の Power Pages SPA サイトが作成されていること
  • サイトが少なくとも一度はデプロイされている必要があります(.powerpages-site フォルダーが存在すること)。サーバーロジックファイルは .powerpages-site/server-logic/ 内に配置されるため、作成前にデプロイが必要です

最初のリクエスト: $ARGUMENTS


ワークフロー

  1. サイトの存在を確認 — Power Pages プロジェクトを見つけ、既存のパターンを確認し、前提条件を検証します
  2. 要件を把握 — ユーザーの意図と、解決策に必要なサーバーロジックファイルの数を判断します
  3. 最新のドキュメントを取得 — Microsoft Learn から最新の Server Logic SDK リファレンスを取得します
  4. 実装計画を確認 — 計画をユーザーに提示し、コードを書く前に承認を得ます
  5. サーバーロジックを実装 — 承認済みの .js ファイルと .serverlogic.yml ファイルを .powerpages-site/server-logic/<name>/ に作成します
  6. テーブル権限を設定 — (条件付き:Server.Connector.Dataverse を使用する場合のみ)サーバーロジックがアクセスする Dataverse テーブルのテーブル権限を設定します
  7. シークレットと環境変数を管理 — (条件付き:サーバーロジックでシークレットが必要な場合のみ)Azure Key Vault(推奨)または Dataverse の直接環境変数を使用して、機密値を安全に保存します
  8. サイト設定を構成 — 必要に応じて ServerLogic のサイト設定を構成します
  9. クライアント側の連携 — サーバーロジックをサイトのフロントエンドコードに組み込む方法を支援します
  10. 検証とテスト方法の案内 — コードを検証し、テスト手順を提示します
  11. レビューとデプロイ — 概要を提示し、デプロイを提案します

フェーズ 1:サイトの存在を確認

目標:Power Pages プロジェクトのルートを特定し、前提条件を確認します

アクション:

  1. 11 フェーズすべてを含む ToDo リストを作成します(進捗管理の表を参照)
1.1 プロジェクトを特定

現在のディレクトリまたは直下のサブディレクトリから powerpages.config.json を探します

見つからない場合:まず /create-site を使ってサイトを作成するよう、ユーザーに伝えます。

1.2 既存の設定を読む

powerpages.config.json を読み、サイト名と設定を確認します。

1.3 フレームワークの検出

package.json を読み込み、フロントエンドのフレームワーク(React、Vue、Angular、または Astro)を特定します。これはフェーズ 8(クライアント側の統合ガイダンス)で必要です。フレームワークの検出方法の全体については、${PLUGIN_ROOT}/references/framework-conventions.md を参照してください。

1.4 既存のサーバーロジックとフロントエンドコードの調査

Explore エージェント(agent_type: "explore" を指定して Task ツールを使用)を使い、サイトに既存のサーバーロジックのパターンと、サーバーロジックのエンドポイントを呼び出す、または呼び出す必要があるフロントエンドコードがないか分析します。

Explore エージェントへのプロンプト:

「この Power Pages SPA サイトについて、サーバーロジックに関連する状況を分析してください。以下を確認してください。

  1. .powerpages-site/server-logic/ は存在しますか?存在する場合は、すべてのサブディレクトリとその中の .js ファイルを列挙してください。各サーバーロジックが実装する機能と、使用する SDK 機能を要約してください。また、対応する .serverlogic.yml ファイルを読み込み、Web ロールの割り当てを確認してください。
  2. フロントエンドのソースコード(src/**/*.{ts,tsx,js,jsx,vue,astro})を検索し、/_api/serverlogics/ の既存の呼び出しを確認してください。これらは、すでに利用されているサーバーロジックのエンドポイントを示します。
  3. CSRF トークンの処理パターン(__RequestVerificationToken、_layout/tokenhtml)を探してください。これらから、現在サイトが認証済みの API 呼び出しをどのように行っているかがわかります。
  4. サーバーロジック、バックエンド、またはサーバー側の処理に言及する TODO/FIXME コメントがないか確認してください。
  5. サーバーロジックの呼び出しに置き換える必要がありそうな、ハードコードされた API URL、モックデータ、またはプレースホルダーの fetch 呼び出しを探してください。
  6. src/shared/、src/services/、または同様のディレクトリに、再利用できそうな既存のサービスレイヤーや API ユーティリティファイルがないか確認してください。
  7. .powerpages-site/web-roles/*.webrole.yml ファイルを読み込み、利用可能な Web ロールとその GUID を列挙してください。これらはサーバーロジックのメタデータ YAML を作成する際に必要です。
  8. 既存のサーバーロジックごとに、新しいサーバーロジックファイルを作成するのではなく、要求された機能のために再利用または安全に拡張できるか評価してください。有力な再利用候補があれば、その理由とともに指摘してください。 作業の重複を避け、既存のパターンに合わせられるよう、すべての調査結果を報告してください。」

Explore エージェントの調査結果から、以下を確認します。

  • 既存のサーバーロジックファイル — すでに実装されている内容と、再利用または拡張の候補
  • フロントエンドの呼び出しパターン — サイトが API 呼び出しを行う方法(フェーズ 9 ではこのパターンに合わせます)
  • 既存のサービス/ユーティリティファイル — クライアント側の統合を追加する際に再利用します
  • 不足しているもの — 存在しないサーバーロジックのエンドポイントをフロントエンドコードが参照している箇所
1.5 デプロイ状況の確認(必須)

.powerpages-site フォルダーを確認します。

見つからない場合:サーバーロジックを作成する前に、サイトを必ずデプロイする必要があります。サーバーロジックファイルは .powerpages-site/server-logic/ 内に保存されます。ユーザーに次のように伝えます。

「.powerpages-site フォルダーが見つかりませんでした。サーバーロジックファイルはこのフォルダー内に保存されるため、サーバーロジックを作成する前に、サイトを少なくとも 1 回デプロイする必要があります。今すぐデプロイしますか?」

🚦 ゲート(plan · add-server-logic:1.5.deploy-first): .powerpages-site がありません — サーバーロジックファイルはこの中に保存されます。先にデプロイするか、停止してください。

トリガー: フェーズ 1.5 で .powerpages-site ディレクトリが見つかりませんでした。 確認が必要な理由: 存在しないパスに書き込んだサーバーロジックの .js/.yml ファイルはデプロイされません。 キャンセルした場合: 何も残りません — サーバーロジックファイルはまだ書き込まれていません。

AskUserQuestion を使用します。

質問選択肢
サーバーロジックには .powerpages-site フォルダーが必要です。今すぐサイトをデプロイしますか?はい、今すぐデプロイ(必須)、キャンセル

「はい、今すぐデプロイ」の場合:まず /deploy-site を実行し、その後フェーズ 2 に進みます。

「キャンセル」の場合:ワークフローを停止します — .powerpages-site がなければサーバーロジックを作成できません。

出力:プロジェクトルートの確認、.powerpages-site の存在、既存のサーバーロジック(ある場合)、利用可能な Web ロール

フェーズ 2:要件を理解する

目標:ユーザーの意図を特定し、1 つ以上のサーバーロジックファイルが必要かどうかを判断して、各項目に必要な HTTP メソッドを把握します。

アクション:

2.1 ユーザーのリクエストを分析する

ユーザーのリクエストから、次の点を判断します。

  • 意図の構成:リクエストは単一のサーバーロジックに対応しますか、それとも複数のサーバーロジックに対応しますか?
  • 再利用の機会:既存のサーバーロジックでリクエストの一部に対応できますか? また、安全に拡張できますか?
  • サーバーロジックの一覧:必要な各サーバーロジックについて、目的、推奨するエンドポイント名、再利用・拡張・新規作成のどれにするかを記録します。
  • 必要な HTTP メソッド:各サーバーロジックで実装すべき 5 つの関数(get、post、put、patch、del)はどれですか?

既存のサーバーロジックが、リクエストされた機能とドメイン、セキュリティモデル、ライフサイクルの点で合致する場合は、再利用または安全な拡張を優先してください。再利用すると既存のファイルがわかりにくくなる、対象範囲が広くなりすぎる、または安全性が損なわれる場合に限り、新しいサーバーロジックを作成してください。

ユースケースが異なる責任、セキュリティ境界、またはライフサイクル上の懸念事項に自然に分かれる場合は、複数のサーバーロジックファイルを優先してください。例:

  • Web ロールの要件が異なる読み取りワークフローと書き込みワークフロー
  • 外部システムやサイト設定が異なる個別の連携
  • 1 つのエンドポイントにまとめると、テストや推論が難しくなる独立したビジネス機能
2.1.1 検証と実行を組み合わせるパターンを特定する

計画した各サーバーロジック項目について、検証と実行を組み合わせるべきかどうかを判断します。これは、サーバーロジックがビジネスルールを検証し、その結果として Dataverse への書き込みも実行することを意味します。クライアントが処理するための検証結果を返すだけではありません。

次のいずれかに該当する場合、サーバーロジック項目は検証と実行を組み合わせる必要があります。

条件例
ステートマシンまたはライフサイクルを適用する注文ステータス:下書き → 送信済み → 承認済み
改ざん防止が必要なビジネスルールに書き込みが依存する「締め切り前に限り入札を許可する」
操作が複数のテーブルにまたがり、不可分に実行される入札を落札にし、その他すべてを却下し、イベントのステータスを更新する
書き込みに計算値または派生値が含まれるサーバーがスコアを計算して書き込む
クライアントにフィールドへの直接書き込み権限を与えるべきではない厳格な遷移ルールがあるステータスフィールド

検証と実行を組み合わせる各項目について、次の点を記録します。

  • サーバーロジックが実行する Dataverse への書き込み(UpdateRecord、CreateRecord など)
  • 書き込むフィールド — これらのフィールドは、クライアントから Web API 経由で書き込み可能にしてはいけません。
  • サーバーロジックがクライアントに返す内容 — 通常は、変更前後の状態を含む成功/失敗の結果です。クライアントがその結果に基づいて処理する検証フラグではありません。

避けるべきアンチパターン:検証だけを行い、{ valid: true/false } を返して、書き込みのための Web API 呼び出しは別途クライアント側で行うよう求めるサーバーロジック項目。これでは、クライアントが検証を回避して直接書き込めてしまいます。

2.1.2 Dataverse カスタムアクションを検出する

計画しているサーバーロジック項目に Dataverse 操作が含まれる場合、ゼロからロジックを構築する代わりに活用できる既存のカスタムアクション(Custom API または Custom Process Action)がユーザーの Dataverse 環境にあるかどうかを確認します。

ステップ 1 — カスタムアクションを取得する:

node "${PLUGIN_ROOT}/scripts/list-custom-actions.js" "<ENV_URL>"

スクリプトは次の内容を含む JSON オブジェクトを出力します:

  • customApis — リクエストパラメーターとレスポンスプロパティの全情報を含む最新の Custom API
  • customProcessActions — 旧式の Custom Process Action(有効化済みのもののみ)
  • total — 両方のタイプの合計数

各エントリーには、name、displayName、description、type(action または function)、binding(unbound、entity、または entityCollection)、boundEntity、source(customApi または customProcessAction)が含まれます。Custom API には、requestParameters と responseProperties の配列も含まれます。

ステップ 2 — ユーザーに提示して確認する:

カスタムアクションが見つかった場合(total > 0)、バインドタイプ(アンバウンドとエンティティバインド)ごとにまとめた概要をユーザーに提示し、使用するものがあるかどうかを確認します。

🚦 ゲート(plan · add-server-logic:2.1.2.use-custom-actions): カスタムアクションが見つかりました。既存の Dataverse Custom API/Process Action をラップするか、サーバーロジックをゼロから構築するかを選択してください。この選択によって、フェーズ 5 の実装形式が変わります。

トリガー: list-custom-actions.js が 1 件以上のエントリーを返しました。 確認する理由: 自動でラップすると誤ったアクションに紐付く可能性があり、自動的にスキップすると Dataverse にすでに存在するロジックが重複する可能性があります。 キャンセルした場合: 何もありません。サーバーロジックのファイルはまだ書き込まれていません。

AskUserQuestion を使用します:

質問選択肢
Dataverse 環境には、<total> 件のカスタムアクションがあります。ロジックをゼロから記述する代わりに、サーバーロジックで使用しますか?はい、使用するものを選びます;いいえ、すべてゼロから構築します

リストを明確に提示してください。各アクションについて、名前、説明、タイプ(action/function)、バインドタイプ、該当する場合はバインド先のエンティティを表示します。見やすいように、アンバウンドとエンティティバインドに分けてください。

ユーザーがいいえと答えた場合は、フェーズ 2.2 に進みます。

ステップ 3 — カスタムアクションをサーバーロジック項目に割り当てる:

ユーザーがはいと答えた場合、作成するサーバーロジック項目ごとに、ラップするカスタムアクションがあるかどうかを確認します。

各サーバーロジック項目について AskUserQuestion を使用します:

質問コンテキスト
<server-logic-name> エンドポイントでは、どのカスタムアクションを使用しますか?名前、説明、バインドタイプとともに、カスタムアクションのリストを提示します。選択肢として 「なし — ゼロから構築」 を含めます。

各サーバーロジック項目について割り当てを記録します。カスタムアクションをラップする項目について、次の情報を記録します:

  • カスタムアクション名(InvokeCustomApi 呼び出しで使用)
  • 関数(GET)かアクション(POST)か
  • バインドタイプと、該当する場合はバインド先のエンティティ
  • リクエストパラメーターとレスポンスプロパティ(Custom API から取得できる場合)

この割り当ては、サーバーロジックコードを生成するフェーズ 5.3 で使用され、既存のカスタムアクションをラップする項目を示すために HTML プラン(フェーズ 4)にも表示されます。

2.2 必要な SDK 機能を特定する

計画している各サーバーロジック項目の目的に基づいて、必要なサーバー SDK 機能を特定します。

機能使用する場面
Server.Connector.HttpClient外部 REST API の呼び出し(Dataverse は対象外)
Server.Connector.DataverseDataverse レコードの読み取り/書き込み(CRUD と、Dataverse カスタム API 用の InvokeCustomApi)
Server.Contextリクエストパラメーター、ヘッダー、本文へのアクセス
Server.Userユーザー単位の操作、ロールの確認
Server.Logger常に使用 — すべての関数で開始/終了とエラーを記録する必要があります
Server.Sitesettingサイト設定の構成値の読み取り
Server.EnvironmentVariableServer.EnvironmentVariable.get(name) を使用した、Dataverse 環境変数値の直接読み取り — シークレット以外の構成には Server.Sitesetting の代わりに使用できます
Server.Websiteサイトのメタデータへのアクセス
2.3 シークレット値を特定する

サーバーロジック項目で、ハードコードすべきではないシークレットまたは機密性の高い構成値が必要かどうかを判断します。一般的な例を次に示します。

シナリオ必要なシークレット
認証が必要な外部 API の呼び出しAPI キー、クライアントシークレット、ベアラートークン
サードパーティサービスへの接続接続文字列、アクセストークン
OAuth2 クライアント認証情報フロークライアント ID + クライアントシークレット
Webhook の検証署名シークレット、共有キー

特定した各シークレットについて、次の情報を記録します。

  • シークレット名:内容がわかる名前(例:ExchangeRateApiKey、PaymentGatewaySecret)
  • 用途:シークレットが必要な理由
  • サイト設定名:サーバーロジックが Server.Sitesetting.Get() で使用する名前(例:ExternalApi/ExchangeRateApiKey)
  • 環境変数のスキーマ名:Dataverse 環境変数のスキーマ名(例:cr5b4_ExchangeRateApiKey)

これらの値は、フェーズ 7 で環境変数とサイト設定を作成する際に使用します。

2.3.1 Key Vault の選択

フェーズ 2.3 でシークレットが特定された場合は、Azure Key Vault を使用するかどうかをこの時点でユーザーに確認します。この選択は、フェーズ 4 の実装計画に選択したシークレット管理方法を反映できるよう、フェーズ 4 より前に行う必要があります。

🚦 ゲート(plan · add-server-logic:2.3.1.keyvault): シークレットの保存方法を選択します(Key Vault または通常の環境変数)。選択内容によって、フェーズ 4 で表示する計画とフェーズ 7 の実装パイプラインが変わります。

実行条件: フェーズ 2.3 でシークレット値が 1 つ以上特定された場合。 確認する理由: 通常の環境変数を作成すると、ソリューションのエクスポートでシークレットが公開される可能性があります。一方、Key Vault を自動的に選択すると、追加の Azure セットアップが必要になります。 キャンセルした場合: 影響はありません — 環境変数の定義はまだ書き込まれていません。

AskUserQuestion を使用します。

質問選択肢
このサーバーロジックでは、シークレット値(API キーやクライアントシークレットなど)が必要です。Azure Key Vault は、シークレットを安全に保存するための推奨方法です。Azure Key Vault を使用しますか?はい、Azure Key Vault を使用する(推奨)、いいえ、環境変数に直接保存する

ユーザーの選択を記録します。選択内容は HTML 計画(フェーズ 4)に表示され、フェーズ 7 で実行されます。

2.4 ユーザーに確認する

要件が曖昧な場合は、AskUserQuestion を使用して明確にします。

質問コンテキスト
このサーバーロジックソリューション全体では、何を実現する必要がありますか?目的が不明確な場合
サーバーロジックは1つにするべきですか、それとも複数にするべきですか?どちらの構成も妥当な場合
各サーバーロジックで必要な HTTP メソッドは何ですか?指定がない場合。ユースケースに基づいて提案します(例:読み取り専用=GET、フォーム処理=POST)
各サーバーロジックでは、外部 API、Dataverse、またはその両方を呼び出す必要がありますか?使用するコネクタを決定します
各サーバーロジックの名前は何にしますか?担当する処理に基づいて、URL に適した名前を提案します
サーバーロジックで、シークレットや機密情報(API キー、クライアントシークレット、トークン)が必要ですか?認証が必要な外部 API やサービスをサーバーロジックが呼び出す場合

出力:全体的な目的、再利用・拡張・作成するサーバーロジックの項目、HTTP メソッド、必要な SDK 機能、および必要なシークレットを明確に把握します


フェーズ 3:最新のドキュメントを取得する

目標:コードを記述する前に、Microsoft Learn から最新の Server Logic ドキュメントをすべて見つけて読みます

この手順は重要です。Server Logic はプレビュー機能であり、SDK の仕様は変更される可能性があるためです。Microsoft Learn のドキュメントが正式な情報源です。

アクション:

3.1 ドキュメントの参照先に従う

Server Logic のドキュメントを検索、分類、取得し、照合する方法については、以下の参照ドキュメントを信頼できる情報源として使用します。

参照:${PLUGIN_ROOT}/skills/add-server-logic/references/server-logic-docs.md

この参照先に従って、次の操作を行います。

  • Microsoft Learn を動的に検索し、最新の Server Logic ドキュメントをすべて見つけます
  • 基本的なリファレンスページと、関連するシナリオ別ページを取得します
  • 最新のコードサンプルを検索します
  • 見つかったドキュメントと、参照先にある既知の SDK ベースラインを照合します
3.2 タスク固有の注意事項を抽出する

取得したドキュメントから、現在のタスクに関係する項目を抽出して記録します。

  • すべての SDK メソッドのシグネチャ、パラメーター型、戻り値の型
  • 現在サポートされている HTTP メソッドと関数シグネチャ
  • サイト設定とその既定値
  • セキュリティモデル(Web ロール、テーブル権限、CSRF)
  • クライアント側の呼び出しパターンと応答形式
  • Microsoft Learn で見つかった新しいメソッドや破壊的変更

出力:関連する Microsoft Learn のドキュメントページすべてに照らして確認済みの、最新の SDK リファレンス


フェーズ 4:実装計画を確認する

目標:コードを記述する前に、実装計画をユーザーに提示して承認を得ます

アクション:

4.1 計画データを準備する

サーバーロジックの計画データを作成し、承認を求める前に HTML の計画をレンダリングします。

参照:${PLUGIN_ROOT}/skills/add-server-logic/references/server-logic-plan-data-format.md

レンダリングされた計画には、次の内容をまとめます。

  • 作成または再利用するサーバーロジック項目の数
  • 各エンドポイントの名前、API URL、作成するファイル
  • 実装する関数と、それぞれの処理内容
  • 各項目で使用する SDK 機能、外部サービス、Dataverse テーブル
  • 各項目に適用される Web ロール、セキュリティ制約、サイト設定
  • 環境変数として保存するシークレットや機密情報(Azure Key Vault の使用有無を問わない)。フェーズ 2.3.1 でユーザーが Azure Key Vault を選択した場合は、SECRETS_DATA に useKeyVault: true とシークレットの一覧を設定します。HTML の計画には、セキュリティ上の利点を説明する Key Vault バナーが表示され、各サーバーロジックが依存するシークレットが示されます。シークレットが不要な場合は、SECRETS_DATA を null に設定します。
  • 承認後に想定される次の手順
4.2 HTML プランをレンダリングする

テンプレートから HTML プランファイルを生成し、承認を求める前にユーザーの既定のブラウザーで開きます。

Power Pages プロジェクト内で作業している場合は、プランを次の場所に書き込みます:

<PROJECT_ROOT>/docs/serverlogic-plan.html

docs/ フォルダーがまだ存在しない場合は作成します。この HTML ファイルは、サーバーロジック作業の残りの部分と一緒にレビューおよびコミットできるよう、リポジトリ内に保管します。

HTML を手作業で作成しないでください。レンダリングスクリプトを使用します:

node "${PLUGIN_ROOT}/scripts/render-serverlogic-plan.js" --output "<OUTPUT_PATH>" --data "<DATA_JSON_PATH>"

レンダリングスクリプトは既存のファイルの上書きを拒否します。呼び出す前に、既定の出力パス (<PROJECT_ROOT>/docs/serverlogic-plan.html) が既に存在するかどうかを確認します。存在する場合は、コンテキストに基づいて新しい説明的なファイル名を選択します — 例: serverlogic-plan-exchange-rate.html、serverlogic-plan-apr-2026.html。選択した名前を --output で渡します。

4.3 プランの概要を提示する

CLI で 2 つ目の詳細なプランを提示しないでください。HTML ファイルが唯一の詳細なプラン成果物です。

CLI では、ブラウザーで開かれている HTML プランをユーザーに示す簡単な概要のみを提示します。含める内容は次のとおりです:

  • サーバーロジックの合計数
  • プランが項目を作成、更新、再利用のいずれであるか
  • Web ロール、テーブル権限、またはサイト設定が関与しているかどうか
  • レンダリングスクリプトが返した実際の出力パス
  • ブラウザーで開かれた HTML に完全な詳細が含まれているという注記

ユーザーが明示的にテキスト版を求めない限り、サーバーロジックごとの内訳、根拠、ロールの割り当て、または関数の詳細を CLI でインラインに繰り返さないでください。詳細な HTML プランファイルがどこに保存されたか、レビューのためにブラウザーで開かれていること、およびユーザーが破棄を求めない限りプランのリポジトリコピーが実装成果物と一緒にコミットされることをユーザーに伝えます。

4.4 ユーザーに確認する

🚦 ゲート (plan · add-server-logic:4.4.plan-approval): フェーズ 5 が .serverlogic.yml / .js ファイルを書き込んだり、フェーズ 7 が環境変数を作成したりする前に、レンダリングされた HTML プランに対する最終承認を行います。

トリガー: フェーズ 4.2 が HTML プランをレンダリングしました。フェーズ 4.3 が CLI の概要を提示しました。 なぜ確認するのか: サーバーロジックファイルが誤った名前 / 誤ったロールでコミットされること。環境変数の定義が誤ったシークレットストレージモードに対して作成されること。 キャンセル時の状態: 何もありません — サーバーロジックファイルはまだ書き込まれていません。

AskUserQuestion を使用します:

質問選択肢
これがこのサーバーロジック作業の実装プランです。正しいと思われますか?承認して実装する (推奨)、変更を依頼する、キャンセル

「変更を依頼する」の場合: 何を変更する必要があるかを尋ね、プランを更新して、再度提示します。

「キャンセル」の場合: ワークフローを停止します。

出力: ユーザーが承認した実装プラン


フェーズ 5: サーバーロジックを実装する

目標: フェーズ 3 で検証した制約に従い、承認された各サーバーロジックの .js ファイルとメタデータ YAML を作成する

アクション:

5.1 サーバーロジックフォルダーを作成する

承認された各サーバーロジック項目について:

  • 承認されたプランが reuse と示している場合: 新しいフォルダーを作成しないでください。既存のサーバーロジックをそのまま再利用し、必要に応じて周辺の統合作業のみを更新します。
  • 承認されたプランが update / 拡張と示している場合: 既存のフォルダーを再利用し、重複を作成するのではなく、既存の .js / .serverlogic.yml ファイルを更新します。
  • 承認されたプランが create と示している場合: .powerpages-site/server-logic/ 内にフォルダーを作成します (注: 単数形の server-logic で、末尾に 's' は付きません)。フォルダー名がそのエンドポイント名と正確に一致することを確認します。
5.2 Web ロールの読み取りまたは作成

Create Web Role スキルを使用して、承認されたサーバーロジック計画に必要な Web ロールを特定し、メタデータを書き込む前に不足しているロールを作成します。

利用可能なすべてのロールをすべてのサーバーロジックに付与すべきだと想定しないでください。代わりに、各サーバーロジックの目的、セキュリティモデル、および承認された計画に基づいて、必要な最小限のロールセットを決定してください。

Web ロールファイルの内容例:

adx_anonymoususersrole: false
adx_authenticatedusersrole: true
description: Role for authenticated users
id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
name: Authenticated Users

スキルのワークフローでは、次の場合に Create Web Role スキルを明示的に呼び出します:

  • サイトに適切な既存の Web ロールがない場合
  • 承認された計画に、まだ存在しないロールの提案が含まれている場合
  • メタデータを作成する前にロールの割り当てを調整する必要がある場合

Create Web Role スキルが完了したら、生成された Web ロールの YAML ファイルを読み取り、各サーバーロジックのメタデータ YAML に必要な id と name の値を収集します。

5.3 サーバーロジックファイルの作成

承認されたサーバーロジック項目ごとにこの手順を繰り返します。承認された計画のステータス(create、update、または reuse)に従って <PROJECT_ROOT>/.powerpages-site/server-logic/<name>/<name>.js を作成または更新し、次の必須パターンに従ってください:

構造ルール
  1. トップレベル関数のみ: ファイルのトップレベルには、get、post、put、patch、del の 5 つの関数のみを含めることができます。ユーザーが必要とする関数だけを含めてください。
  2. 各関数は文字列を返す: オブジェクトや配列には JSON.stringify() を使用します。
  3. 各関数に try/catch を付ける: すべての関数は、そのロジックを try/catch ブロックで囲む必要があります。
  4. 各関数でログを出力する: エントリ時には Server.Logger.Log() を、catch ブロックでは Server.Logger.Error() を使用します。
  5. インポートや require は禁止: import、require、外部依存関係は使用しないでください。
  6. ブラウザー API は禁止: fetch、XMLHttpRequest、setTimeout、setInterval、console.log、DOM API は使用しないでください。
  7. 必要な場合のみ async: 関数は await(HttpClient 呼び出し)を使用する場合にのみ async としてマークしてください。Dataverse コネクタのメソッド(Server.Connector.Dataverse.*)は同期的です — これらに対して async/await を使用しないでください。
禁止されているスクリプトパターン

Power Pages のサーバー側スクリプトバリデーターは、特定のパターンを含むスクリプトを実行時に拒否します。違反は診断で RTSL01: Script validation failed: prohibited pattern found - Pattern: <regex> として表面化し、関数はユーザーコードを実行せずにサイレントにフォールスルーします。

パターン正規表現注意点
JavaScript の with 文with\s*\(この正規表現は、ファイル内のどこであっても部分文字列 with( にマッチします — 文字列リテラル内や他の識別子内も含みます。startswith(、endswith(、groupwith( のような OData フィルター関数は with( で終わるため、これに引っかかります。

OData 関数の回避策 — ソース内で with( が連続しないようにリテラルを分割します:

// ❌ Triggers validator: "startswith(" contains the substring "with("
var query = "$filter=startswith(name,'INV-')";

// ✅ Split the literal — server still receives "startswith(name,...)"
var query = "$filter=startswith" + "(name,'INV-')";

同じテクニックは endswith(、groupwith(、および with( で終わるその他の識別子にも適用されます。

コードテンプレート
// Server Logic: <name>
// Purpose: <description>
// API URL: https://<site-url>/_api/serverlogics/<name>

function get() {
    try {
        Server.Logger.Log("<name> GET called");

        // Access query parameters
        // const id = Server.Context.QueryParameters["id"];

        // Your logic here...

        return JSON.stringify({
            status: "success",
            method: "GET",
            data: null // replace with actual data
        });
    } catch (err) {
        Server.Logger.Error("<name> GET failed: " + err.message);
        return JSON.stringify({
            status: "error",
            method: "GET",
            message: err.message
        });
    }
}
検証して実行するテンプレート

サーバーロジック項目が検証して実行(validate-and-execute)として識別された場合(フェーズ 2.1.1 を参照)、このパターンを使用します。主な違い: サーバーロジックは現在の状態を読み取り、ビジネスルールを検証し、かつ結果を Dataverse に書き込みます — これをすべて 1 回の呼び出しで行います。クライアントは保護されたフィールドに直接書き込みません。

// Server Logic: <name>
// Purpose: Validate and execute <describe the operation>
// Pattern: Validate-and-execute — this endpoint both validates the business rule
//          and performs the Dataverse write. The client should NOT write <protected fields>
//          via Web API — all writes to those fields go through this endpoint.
// API URL: https://<site-url>/_api/serverlogics/<name>

function post() {
    try {
        Server.Logger.Log("<name> POST called");

        const body = JSON.parse(Server.Context.Body);
        const entityId = body.entityId;
        const targetStatus = body.targetStatus;

        // 1. Read the current record from Dataverse
        const current = Server.Connector.Dataverse.RetrieveRecord("<table-name>", entityId, "?$select=<status-field>");
        const currentStatus = current["<status-field>"];

        // 2. Validate the transition
        const allowedTransitions = {
            "Draft": ["Submitted"],
            "Submitted": ["Approved", "Rejected"],
            "Approved": ["Fulfilled"]
        };

        const allowed = allowedTransitions[currentStatus] || [];
        if (!allowed.includes(targetStatus)) {
            return JSON.stringify({
                status: "error",
                message: "Invalid transition: " + currentStatus + " → " + targetStatus + " is not allowed",
                currentStatus: currentStatus,
                targetStatus: targetStatus,
                allowedTargets: allowed
            });
        }

        // 3. Execute the write — server performs the Dataverse update
        const updateData = {};
        updateData["<status-field>"] = targetStatus;
        Server.Connector.Dataverse.UpdateRecord("<table-name>", entityId, JSON.stringify(updateData));

        Server.Logger.Log("<name> transition executed: " + currentStatus + " → " + targetStatus);

        // 4. Return the result — client receives confirmation, not a validation flag
        return JSON.stringify({
            status: "success",
            previousStatus: currentStatus,
            newStatus: targetStatus,
            entityId: entityId
        });
    } catch (err) {
        Server.Logger.Error("<name> POST failed: " + err.message);
        return JSON.stringify({
            status: "error",
            message: err.message
        });
    }
}

基本テンプレートとの主な違い:

  1. サーバーロジックは Dataverse から現在の状態を読み取ります(クライアントのビューを信頼しません)
  2. ビジネスルールをサーバー側で検証します
  3. Server.Connector.Dataverse.UpdateRecord を介して結果を Dataverse に書き込みます
  4. 成功/失敗の結果を返します — クライアントが処理するための { valid: true/false } フラグではありません
  5. クライアントはこの 1 つのエンドポイントを呼び出します — 別途 Web API の PATCH 呼び出しを行いません
カスタムアクションのラッパーテンプレート

サーバーロジック項目で Dataverse カスタムアクション(Phase 2.1.2 でマッピング済み)をラップする場合は、Server.Connector.Dataverse.InvokeCustomApi を使用した次のパターンを使います。サーバーロジックはポータルに適したラッパーとして機能し、適切な Web ロール認可を適用して、カスタムアクションを /_api/serverlogics/<name> エンドポイント経由で公開します。

バインドされていないアクション:

// Server Logic: <name>
// Purpose: Wraps Dataverse custom action "<custom-action-name>" for portal consumption
// Custom Action: <custom-action-name> (unbound, action)
// API URL: https://<site-url>/_api/serverlogics/<name>

function post() {
    try {
        Server.Logger.Log("<name> POST called — invoking custom action <custom-action-name>");

        const body = JSON.parse(Server.Context.Body);

        // Build the request payload matching the custom action's input parameters
        const payload = JSON.stringify({
            // "<ParameterName>": body.<clientFieldName>
        });

        const result = Server.Connector.Dataverse.InvokeCustomApi(
            "POST",
            "<custom-action-name>",
            payload
        );

        Server.Logger.Log("<name> custom action completed successfully");

        return JSON.stringify({
            status: "success",
            data: result
        });
    } catch (err) {
        Server.Logger.Error("<name> POST failed: " + err.message);
        return JSON.stringify({
            status: "error",
            message: err.message
        });
    }
}

エンティティにバインドされたアクション:

function post() {
    try {
        Server.Logger.Log("<name> POST called — invoking bound action <custom-action-name>");

        const body = JSON.parse(Server.Context.Body);
        const entityId = body.entityId;

        const payload = JSON.stringify({
            // "<ParameterName>": body.<clientFieldName>
        });

        // Include the entity set and record ID, followed by the fully qualified action name
        const result = Server.Connector.Dataverse.InvokeCustomApi(
            "POST",
            "<entity-set-name>(" + entityId + ")/Microsoft.Dynamics.CRM.<custom-action-name>",
            payload
        );

        Server.Logger.Log("<name> bound action completed for entity " + entityId);

        return JSON.stringify({
            status: "success",
            data: result,
            entityId: entityId
        });
    } catch (err) {
        Server.Logger.Error("<name> POST failed: " + err.message);
        return JSON.stringify({
            status: "error",
            message: err.message
        });
    }
}

バインドされていない関数(読み取り専用、GET):

function get() {
    try {
        Server.Logger.Log("<name> GET called — invoking custom function <custom-function-name>");

        // Pass parameters as query string for functions
        const param1 = Server.Context.QueryParameters["param1"];
        const queryString = "<custom-function-name>(Param1='" + param1 + "')";

        const result = Server.Connector.Dataverse.InvokeCustomApi(
            "GET",
            queryString,
            null
        );

        Server.Logger.Log("<name> custom function completed successfully");

        return JSON.stringify({
            status: "success",
            data: result
        });
    } catch (err) {
        Server.Logger.Error("<name> GET failed: " + err.message);
        return JSON.stringify({
            status: "error",
            message: err.message
        });
    }
}

要点:

  • バインドされていないアクション:URL にアクション名を使用し、パラメーターを JSON 本文として渡します
  • エンティティにバインドされたアクション:URL パスにエンティティセットとレコード ID を含め、その後に Microsoft.Dynamics.CRM.<action-name> を続けます
  • 関数(GET):HTTP メソッドに "GET" を使用し、OData の関数呼び出し構文を使って URL 内でパラメーターを渡します
  • アクション(POST):HTTP メソッドに "POST" を使用し、パラメーターを JSON 本文のペイロードとして渡します
  • InvokeCustomApi は同期処理です。async/await は使用しないでください
  • サーバーロジックでは、カスタムアクション呼び出しに検証、変換、ログ記録を追加できます。単に呼び出しを中継するだけである必要はありません
  • Custom API の応答プロパティが判明している場合(Phase 2.1.2 より)、明確にするため、応答オブジェクトにマッピングします
Dataverse 応答の形式(フロントエンド統合で重要)

関数が Server.Connector.Dataverse.* メソッドの結果を返す場合、クライアントには二重にラップされたペイロードが届きます。これは、フロントエンド統合が壊れる最も一般的な原因です。関数を作成する前に、3 つの応答形式から 1 つを選び、Phase 9 用に選択内容を記録してください。アプローチ A — 生のパススルー(コネクタの結果をそのまま返す)、アプローチ B — コネクタの結果をラップするエンベロープ(Body を展開せず、{ status, data: result } を返す)、またはアプローチ C — 完全に正規化(サーバー側で Body を解析し、機能に特化した形式を返す。汎用ではないエンドポイントに推奨)。

二重ラップの説明、CreateRecord/entityid ヘッダーの動作、および各形式のサーバー側とクライアント側の例については、${PLUGIN_ROOT}/skills/add-server-logic/references/frontend-integration-reference.md → 「Dataverse Connector Response Format」を参照してください。

コード内でのシークレットの参照

サーバーロジックで Phase 2.3 で特定したシークレット値が必要な場合、値をハードコードしてはいけません。代わりに、環境変数を参照するサイト設定から、実行時に読み取ります。

const apiKey = Server.Sitesetting.Get("ExternalApi/ExchangeRateApiKey");

Phase 2.3 で計画したサイト設定名を使用してください。実際の環境変数とサイト設定の YAML は Phase 7 で作成します。

SDK の使用に関するガイダンス

このスキル内で Microsoft Learn の SDK 使用パターンを重複して記載しないでください。コネクタのメソッド、シグネチャ、サポートされているパターンの信頼できる情報源として Phase 3 で取得したドキュメントを使用し、承認済みの計画で記録されたタスク固有の注意事項のみを適用してください。

5.4 メタデータ YAML を作成する

計画のステータスが create である承認済みのサーバーロジック項目ごとに、YAML を手作業で作成するのではなく、決定的な書き込みスクリプトを使ってメタデータファイルを生成します。スクリプトは UUID を生成し、フィールドを正しい順序で書き込み、作成したファイルパスを JSON として返します。update / reuse 項目ではこの手順をスキップしてください — YAML はすでに存在するため、必要に応じて手動で更新します。

node "${PLUGIN_ROOT}/skills/add-server-logic/scripts/create-serverlogic-metadata.js" --projectRoot "<PROJECT_ROOT>" --name "<name>" --displayName "<human-readable display name>" --description "<description of what this server logic does>" --webRoleIds "<uuid1,uuid2,uuid3>"

生成される <PROJECT_ROOT>/.powerpages-site/server-logic/<name>/<name>.serverlogic.yml ファイルの構造は次のとおりです。

adx_serverlogic_adx_webrole:
  - <web-role-guid-1>
  - <web-role-guid-2>
  - <web-role-guid-3>
description: <description of what this server logic does>
display_name: <human-readable display name>
id: <generated-uuid>
name: <name>

重要な要件:

  • id フィールドは必須です — スクリプトは新しい UUID(v4)を生成します。これがないと、PAC CLI は Expected Guid for primary key 'id' でクラッシュします。
  • adx_serverlogic_adx_webrole — 手順 5.2 の Web ロール GUID の配列です。そのサーバーロジック項目に必要なロールのみを含めてください。
  • name — フォルダー名および .js ファイル名と一致させる必要があります(/_api/serverlogics/<name> で使われる URL に適した名前)。
  • display_name — 人が読みやすい名前です(例:「為替レート API」、「注文処理」)。
  • フィールドのアルファベット順 — フィールドはアルファベット順に並べる必要があります:adx_serverlogic_adx_webrole、description、display_name、id、name。
5.5 コードを検証する

保存する前に、以下の制約に照らしてコードを確認します。

制約確認内容
許可されたトップレベル関数のみget、post、put、patch、del 以外の関数がない
すべての関数が文字列を返すcatch ブロックを含むすべてのコードパスが文字列を返す
すべての関数に try/catch がある各関数本体が try/catch で囲まれている
すべての関数に Server.Logger がある関数の開始時にログを記録し、catch 内で Error を記録する
外部依存関係がないimport、require、module.exports がない
ブラウザー API がないfetch、XMLHttpRequest、setTimeout、console.log、document、window がない
必要な場合のみ async を使用await を使う関数のみ async として宣言されている
ECMAScript 2023 に準拠標準の JS 機能のみを使用する(オプショナルチェーン、Null 合体演算子などは使用可能)
5.6 Git コミット

承認済みのサーバーロジックファイルを作成した後、サーバーロジックの変更を git commit します。

HTML 計画がプロジェクト内で生成されている場合は、同じコミットに含めます(render スクリプトの JSON 応答から実際の出力パスを使用してください)。

出力:サーバーロジックの .js ファイルと .serverlogic.yml ファイルが作成、検証され、コミットされている


フェーズ 6:テーブル権限の構成(条件付き)

目標:サーバーロジックコード内の Server.Connector.Dataverse がアクセスする Dataverse テーブルのテーブル権限を設定します

このフェーズは、サーバーロジックが Server.Connector.Dataverse を使用する場合にのみ実行します。 サーバーロジックが Server.Connector.HttpClient(外部 API)のみを使用する場合、または Dataverse にまったくアクセスしない場合は、このフェーズ全体をスキップし、フェーズ 7 に進んでください。

Server.Connector.Dataverse はテーブル権限をバイパスしません — テーブル権限に従います。テーブル権限が構成されていない場合、Dataverse コネクターは実際のデータではなく、0 件のレコードを何も通知せずに返します。これはよくある混乱の原因です。

アクション:

6.1 Dataverse テーブルと必要な権限を特定する

フェーズ 5 で作成したサーバーロジックの .js ファイルを解析し、アクセスする Dataverse テーブルと実行する CRUD 操作を特定します。

Dataverse SDK メソッド必要なテーブル権限
RetrieveMultipleRecords("tablename", ...)読み取り
RetrieveRecord("tablename", ...)読み取り
CreateRecord("tablename", ...)作成
UpdateRecord("tablename", ...)書き込み
DeleteRecord("tablename", ...)削除

各メソッド呼び出しからエンティティセット名(第 1 引数)を抽出します。次の対応表を作成します。

テーブル(エンティティセット名)読み取り作成書き込み削除
accountsはい———
contactsはいはい——
6.2 テーブル権限アーキテクトを使用する

承認済みのサーバーロジック項目で Server.Connector.Dataverse を使用する場合は、table-permissions-architect エージェントを ${PLUGIN_ROOT}/agents/table-permissions-architect.md から呼び出し、必要なテーブル権限を判断して作成します。

プロンプト:

「この Power Pages SPA サイトを分析し、承認済みのサーバーロジック計画でアクセスする Dataverse テーブルのテーブル権限を提案してください。以下のテーブルに権限が必要です。

[手順 6.1 の必要な CRUD 権限とともに、サーバーロジック項目ごとにグループ化して各テーブルを列挙]

コンテキスト:

  • サーバーロジックが Server.Connector.Dataverse を使用するため、これらの権限が必要です。このコネクタはテーブル権限を適用するため、権限がない場合、コネクタは警告なしに 0 件のレコードを返します。
  • サーバーロジックがすべてのレコードを取得する場合、通常はスコープを Global にします。ただし、サーバーロジックが現在のユーザーで絞り込む場合は Contact スコープを使用します。
  • これらのサーバーロジック項目に割り当てられている Web ロールは次のとおりです:[フェーズ 5.2 の Web ロール名と GUID を列挙]
  • プロジェクトルート:[パス]

既存のテーブル権限と Web ロールを確認してください。新しい Web ロールが必要な場合は、create-web-role.js スクリプトを使用して作成してください。計画を提案し、承認後、決定論的なスクリプトを使用してテーブル権限の YAML ファイルを作成してください。」

エージェントは次の作業を行います。

  1. 既存のテーブル権限と Web ロールを検出する
  2. 必要に応じて、create-web-role.js を使用して不足している Web ロールを作成する
  3. テーブル権限の計画を提案する(HTML の可視化を含む)
  4. 計画モードでユーザーに計画を提示し、承認を求める
  5. 承認後、create-table-permission.js を使用して .powerpages-site/table-permissions/ にテーブル権限の YAML ファイルを作成する
6.3 Git コミット

テーブル権限(および新しい Web ロールがあればそれも)の作成後、テーブル権限の変更を Git にコミットします。

出力:サーバーロジックがアクセスするすべての Dataverse テーブルに対して、テーブル権限(および作成した場合は Web ロール)が設定されます


フェーズ 7:シークレットと環境変数の管理

目標:サーバーロジックで必要なシークレット値(API キー、クライアントシークレット、接続文字列)を、必要に応じて Azure Key Vault を利用し、Dataverse の環境変数として安全に保存します

このフェーズは、サーバーロジックでシークレットまたは機密性の高い設定値が必要な場合(フェーズ 2.3 で特定された場合)にのみ実行します。シークレットが不要な場合は、このフェーズをスキップしてフェーズ 8 に進みます。

アクション:

7.1 Key Vault の選択を確認する

ユーザーはフェーズ 2.3.1(計画の提示前)に Azure Key Vault を使用するかどうかをすでに選択しています。ここではその選択に従い、再度質問しないでください。

7.2a Azure Key Vault のパス

ユーザーがフェーズ 2.3.1 で Azure Key Vault を選択した場合:

ステップ 1 — 利用可能な Key Vault を一覧表示する:

node "${PLUGIN_ROOT}/scripts/list-azure-keyvaults.js"

スクリプトは、ユーザーの Azure サブスクリプションにある Key Vault の JSON 配列(name、resourceGroup、location)を出力します。

ステップ 2 — Key Vault を選択または作成する:

Key Vault が見つかった場合は、一覧を提示して、どれを使用するか尋ねます。

AskUserQuestion を使用します:

質問コンテキスト
シークレットの保存に使用する Azure Key Vault を選択してください。スクリプトの出力にある名前を提示します

Key Vault が見つからない場合は、どのように進めるかユーザーに尋ねます。

🚦 ゲート(plan · add-server-logic:7.2a.no-vaults): ユーザーのサブスクリプションに Key Vault が見つかりませんでした — 新規作成するか、プレーンな環境変数にフォールバックします。シークレット保存のフローを分岐させます。

トリガー: フェーズ 2.3.1 で Key Vault が選択されましたが、list-azure-keyvaults.js が空のリストを返しました。 確認する理由: Key Vault を自動作成すると、明示的な同意なしに Azure リソースがプロビジョニングされます。自動的にフォールバックすると、ユーザーが明示的に Key Vault を選択した後に、シークレットがプレーンな環境変数として保存されます。 キャンセルした場合: 何もありません — Azure または Dataverse への書き込みはまだ行われていません。

AskUserQuestion を使用します:

質問選択肢
サブスクリプションに Azure Key Vault が見つかりませんでした。新しく作成しますか、それともシークレットを環境変数に直接保存する方法に切り替えますか?新しい Key Vault を作成する(推奨)、環境変数に直接保存する

「新しい Key Vault を作成する」の場合:Key Vault の名前、リソースグループ、リージョンを尋ねてから作成します。

AskUserQuestion を使用します:

質問コンテキスト
新しい Key Vault の名前、リソースグループ、Azure リージョンを指定してください。Key Vault 名は 3~24 文字で、グローバルに一意である必要があります。先頭は英字とし、使用できる文字は英数字とハイフンのみです。プロジェクト名またはサイト名に基づいて名前を提案してください。
node "${PLUGIN_ROOT}/scripts/create-azure-keyvault.js" \
  --name "<vault-name>" \
  --resourceGroup "<resource-group>" \
  --location "<location>"

スクリプトは、name、resourceGroup、location を含む JSON オブジェクトを出力します。以降の手順では、作成した Key Vault を使用します。

「環境変数に直接保存する」の場合:フェーズ 7.2a の残りをスキップし、フェーズ 7.2b(環境変数に直接保存するパス)に進みます。

ステップ 3 — 各シークレットを Key Vault に保存する手順を案内する:

フェーズ 2.3 で特定した各シークレットについて、値をユーザー自身が保存するための手順を案内します。シークレットの値を尋ねてはいけません。シークレットの値が会話を通じて渡されることがあってはなりません。

ユーザーが希望する方法を選べるよう、両方の方法(CLI と Azure Portal)を提示します。

オプション A — Azure CLI(自動化に推奨):

ユーザーがコピーして実行できるよう、コマンドを番号付きリストで提示します。シークレット値がプロセス一覧に表示されないよう、標準入力形式を使用します。

For each secret, run the following command (replacing <YOUR_SECRET_VALUE> with the actual value):

1. <secret-name>:
   printf '%s' '<YOUR_SECRET_VALUE>' | node "${PLUGIN_ROOT}/scripts/store-keyvault-secret.js" \
     --vaultName "<selected-vault>" \
     --secretName "<secret-name>"

各コマンドは secretUri を含む JSON オブジェクトを出力すること、その出力(URI のみが含まれ、シークレットは含まれません)を共有してもらえればワークフローを続行できることを伝えます。

オプション B — Azure Portal:

各シークレットについて、次の手順を案内します。

1. Go to the Azure Portal (https://portal.azure.com)
2. Search for "Key vaults" in the top search bar and select it
3. Select the Key Vault: <selected-vault>
4. In the left menu under "Objects", click "Secrets"
5. Click "+ Generate/Import" at the top
6. Fill in the fields:
   - Upload options: Manual
   - Name: <secret-name>
   - Secret value: paste your secret value here
   - Leave other fields as defaults
7. Click "Create"
8. After creation, click on the secret name, then click the current version
9. Copy the "Secret Identifier" URI and share it here so the workflow can continue

Secret Identifier URI は https://<vault-name>.vault.azure.net/secrets/<secret-name>/<version> のような形式であり、共有してもらうのはこの URI(シークレットの値ではありません)であることを伝えます。

ステップ 4 — Dataverse に環境変数を作成する:

ユーザーが各コマンドの secretUri 出力を共有した後、Key Vault シークレットを参照する環境変数の定義を Dataverse に作成します。secret 型を使用します。

node "${PLUGIN_ROOT}/scripts/create-environment-variable.js" "<ENV_URL>" \
  --schemaName "<prefix_SecretName>" \
  --displayName "<Secret Display Name>" \
  --type "secret" \
  --value "<secretUri-from-step-3>"

ステップ 5 — 環境変数用のサイト設定を作成する:

各環境変数について、それに対応するサイト設定 YAML を作成します。

node "${PLUGIN_ROOT}/scripts/create-site-setting.js" \
  --projectRoot "<PROJECT_ROOT>" \
  --name "<SiteSetting/Name>" \
  --envVarSchema "<schemaName-from-step-4>"

これにより、envvar_schema と source: 1 を持つサイト設定が作成されます。これは、Power Pages に対して、Dataverse の環境変数(Key Vault をバックエンドとする)から値を解決するよう指示します。

7.2b 環境変数を直接使用する方法

ユーザーが Azure Key Vault を使用しないことを選択した場合:

手順 1 — プレースホルダー値を使用して環境変数を作成します:

フェーズ 2.3 で特定した各シークレットについて、プレースホルダー値を使用して Dataverse に環境変数を作成します:

node "${PLUGIN_ROOT}/scripts/create-environment-variable.js" "<ENV_URL>" \
  --schemaName "<prefix_SecretName>" \
  --displayName "<Secret Display Name>" \
  --value "PLACEHOLDER_SET_ACTUAL_VALUE"

手順 2 — 環境変数のサイト設定を作成します:

node "${PLUGIN_ROOT}/scripts/create-site-setting.js" \
  --projectRoot "<PROJECT_ROOT>" \
  --name "<SiteSetting/Name>" \
  --envVarSchema "<schemaName-from-step-1>"

手順 3 — 実際のシークレット値を設定する手順をユーザーに案内します:

シークレット値を尋ねないでください。会話を介して受け取ることは決してありません。代わりに、次のいずれかの方法で、各プレースホルダーを実際の値に更新するようユーザーに伝えてください:

  1. Power Apps maker portal(make.powerapps.com)— Solutions → Default Solution → Environment variables に移動し、表示名で変数を見つけて、値を更新します

更新が必要な環境変数の一覧(それぞれの表示名とスキーマ名)を提示し、ユーザーがどの変数を設定すればよいか正確にわかるようにします。

7.3 環境変数の設定を確認する

すべての環境変数とサイト設定を作成した後:

  • 各サイト設定 YAML が .powerpages-site/site-settings/ に作成されていることを確認します
  • 各 YAML に envvar_schema と source: 1 が含まれていることを確認します
  • サーバーロジックのコードが Server.Sitesetting.Get("<SiteSetting/Name>") を介して正しいサイト設定名を参照していることを確認します
7.4 Git コミット

環境変数のサイト設定の変更を Git コミットします。

出力:Dataverse に作成された環境変数(Azure Key Vault による裏付けの有無を問わない)、設定済みのサイト設定、正しい設定名を参照するサーバーロジック


フェーズ 8:サイト設定を構成する

目標:サーバーロジック機能のサイト設定をセットアップします

アクション:

8.1 サーバーロジックのサイト設定を構成する

この時点で .powerpages-site フォルダーが存在することが保証されています(フェーズ 1.5 で確認済み)。

以下のサイト設定は、サーバーロジックの動作を制御します。既定値と異なる設定、または特に必要な設定のみを作成してください:

設定説明既定値構成する場合
ServerLogic/Enabledサーバーロジック機能を有効化/無効化しますtrue明示的に無効化されており、再度有効にする必要がある場合のみ
ServerLogic/AllowedDomainsHttpClient が呼び出せる外部ドメインを制限しますすべてのドメインサーバーロジックが外部 API を呼び出し、セキュリティのために特定のドメインに制限したい場合
ServerLogic/TimeoutInSeconds最大実行時間120プラットフォームでは最大 120 秒 までに制限され、120 を超える値は通知なく切り詰められます。タイムアウトを長くするのではなく、短くする必要がある場合にのみ構成してください。
ServerLogic/AllowNetworkingToAllDomainsドメイン間のネットワーク通信を許可しますtrueAllowedDomains による制限を行う場合は false に設定します

既存のサイト設定作成スクリプトを使用します:

node "${PLUGIN_ROOT}/scripts/create-site-setting.js" --projectRoot "<PROJECT_ROOT>" --name "ServerLogic/AllowedDomains" --value "api.example.com,api.other.com" --description "Restrict server logic external API calls to these domains"
8.2 Git コミット

設定を作成した場合:

サイト設定の変更を Git コミットします。

出力:サイト設定を構成してコミットします(不要またはデプロイ済みの場合はスキップ)


フェーズ 9:クライアント側の統合

目標:フェーズ 1 で確認した既存のパターンに合わせて、サイトのフロントエンドコードからサーバーロジックのエンドポイントを呼び出せるようユーザーを支援します

サーバーロジックによってバックエンドが作成されますが、それを呼び出すフロントエンドコードがなければ、エンドポイントは使用されません。このフェーズでは、コードベースですでに確立されているパターンと規約を使って、サーバーロジック API を利用するフロントエンドコードを作成または更新します。

アクション:

9.1 統合範囲をユーザーに確認する

🚦 ゲート(計画・add-server-logic:9.1.frontend-scope): サーバーロジックをフロントエンド UI にも組み込むか、バックエンドで止めるかを決定します。

トリガー: フェーズ 8 が完了したとき(サーバーロジックのデプロイ準備完了)。 確認する理由: 自動で統合すると、ユーザーが自分で対応するつもりだった UI ファイルが変更されます。自動でスキップすると、アプリからエンドポイントにアクセスできなくなります。 キャンセル時に残るもの: ありません。サーバーロジックのバックエンドはすでにディスク上にあり、このプロンプトではフロントエンドへの反映を続けるかどうかだけを決定します。

AskUserQuestion を使用します。

質問選択肢
サーバーロジックのバックエンドを作成しました。フロントエンド UI にも完全に統合しますか?はい、UI に完全に統合する(推奨)、いいえ、フロントエンドは自分で対応する

「いいえ」の場合:フェーズ 10 に進みます。ただし、ユーザーがコピーできる API URL とコードスニペットを提示します。

9.2 フロントエンド統合リファレンスに従う

以下のリファレンスを、フロントエンド統合の方法、例、フレームワーク固有のパターンに使用します。

リファレンス:${PLUGIN_ROOT}/skills/add-server-logic/references/frontend-integration-reference.md

フェーズ 1.4 での Explore エージェントの調査結果と承認済みの計画に基づき、このリファレンスから統合方法を選び、フロントエンドに組み込むすべてのサーバーロジックエンドポイントに一貫して適用します。

9.3 フロントエンド統合を作成または更新する

リファレンスに従います。

  • サイトに既存のサービスレイヤーまたは API ユーティリティがある場合は、それを再利用します
  • サイトに確立された API クライアントのパターンがない場合に限り、軽量で CSRF に対応したヘルパーを作成します
  • 保守性が向上する場合は、複数のサーバーロジックエンドポイントをまとまりのあるサービスモジュールにグループ化します
  • コードベースですでにそのパターンが使われている場合に限り、フレームワーク固有のフック、コンポーザブル、サービスを追加します
  • サーバーロジックを実際の UI フローに完全に統合します。サービス/ヘルパーコードの作成だけで終わらせないでください
  • 新しいバックエンド動作にインターフェースからアクセスできるよう、関連するページ、コンポーネント、フォーム、ボタン、ユーザーフローを更新します
  • 新しいサーバーロジックエンドポイントで処理する想定のプレースホルダーデータ、モックハンドラー、一時的なアクションを置き換えます
  • UI が完成した機能として動作するよう、読み込み、成功、空、エラーの各状態を追加または維持します
  • 検証してから実行するエンドポイントの場合:保護された操作(例:ステータスの遷移)では、フロントエンドからサーバーロジックエンドポイントを呼び出す必要があります。同じフィールドに対して別途 Web API PATCH を実行してはいけません。その操作の UI(例:「送信」または「承認」ボタン)が Web API サービスではなく、サーバーロジックのサービス関数を呼び出すようにします
  • Dataverse を使用するエンドポイントの場合:フェーズ 5.3 で選択したレスポンス形式に合わせて、フロントエンドでの解析方法を設定します。形式ごとの具体的な解析方法については、フロントエンド統合リファレンスの「Dataverse Connector Response Format」を参照してください
  • レスポンス形式が不明確な場合:推測しないでください。サイトのデプロイ後、稼働中のサイトに対して /test-site を実行し、ネットワークタブから実際のサーバーロジックレスポンスを取得して、統合に反映します
9.4 Git コミット

フロントエンド統合コードを作成した場合:

フロントエンド統合の変更を git commit します。

出力:必要に応じてフロントエンドのサービス/フックを作成し、UI コンポーネント/ページに完全に統合したうえで、変更をコミットします


フェーズ 10:検証とテストのガイダンス

目標:コードを検証し、サーバーロジックをテストするために必要なものをすべてユーザーに提供します

アクション:

10.1 最終コード検証

作成した各 .js ファイルを読み直し、次の点を確認します。

  • 許可されているトップレベル関数(get、post、put、patch、del)のみである
  • すべての関数が文字列を返す
  • すべての関数に try/catch がある
  • すべての関数に Server.Logger の呼び出しがある
  • import、require、外部依存関係がない
  • ブラウザー API(fetch、XMLHttpRequest、setTimeout、console.log、document、window)がない
  • await を使用する関数にのみ async を指定している
  • SDK メソッドを正しく使用している(Phase 3 のドキュメントで確認済み)
  • HttpClient は外部 API にのみ使用している(Dataverse では使用しない)
  • Dataverse の操作には Dataverse コネクターを使用している

各 .serverlogic.yml ファイルを読み直し、次の点を確認します。

  • id フィールドが存在し、有効な UUID である
  • adx_serverlogic_adx_webrole 配列が空でなく、少なくとも 1 つの Web ロールが含まれている
  • name がフォルダー名および .js ファイル名と一致している
  • display_name と description が設定されている
  • フィールドがアルファベット順に並んでいる
  • ファイル名が一致している:フォルダー名、.js 名、.serverlogic.yml 名、および name フィールドの値がすべて同じである
10.1b 最終サイト整合性ゲート

サーバーロジックと、任意のクライアント側統合が完了したら、次を実行します。

node "${PLUGIN_ROOT}/scripts/validate-site-integrity.js" --projectRoot "<PROJECT_ROOT>"

完了を報告する前、またはデプロイを依頼する前に、すべてのブロッキングエラーを修正します。両方向からレビュー結果を確認して報告し、内容を詳しく展開します。バックエンドのみの実行でもこのゲートを実行します。SPA ソースに変更がない場合、表示ソースの整合性チェックは何も行いません。以降にソースを変更した場合は、再度実行します。

10.2 API URL の提示

各エンドポイントの URL をユーザーに伝えます。

https://<site-url>/_api/serverlogics/<server-logic-name>
10.3 テスト手順

テスト手順を提示します。

  1. まずサイトをデプロイします — サーバーロジックを呼び出すには、/deploy-site を使ってデプロイしておく必要があります
  2. GET 以外のリクエストには CSRF トークンが必要です — サーバーロジックのエンドポイントへの POST、PUT、PATCH、DELETE 呼び出しには CSRF トークンが必要です。/_layout/tokenhtml からトークンを取得し、__RequestVerificationToken ヘッダーに含めます。GET リクエストは偽造防止検証の対象外であり、読み取り専用の呼び出しにトークンは不要です。
  3. 認証 — サーバーロジックにはサイトの認証設定が適用されます。認証済みセッションからの呼び出しでは、Cookie ベースの認証が自動的に使用されます。匿名アクセスの可否はガバナンス設定によって異なります。
  4. ブラウザーコンソールからのテスト:

サイトのスタックに合った正確な呼び出し方法については、Phase 9 のフロントエンド統合リファレンスを使用してください。

  1. 診断情報を確認します — Server.Logger の出力は Power Pages デザインスタジオの診断情報で確認できます
  2. エンドポイントがエラーまたは予期しない応答を返す場合 — Playwright と X-Ms-UserTrace を使用したデバッグの流れについては、サーバーロジック実行エラーのトラブルシューティングを参照してください

出力:コードの検証完了、API URL の提示、テスト手順の提示


Phase 11:レビューとデプロイ

目標:実施した作業の概要を提示し、デプロイを提案します

アクション:

11.1 スキルの使用状況を記録

参照:${PLUGIN_ROOT}/references/skill-tracking-reference.md

参照先にあるスキル使用状況の記録手順に従って、このスキルの使用状況を記録します。--skillName "AddServerLogic" を使用してください。

11.2 概要の提示

実施したすべての作業の概要を提示します。

手順状態詳細
Server Logic JS作成済み作成した .powerpages-site/server-logic/<name>/<name>.js ファイルをそれぞれ列挙
Server Logic YAML作成済み作成した .powerpages-site/server-logic/<name>/<name>.serverlogic.yml ファイルをそれぞれ列挙
HTML プラン作成済み/更新済みレンダリングスクリプトの出力に記載された実際のパス
関数実装済み各サーバーロジック項目で実装したメソッドの概要
使用した SDK 機能—各サーバーロジック項目で使用した機能の概要
テーブルのアクセス許可作成済み/スキップaccounts(読み取り)、contacts(読み取り、作成)など
シークレットと環境変数作成済み/スキップ環境変数(Key Vault 経由または直接)、envvar_schema を含むサイト設定
サイト設定作成済み/スキップServerLogic/AllowedDomains など
クライアント側サービス作成済み/スキップ作成または更新したフロントエンドのサービスファイルを列挙
UI 統合作成済み/スキップサーバーロジックのエンドポイントに完全に接続されたページ、コンポーネント、フォーム、またはアクション
API URL—各 /_api/serverlogics/<name> URL を列挙
11.3 デプロイの確認

🚦 ゲート(plan · add-server-logic:11.3.deploy): 実装後のデプロイ確認 — デプロイされるまでサーバーロジックのエンドポイントにはアクセスできません。

トリガー: すべてのサーバーロジック成果物が書き込まれ、コミット済みであること。 確認する理由: 自動デプロイでは誤った環境が選択されます。 キャンセルした場合: 何も起きません — 成果物はディスク上に残り、デプロイは実行されません。

AskUserQuestion を使用します。

質問選択肢
サーバーロジックの作業が完了しました。公開するには、サイトをデプロイする必要があります。今すぐデプロイしますか?はい、今すぐデプロイします(推奨)、いいえ、後でデプロイします

🚦 ゲート(plan · add-server-logic:11.3.test): デプロイ後の検証確認 — /test-site を実行して、新しいエンドポイントを本番環境でテストします。

トリガー: 前のゲートでのデプロイが成功したこと。 確認する理由: スキップしても問題ありません(手動テストは引き続き可能です)。自動で /test-site を実行すると、実行時間が追加されます。 キャンセルした場合: 何も起きません — デプロイはすでに完了しています。

「はい、今すぐデプロイします」の場合: /deploy-site スキルを実行して、サイトをデプロイします。

デプロイが成功した後、AskUserQuestion を使用します。

質問選択肢
サイトがデプロイされました。検証のために、今 /test-site を実行しますか?はい、/test-site を実行します(推奨)、いいえ、テストをスキップします

「はい、/test-site を実行します」の場合: /test-site スキルを実行します。

「いいえ、後でデプロイします」の場合: 次のように了承し、リマインドします。

「問題ありません。準備ができたら、/deploy-site を使用してサイトをデプロイしてください。サイトがデプロイされるまで、サーバーロジックのエンドポイントにはアクセスできません。」

11.4 デプロイ後の注意事項

デプロイ後(またはデプロイを省略した場合)、ユーザーに以下を伝えてください。

  • エンドポイントをテストする:各 /_api/serverlogics/<name> URL に適切な HTTP メソッドでリクエストします(GET 以外のリクエストでは CSRF トークンを含めてください)。
  • サイト全体の検証を推奨する:デプロイ後、公開サイトをエンドツーエンドで検証するために /test-site を実行するかどうかを尋ねます。
  • ログを確認する:Power Pages デザインスタジオの診断に表示される Server.Logger の出力を使って問題をデバッグします。
  • テーブルのアクセス許可:このサーバーロジックで使用する Dataverse テーブルのアクセス許可は設定済みです。後から Dataverse テーブルを追加した場合は、テーブルのアクセス許可を再度設定してください。アクセス許可がないと、Server.Connector.Dataverse は 0 件のレコードをサイレントに返します。
  • タイムアウト:デフォルトの実行タイムアウトは 120 秒です。これはプラットフォームの最大値でもあり、120 を超える値はサイレントに 120 秒へ制限されます。
  • 匿名アクセス:サイトのガバナンス制御で匿名アクセスが無効になっている場合、匿名ユーザーは外部システムと連携するサーバーロジックを呼び出せません。
  • プレビュー機能:Server Logic は現在プレビュー段階です。Microsoft Learn で最新情報を確認してください。
  • プレースホルダー値が設定された環境変数:フェーズ 7 でプレースホルダー値を設定した環境変数を作成した場合、テスト前に実際のシークレット値へ更新するようユーザーに伝えてください。更新は次の方法で行えます。
    1. Power Platform 管理センター — 環境 → 環境を選択 → 環境変数 → 表示名で検索 → 値を更新
    2. Power Apps メーカーポータル — ソリューション → ソリューションを開く → 環境変数 → 値を編集

出力:概要を提示し、デプロイを完了または延期して、デプロイ後のガイダンスを提供します。


サーバーロジック実行エラーのトラブルシューティング

デプロイ済みのサーバーロジックエンドポイントがエラーや想定外の応答を返す場合、根本原因は通常、X-Ms-UserTrace レスポンスヘッダーに隠れています。このヘッダーには、ランタイム診断ログを含む Base64 エンコード済みのデータが格納されています。Power Pages Edge ブラウザー拡張機能でも同じデータを確認できますが、稼働中のサイトで反復検証する際は、レスポンスヘッダーを調べるのが最も早い方法です。

サーバーロジックの呼び出しに失敗した場合、または想定と異なる応答が返された場合は、次の手順に従ってください。

1. Playwright でブラウザーから公開サイトを開く

Playwright MCP ツールを使ってサイトを操作します。

  1. デプロイ済みサイトの URL(/activate-site から返される、または Power Pages 管理センターに表示される websiteUrl)に移動します。
  2. エンドポイントで認証が必要な場合は、ユーザーにサインインを依頼し、完了の確認を待ちます。
  3. エラーが発生しているサーバーロジックエンドポイントを呼び出す操作(ボタンのクリック、フォームの送信など)を実行するか、fetch() でエンドポイントを直接呼び出します。
2. ネットワーク応答を取得する

mcp__plugin_power-pages_playwright__browser_network_requests を使ってネットワークアクティビティを一覧表示し、/_api/serverlogics/<name> へのリクエストを探します。次の項目を確認してください。

  • HTTP ステータスコード(例:200、400、500)
  • レスポンスボディ(検証に失敗した場合は、一般的なエラーや空のペイロードであることがよくあります)
  • 最も重要な情報:X-Ms-UserTrace レスポンスヘッダー — 実際の診断ログはここに格納されています

browser_network_requests でレスポンスヘッダーを直接確認できない場合は、mcp__plugin_power-pages_playwright__browser_evaluate に切り替え、fetch() 呼び出しからヘッダーを読み取ります。

const res = await fetch('/_api/serverlogics/<name>', { method: 'GET', credentials: 'include' });
const trace = res.headers.get('X-Ms-UserTrace');
return { status: res.status, body: await res.text(), trace };
3. X-Ms-UserTrace ヘッダーをデコードする

ヘッダーの値は Base64 エンコードされた JSON です。これをデコードします。

デコードしたペイロードには、実際のエラーメッセージや、スクリプトの検証に失敗した場合は許可されていないパターンなど、診断ログのエントリが含まれています。

修正後、/deploy-site で再デプロイし、変更をすぐに反映させるためにサイトを再起動します。


重要な注意事項

すべてのフェーズを通じて
  • 各フェーズの進捗を追跡するため、TaskCreate/TaskUpdate を使用します
  • コードを書く前に、Phase 3 で必ず Microsoft Learn のドキュメントを取得します。ドキュメントが信頼できる情報源です
  • 重要な判断ポイントでは、ユーザーに確認を求めます
  • マイルストーンごとにコミットします。サーバーロジックのコード、テーブルのアクセス許可(該当する場合)、シークレット/環境変数(該当する場合)、サイト設定、フロントエンド連携(該当する場合)の後にコミットします
  • 徹底的に検証します。サーバーロジックには厳格な制約があり、違反すると実行時エラーが発生します
重要な判断ポイント(ユーザーの回答を待つ)
  1. Phase 1.5:今すぐデプロイするか、キャンセルするか(.powerpages-site が見つからない場合は必須)
  2. Phase 2.1.2:既存の Dataverse カスタムアクションを使用するか、一から作成するか(カスタムアクションが見つかった場合)
  3. Phase 2:要件を確認する(目的、名前、HTTP メソッド、シークレット)
  4. Phase 4:コードを書く前に実装計画の承認を得る
  5. Phase 6.2:table-permissions-architect の計画を確認し、承認を得る(Dataverse コネクタを使用する場合)
  6. Phase 2.3.1:Azure Key Vault を使用するか、環境変数を直接使用するかを選択する(シークレットが必要な場合)
  7. Phase 7.2a の Step 2:新しい Key Vault を作成するか、環境変数を直接使用するかを選択する(Key Vault が見つからない場合)
  8. Phase 9.1:フロントエンド連携を作成するか、スキップするかを選択する
  9. Phase 11.3:今すぐデプロイするか、後でデプロイするかを選択する
SDK パターンの信頼できる情報源

このスキルファイルを、SDK の正式なリファレンスとして扱わないでください。Phase 3 で取得する Microsoft Learn の情報が、SDK の使用パターン、サポートされるメソッド、シグネチャ、コネクタの動作に関する信頼できる情報源です。計画と実装のメモには、タスク固有の判断のみを記載してください。

進捗の追跡

Phase 1 を開始する前に、すべてのフェーズを含むタスクリストを TaskCreate で作成します。

タスクの件名activeForm説明
サイトの存在を確認するサイトの前提条件を確認中プロジェクトのルートを特定し、フレームワークを検出し、既存のサーバーロジックとフロントエンドのパターンを調べ、.powerpages-site が存在することを確認する(必須)
要件を把握する要件を収集中ユーザーの意図、必要なサーバーロジックファイルの数、各項目のメソッド/機能、Dataverse カスタムアクションの有無、必要なシークレットを特定する
最新のドキュメントを取得するMicrosoft Learn のドキュメントを取得中Microsoft Learn で、最新の Server Logic SDK リファレンスとサンプルを検索する
実装計画を確認するユーザーと計画を確認中計画(サーバーロジックの一覧、関数、SDK 機能、外部 API、シークレット)を提示し、コードを書く前に確認を得る
サーバーロジックを実装するサーバーロジックのコードを作成中必要な Web ロールを特定/作成し、承認済みの .js ファイルと .serverlogic.yml ファイルを作成して、コードを検証する
テーブルのアクセス許可を設定するDataverse テーブルのアクセス許可を設定中(条件付き).js ファイルから Dataverse テーブルを解析し、table-permissions-architect を起動して、アクセス許可の YAML ファイルを作成する
シークレットと環境変数を管理するシークレットと環境変数を設定中(条件付き)Azure Key Vault を推奨し、Key Vault の一覧表示、シークレットの保存、Dataverse での環境変数の作成、envvar_schema を使用したサイト設定の作成を行う
サイト設定を構成するサイト設定を構成中必要に応じて ServerLogic/* のサイト設定をセットアップする
クライアント側の連携フロントエンドとサーバーロジックを接続中フロントエンド連携のリファレンスに従い、必要に応じてサービスファイルを作成/更新し、UI とサーバーロジックのエンドポイントを完全に接続する
検証とテストのガイダンス検証とテストのガイダンスを準備中最終検証、API URL、CSRF トークンの手順、テストガイド
確認とデプロイ概要を確認し、デプロイを準備中概要を提示し、デプロイするかを確認して、デプロイ後のガイダンスを提供する

各タスクの開始時に TaskUpdate で in_progress に設定し、完了時に completed に設定します。フェーズ間の移行時と最終概要の前に TaskList を使用し、未完了の作業項目が残っていないことを確認します。


Phase 1:サイトの存在確認から開始します

コメント