add-cloud-flow について
Power Automate のクラウドフローを Power Pages SPA に追加したり、登録済みフローを別の UI に接続したりするワークフロースキルです。フローの選択、ロール設定、メタデータ作成、フロントエンド連携を扱います。
主な機能
- 01新しい Power Automate フローの接続
- 02登録済みフローの別 UI への連携
- 03フローのシナリオに応じた Web ロール設定
- 04型付きクライアントサービスコードの生成
- 05ファイル作成前の計画確認
活用シーン
- 01Power Pages フォームをクラウドフローに接続
- 02既存フローを別のページやコンポーネントに追加
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ microsoft/ power-platform-skills --skill add-cloud-flowインストール後、Claude Code で/add-cloud-flowを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/cloud-flow-plan.htmlscripts/create-cloud-flow-metadata.jslist-cloud-flows.jsvalidate-cloudflow.js詳細
プラグインの確認:
node "${PLUGIN_ROOT}/scripts/check-version.js"を実行します。メッセージが出力された場合は、続行する前にユーザーに表示してください。
クラウドフローの追加
1 つ以上の Power Automate クラウドフローを Power Pages SPA サイトに接続するか、すでに登録済みのフローを追加のページやコンポーネントに組み込みます。新しいフローの場合、このスキルでは次の処理を行います。
.powerpages-site/cloud-flow-consumer/にadx_cloudflowconsumerメタデータ YAML を作成します- フローのシナリオと対象ユーザーに基づいて Web ロールを割り当てます
- CSRF 認証を使用してフローをトリガーする、クライアント側の TypeScript/JavaScript サービスコードを生成します
すでに登録済みのフローの場合、このスキルではメタデータとロールの作成を省略し、クライアント側の統合に直接進みます。既存のフローを新しい UI の場所に組み込みます。
基本原則
- 1 回の実行で複数のフローに対応:ユーザーは一度に複数のフローを追加できます。デプロイについて確認する前に、すべてのフローをまとめて計画し、実装します。
- 実行前に確認:ファイルを作成する前に、すべてのフロー、ロール、理由を含む完全な HTML プランを提示します。
- アクセス権は Web ロールで管理:すべてのフローに少なくとも 1 つの Web ロールが必要です。匿名ユーザーロールも使用できますが、確認が必要です。
- シナリオに基づいてロールを決定:ロールを選ぶ前に、各フローの処理内容とトリガーするユーザーを把握します。
- TaskCreate/TaskUpdate を使用:作業を始める前に、すべてのフェーズを記録します。
- サイトの整合性を保つ:フローをページまたはコンポーネントに組み込む前に、
${PLUGIN_ROOT}/references/site-modification-integrity.mdを読みます。設定されている場合は、新たに表示されるすべての状態をローカライズし、UI の双方向性を保ち、拡張に安全な実装にします。
前提条件:
.powerpages-siteがデプロイ済みの既存の Power Pages SPA サイト- PAC CLI が認証済みであること(
pac auth whoが成功する必要があります)- Azure CLI が認証済みであること(Azure サブスクリプションの有無にかかわらず
az login --allow-no-subscriptionsが動作します。Dataverse と Power Platform のトークンは AAD スコープです)
初回のリクエスト: $ARGUMENTS
ワークフロー
- 前提条件を確認 — プロジェクトを特定し、
.powerpages-siteの存在を確認して、Web ロールと既存のフローを一覧にします - 利用可能なフローを一覧表示 — Power Automate Flow RP API からフローを取得します
- フローを選択し、シナリオを把握 — ユーザーが 1 つ以上のフローを選択し、それぞれのシナリオと対象ユーザーを特定します
- Web ロールを決定 — 理由を示して、各フローに必要な最小限のロールを提案します
- プランを確認 — すべてのフローの HTML プランを表示し、ユーザーの承認を得ます
- メタデータを作成 — 各フローの
.cloudflowconsumer.ymlを書き込み、不足している Web ロールを先に作成します - クライアント側の統合 — フロントエンドから各フローを呼び出すための型付きサービスコードを生成します
- 検証と要約 — すべての YAML を検証し、スキルの使用状況を記録して、デプロイを提案します
フェーズ 1:前提条件の確認
目標:Power Pages プロジェクトを特定し、すべての前提条件が満たされていることを確認します
アクション:
- 8 つすべてのフェーズを含む ToDo リストを作成します(進捗の追跡の表を参照)
1.1 プロジェクトの特定
現在のディレクトリまたは直下のサブディレクトリで powerpages.config.json を探します。
見つからない場合:まず /create-site を使用してサイトを作成するようユーザーに伝えます。
1.2 設定の読み取り
powerpages.config.json を読み取り、siteName(表示およびプランのレンダリングに使用)を取得します。
1.3 .powerpages-site が存在するか確認する
プロジェクトルートに .powerpages-site フォルダーがあるか探します。
見つからない場合:
🚦 ゲート (plan · add-cloud-flow:1.3.deploy-first):
.powerpages-siteがありません — クラウドフローの YAML はその中にあります。先にデプロイするか、中止してください。トリガー: フェーズ 1.3 で
.powerpages-siteディレクトリが見つかりませんでした。 なぜ確認するのか: 存在しないパスに書き込まれたクラウドフローの YAML はデプロイされません。 キャンセルした場合: 何も残りません — YAML ファイルは書き込まれません。
AskUserQuestion を使用します:
| 質問 | オプション |
|---|---|
クラウドフローを追加するには .powerpages-site が必要です。今すぐサイトをデプロイしますか? | はい、今すぐデプロイする (必須)、キャンセル |
「はい、今すぐデプロイする」の場合: まず /deploy-site を呼び出し、その後フェーズ 2 に進みます。
「キャンセル」の場合: 中止します。
1.4 既存の Web ロールを読み取る
.powerpages-site/web-roles/ からすべての .webrole.yml ファイルを読み取り、利用可能なロールを一覧化します。各ロールの id、name、adx_anonymoususersrole、adx_authenticatedusersrole を記録します。
1.5 既存のクラウドフローを確認する
.powerpages-site/cloud-flow-consumer/ に既存の .cloudflowconsumer.yml ファイルがあるか確認します。各ファイルについて、以下を読み取ります:
processid— フローのworkflowEntityIdname— フローの表示名adx_CloudFlowConsumer_adx_webrole— 割り当てられた Web ロールの UUID
これらを 登録済みフロー リストとして保存します。これらのフローはすでにメタデータと Web ロールが構成されていますが、他のページやコンポーネントで追加のフロントエンド統合が必要になる場合があります。
1.6 フロントエンドフレームワークを検出する
package.json を読み取り、フレームワーク (React、Vue、Angular、Astro) を検出します。フレームワークとその規約をフェーズ 7 のために記録します。検出のマッピングについては ${PLUGIN_ROOT}/references/framework-conventions.md を参照してください。
出力: プロジェクトルート、サイト名、フレームワーク、利用可能な Web ロール、登録済みフロー (processid、name、Web ロールを含む)
フェーズ 2: 利用可能なフローを一覧表示する
目標: PowerPages トリガーを持つすべての Power Automate クラウドフローを取得する
アクション:
list-cloud-flows スクリプトを実行します (内部で pac auth who から環境を読み取ります):
node "${PLUGIN_ROOT}/skills/add-cloud-flow/scripts/list-cloud-flows.js"
これは Power Automate Flow RP API を、フィルター properties/definitionSummary/triggers/any(t: t/kind eq 'powerpages') を付けて呼び出します。結果には以下が含まれます:
| フィールド | ソース | 用途 |
|---|---|---|
id | properties.workflowEntityId | YAML 内の processid、クライアント側 API 呼び出しの URL |
flowRpName | flow.name | Flow RP 識別子 |
displayName | properties.displayName | ユーザーに表示、YAML に name として書き込み |
description | properties.description | ユーザーに表示 |
state | properties.state | ユーザーに表示 (Active/Draft) |
2 つのリストに分けます:
- 未登録フロー:
idがフェーズ 1.5 のどのprocessidとも一致しないフロー — これらには完全なセットアップ (メタデータ + ロール + クライアント側) が必要です - 登録済みフロー:
idがフェーズ 1.5 のprocessidと一致するフロー — これらはすでにメタデータとロールを持っていますが、追加のページやコンポーネントに統合できます
エラーの処理:
-
認証メッセージとともに終了コード 1 → ユーザーに
az login --allow-no-subscriptionsの実行を促します -
API からフローがゼロ件 (PowerPages トリガーを持つフローがまったく存在しない) → この環境に PowerPages トリガーを持つ Power Automate フローが見つからなかったことをユーザーに伝えます。まずフローを作成するよう案内します:
「この環境に PowerPages トリガーを持つ Power Automate クラウドフローは見つかりませんでした。このスキルを使用するには、まず Power Automate で 「When a Power Pages flow step is run」 トリガーを持つフローを作成し、その後このスキルを再度実行してサイトに接続する必要があります。」
ワークフローを停止します — フェーズ 3 に進まないでください。
-
未登録フローがゼロ件だが登録済みフローが存在する → 停止しないでください。登録済みフローのみを利用可能な状態 (追加のフロントエンド統合用) でフェーズ 3 に進みます。
出力: 未登録フローのリストと登録済みフローのリスト
フェーズ 3:フローを選択し、シナリオを把握する
目標:ユーザーの意図を把握し、最も関連性の高いフロー(追加の統合対象となる、すでに登録済みのフローを含む)を提案して、ユーザーに確認または調整してもらい、選択した各フローのシナリオを特定します。
アクション:
3.1 ユーザーの意図を分析し、フローを提案する
一覧全体を表示する前に、ユーザーの最初のリクエスト($ARGUMENTS)を、未登録のフローと登録済みのフローの両方に照らして分析します。表示名、説明、シナリオの推定を使って、ユーザーが説明したニーズに具体的なフローを対応付けます。
意図を照合するときは、まず登録済みのフローを確認します。ユーザーは新しいフローの登録ではなく、既存のフローを新しいページやコンポーネントに組み込もうとしている場合があります。
-
ユーザーが具体的なニーズを説明している場合(例:「お問い合わせフォームに自動化を追加する」、「メール通知フローを接続する」):名前または説明がリクエストに近いフローを特定し、それぞれが適切な候補である理由を説明しておすすめとして提示します。また、提案が適切でない場合に備えて、残りのフローも追加の選択肢として表示します。
Based on your request, I recommend: ⭐ 1. Contact Form Submission — Sends an email when a contact form is submitted (Active) → Matches your request to add automation for the contact form Other available flows: 2. Support Ticket Handler — Creates a case record from user input (Active) 3. Newsletter Signup — Adds the user's email to a mailing list (Draft) -
ユーザーのリクエストが一般的な場合(例:「クラウドフローを追加する」、「いくつかのフローを接続する」):おすすめを提示せず、全フローの一覧を表示します。
Available flows: 1. Contact Form Submission — Sends an email when a contact form is submitted (Active) 2. Support Ticket Handler — Creates a case record from user input (Active) 3. Newsletter Signup — Adds the user's email to a mailing list (Draft)
両方のカテゴリがある場合は、明確に分けて提示します。
New flows (not yet registered):
1. Newsletter Signup — Adds the user's email to a mailing list (Active)
Already registered (available for additional frontend integration):
2. Contact Form Submission — Already connected, can be wired into more pages
3. Support Ticket Handler — Already connected, can be wired into more pages
🚦 ゲート(計画 · add-cloud-flow:3.1.select-flows): 検出済みおよび登録済みのフローから複数選択します。以降のフェーズ 4〜7 の処理に使用します。
トリガー: フェーズ 2 の list-cloud-flows で 1 つ以上のフローが返された場合。 確認が必要な理由: 誤ったフローを登録したり(新しい
.cloudflowconsumer.ymlファイルが書き込まれます)、誤った既存フローをフロントエンドに再接続したりするのを防ぎます。 キャンセルした場合: 何も残りません。YAML ファイルやクライアントコードはまだ書き込まれていません。
AskUserQuestion を使用します。
| 質問 | 選択肢 |
|---|---|
| どのフローを追加または統合しますか?新規フローと登録済みフローの両方から選択できます。 | (フロー名の一覧または複数選択。該当する場合は、おすすめのフローを事前に強調表示します) |
利用可能なフローが 10 個を超える場合は、名前または番号を入力するようユーザーに求めます(複数の場合はカンマ区切り)。
3.2 選択したフローにタグを付ける
選択した各フローについて、ソースに応じてタグを付けます。
| タグ | 意味 | 実行するフェーズ |
|---|---|---|
new | 未登録のフロー — セットアップ全体が必要です | フェーズ 4 → 5 → 6 → 7(メタデータ + ロール + クライアント側) |
integration-only | 登録済み — メタデータとロールが存在します | フェーズ 7 に進みます(クライアント側の統合のみ) |
3.3 フローごとにシナリオを特定する
選択した各フローについて、名前と説明からシナリオを特定します。
| シナリオの種類 | 例 | トリガーするユーザー |
|---|---|---|
| フォーム送信 | お問い合わせフォーム、フィードバック、アンケート | 認証済みまたは匿名の訪問者 |
| ユーザーのセルフサービス | プロフィール更新、リクエスト、休暇申請 | 認証済みユーザーのみ |
| 管理者による操作 | 一括処理、コンテンツ承認、データエクスポート | 管理者/特定のロールのみ |
| バックグラウンド/システム | 定期同期、データ補完 | ポータルユーザーが直接トリガーすることはありません |
フローのシナリオが不明確な場合は、フローごとに AskUserQuestion を使用します。
| 質問 | コンテキスト |
|---|---|
| 「[フロー名]」はサイトで何をしますか?誰がトリガーしますか? | ロールの割り当てに必要です |
integration-only フローの場合も、フロントエンドのどこにどのようにフローを接続するかを決めるために、シナリオを確認する必要があります(フェーズ 7)。
3.4 フローごとにクライアント側の関数名を決定する
各フローについて、クライアント側サービスの camelCase 関数名を導出します:
- 表示名から特殊文字と接続詞を削除します
- 例:「PowerPages -> Send an email notification (V3)」→
sendEmailNotification - 例:「Contact Form Submission」→
submitContactForm
integration-only フローについては、コードベースにトリガー関数がすでに存在するかどうか(このスキルの以前の実行によるもの)を確認します。存在する場合は、その関数名を再利用します — 重複を作成しないでください。まだ存在しない場合にのみ、新しい関数を作成します。
出力: 選択されたフローのリスト。それぞれにタグ(new または integration-only)、シナリオ、対象ユーザー、クライアント側の関数名を含みます
フェーズ 4: Web ロールを決定する
目標: 各 new フローのシナリオに基づいて、最小限の Web ロールのセットを提案します
integration-onlyフローではスキップします — これらにはすでに.cloudflowconsumer.ymlで Web ロールが割り当てられています。それらのロールを再提案したり変更したりしないでください。
アクション:
4.1 フローごとのロール要件を分析する(新規フローのみ)
| シナリオ | 推奨されるロール |
|---|---|
| 任意の訪問者(未認証を含む) | Anonymous Users(確認 — セキュリティへの影響あり) |
| ログイン済みユーザーのみ | Authenticated Users |
| 特定のグループのみ | グループに一致するカスタムロール |
デフォルトですべてのロールを割り当てないでください。 フローごとに最小限のセットを使用します。同じバッチ内の異なるフローが異なるロールセットを持つことができます。
4.2 既存のロールと照合する
すべてのフローで提案された各ロールについて、.powerpages-site/web-roles/ に存在するかどうかを確認します。ロールを 既存 または 提案/新規 としてマークします。
4.3 ロールごとの理由を組み立てる
各フローに割り当てられた各ロールについて、その理由を説明する文を 1 つ書きます:
- プロフィールフォームの
Authenticated Users:「ログイン済みユーザーのみが自分のプロフィールを更新できます。」 - お問い合わせフォームの
Anonymous Users:「未認証の訪問者がお問い合わせリクエストを送信できる必要があります。」 - メールフローの
Blog Authors:「Blog Authors は、この通知をトリガーする投稿を送信する主要なアクターです。」
4.4 匿名ロールにフラグを立てる
いずれかのフローに Anonymous Users が割り当てられている場合は、これを記録します — HTML プランは警告バナーを表示し、確認ステップで明示的にそれを提示する必要があります。
出力: 理由付きのフローごとのロールセット、作成が必要なロールのリスト
フェーズ 5: プランをレビューする
目標: すべてのフローについて HTML プランをレンダリングし、ファイルを書き込む前にユーザーの承認を得ます
アクション:
5.1 プランデータを構築する
プラン JSON を組み立てます(メモリ内に保持 — ディスクには書き込みません)。CLOUD_FLOWS_DATA に選択されたすべてのフローを含め、new と integration-only を区別します:
{
"SITE_NAME": "<site name>",
"PLAN_TITLE": "Cloud Flow Integration Plan",
"SUMMARY": "<N new flows + M integration-only flows, scenarios, key role assignments>",
"WEB_ROLES_DATA": [
{
"id": "<uuid or temp-id>",
"name": "<role name>",
"desc": "<description>",
"builtin": false,
"isNew": true,
"isAnonymous": false,
"color": "#0078d4"
}
],
"CLOUD_FLOWS_DATA": [
{
"flowId": "<workflowEntityId>",
"name": "<flow display name>",
"displayName": "<flow display name>",
"description": "<flow description>",
"state": "Active",
"tag": "new | integration-only",
"scenario": "<scenario type>",
"rationale": "<why this flow is being added or where it will be additionally integrated>",
"webRoles": [
{ "id": "<role-uuid>", "reasoning": "<why this role>" }
]
}
],
"RATIONALE_DATA": [
{ "icon": "⚡", "title": "<title>", "desc": "<reasoning>" }
]
}
integration-only フローの場合、webRoles は .cloudflowconsumer.yml の既存のロールを反映する必要があります(読み取り専用 — 変更されません)。rationale は、フローが追加で統合される場所を説明する必要があります(例:「既存の Contact Form フローをサポートページに配線する」)。
5.2 HTML プランをレンダリングする
node "${PLUGIN_ROOT}/scripts/render-cloudflow-plan.js" \
--output "<PROJECT_ROOT>/docs/cloud-flow-plan.html" \
--data-inline '<json>'
レンダリングスクリプトは既存のファイルを上書きしません。呼び出す前に、デフォルトの出力パス(<PROJECT_ROOT>/docs/cloud-flow-plan.html)がすでに存在するかどうかを確認します。存在する場合は、コンテキストに基づいて新しいわかりやすいファイル名を選択します — 例:cloud-flow-plan-contact-form.html、cloud-flow-plan-apr-2026.html。選択した名前を --output で渡します。
レンダリングされたファイルをデフォルトのブラウザで開きます(macOS では open、Windows では start、Linux では xdg-open)。
5.3 ユーザーに確認する
フロー数、シナリオ数、ロール数、匿名ロールに関する警告の有無を、簡潔に CLI で要約します。
🚦 ゲート(計画 · add-cloud-flow:5.3.plan-approval): Web ロール/
.cloudflowconsumer.yml/クライアントコードを作成する前に、レンダリングされた HTML 計画の最終承認を得ます。トリガー: フェーズ 5.2 で HTML 計画をレンダリングしました。 確認する理由: Web ロールの割り当てを誤ったままコミットするおそれがあります(特に、認証で保護されたフローに Anonymous Users を割り当てる場合)。
.powerpages-site/cloud-flow-consumer/に孤立した YAML ファイルが残るおそれもあります。 キャンセルした場合: 何も残りません。YAML やフロントエンドの変更はまだありません。
AskUserQuestion を使用します:
| 質問 | 選択肢 |
|---|---|
| ブラウザーでクラウドフローの計画を確認してください。内容は正しいですか? | 承認して実装(推奨)、変更を依頼、キャンセル |
「変更を依頼」の場合:変更内容を尋ね、更新して再レンダリングし、再度提示します。 「キャンセル」の場合:停止します。
出力:すべてのフローについてユーザーが承認した計画
フェーズ 6:メタデータの作成
目標:Web ロール(新規の場合)を作成してから、承認済みの計画に含まれるすべての new フローについて .cloudflowconsumer.yml を書き込みます。
integration-onlyフローではスキップします。これらのフローには、すでに.cloudflowconsumer.ymlと Web ロールがあります。メタデータを再作成または変更しないでください。フェーズ 7(クライアント側の統合のみ)で処理します。
承認済みの計画に integration-only フローしか含まれていない場合(new フローがない場合)は、このフェーズ全体をスキップしてフェーズ 7 に進みます。
アクション:
6.1 不足している Web ロールを作成する
承認済みの計画に、まだ存在しないロール(new フロー用)が含まれている場合は、ここで /create-webroles を呼び出します。
完了後、.powerpages-site/web-roles/ を再度読み込み、すべての新しいロールの id 値を取得します。
6.2 新しいフローごとに処理する
承認済みの計画に含まれるすべての new フローについて、手順 6.3~6.4 を繰り返します。
6.3 フロー API URL を決定する
/_api/cloudflow/v1.0/trigger/<workflowEntityId>
6.4 メタデータ作成スクリプトを実行する
node "${PLUGIN_ROOT}/skills/add-cloud-flow/scripts/create-cloud-flow-metadata.js" \
--projectRoot "<PROJECT_ROOT>" \
--fileSlug "<url-safe-slug>" \
--flowName "<flow-display-name>" \
--flowId "<workflowEntityId>" \
--flowTriggerUrl "" \
--flowApiUrl "/_api/cloudflow/v1.0/trigger/<workflowEntityId>" \
--webRoleIds "<uuid1>,<uuid2>" \
--metadata "<flow-display-name>"
--fileSlug:表示名を小文字にし、特殊文字をハイフンに置き換えた文字列。最大 50 文字です。
--flowName:表示名をそのまま name YAML フィールドに書き込みます。
生成される YAML(PAC CLI SPA git 形式):
adx_*スカラーのプレフィックスを削除:adx_flowapiurl→flowapiurl、adx_processid→processidadx_cloudflowconsumerid→id。adx_websiteidは省略- M2M キー
adx_CloudFlowConsumer_adx_webroleはそのまま保持 statecode/statuscodeのデフォルト値は省略。空文字列は''として書き込み- フィールドをアルファベット順に並べ替え
6.5 Git コミット
すべての YAML ファイル(および新しい Web ロールがあればそれも)の作成後、Git コミットを 1 回だけ行います。HTML 計画ファイルを含めてください(レンダリングスクリプトの JSON レスポンスから実際の出力パスを使用します)。
出力:new フローごとに .cloudflowconsumer.yml を 1 つ作成し、コミットします(integration-only フローではスキップ)
フェーズ 7:クライアント側の統合
目標:サイトのフロントエンドから登録済みの各フローを呼び出す、型付きサービスコードを生成します。
クラウドフローは、/_api/cloudflow/v1.0/trigger/<workflowEntityId> への認証済み POST によって呼び出します。リクエストには /_layout/tokenhtml から取得した CSRF トークンを含め、ペイロードは eventData キーでラップしたうえで、JSON 文字列に変換する必要があります。
アクション:
7.1 既存のフロントエンドのパターンを調査する
Explore エージェントを使って、サイトをスキャンします:
「Power Pages サイトのフロントエンドに既存のパターンがあるか確認してください。以下を調べてください。
src/shared/、src/services/、src/api/などに既存の API サービスファイルがあるか- CSRF トークンの既存の処理(
__RequestVerificationToken、_layout/tokenhtml)- フレームワーク(React/Vue/Angular/Astro)と、その規約(フック、コンポーザブル、サービス)
- コードベースに既存のクラウドフロー呼び出し(
/_api/cloudflow/)があるか。すでに呼び出されているフローと、その呼び出し元のページ/コンポーネントを記録してください。 調査結果をすべて報告してください。」
integration-only フローでは、Explore エージェントの調査結果のうち 4 点目が重要です。フローがすでにどこで組み込まれているかがわかるため、既存の呼び出し箇所を重複させずに、別のページ/コンポーネントを新しい統合先にできます。
7.2 Cloud Flow サービスの作成または更新
クラウドフローのトリガーには、サイトに既存の OData フェッチラッパーを使用しないでください。
Dataverse Web API を対象とする一元化された API クライアント(例:
powerPagesFetch)がサイトにある場合でも、ここでは使用しないでください。クラウドフローのトリガー URL(/_api/cloudflow/v1.0/trigger/...)は、OData 固有のリクエストヘッダーを受け付けない別のエンドポイントです。OData ラッパーを使用すると、リクエストが失敗します。クラウドフローの呼び出しには、直接
fetchを使用するか、同等の低レベル HTTP クライアント(例:Angular のHttpClient)を使用してください。Dataverse Web API のヘッダーを自動的に追加する OData 固有のラッパーやヘルパーは使用しないでください。サイトで既存の CSRF トークンヘルパーがエクスポートされている場合は再利用できますが、HTTP リクエストはfetchまたは選択した低レベルクライアントで直接実行してください。
フレームワークと既存のパターンに応じて、次のようにします。
サイトにすでに API サービスレイヤーがある場合:新しいフロー関数を追加します。
サービスレイヤーがない場合:src/services/cloudFlowService.{ts,js}(またはフレームワークに相当する場所)を作成します。
integration-only フローの場合:トリガー関数がすでにサービスファイルにある場合は、重複して作成せず、再利用します。コードベースに既存の関数がない場合に限り、新しいトリガー関数を追加します。
サービスの構成
すべてのフロートリガー呼び出しで必須です。これらのヘッダーがないと、リクエストは 500 エラーを返します。
__RequestVerificationToken:/_layout/tokenhtmlから取得した CSRF トークンX-Requested-With:XMLHttpRequest
ペイロードは、JSON 文字列化した文字列として
eventDataにラップする必要があります。これは Power Pages のクラウドフローエンドポイントが想定する形式です。{ "eventData": "{\"Email\":\"[email protected]\"}" }
サービスファイルには、getCsrfToken ヘルパーと、フローごとのトリガー関数を含める必要があります。コードベースに getCsrfToken ヘルパーがすでにある場合は再利用し、ない場合は作成します。いずれの場合も、各トリガー関数は必ずこれを呼び出し、上記の両方のヘッダーを含めてください。
CSRF ヘルパー(既存のものを再利用するか、新規作成します):
async function getCsrfToken(): Promise<string> {
const res = await fetch('/_layout/tokenhtml');
const html = await res.text();
const match = html.match(/value="([^"]+)"/);
if (!match) throw new Error('CSRF token not found');
return match[1];
}
フローごとのトリガー関数(登録されたフローごとに 1 つ):
// Trigger: <flow display name>
// API: /_api/cloudflow/v1.0/trigger/<workflowEntityId>
export async function <camelCaseFunctionName>(payload: Record<string, unknown> = {}): Promise<unknown> {
const token = await getCsrfToken();
const response = await fetch('/_api/cloudflow/v1.0/trigger/<workflowEntityId>', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'__RequestVerificationToken': token,
'X-Requested-With': 'XMLHttpRequest',
},
body: JSON.stringify({ eventData: JSON.stringify(payload) }),
});
if (!response.ok) {
throw new Error(`Cloud flow trigger failed: ${response.status} ${response.statusText}`);
}
// 202 Accepted = flow has no Response action (fire-and-forget); 200 OK = flow returns data
if (response.status === 202) return null;
return response.json();
}
フレームワーク固有のパターン:
| フレームワーク | 規約 | 出力 |
|---|---|---|
| React | サービス関数をラップし、ローディング/エラー状態を管理するカスタムフック useCloudFlow<Name>() | src/hooks/useCloudFlow.ts |
| Vue | ローディング/エラー状態に ref を使用するコンポーザブル useCloudFlow<Name>() | src/composables/useCloudFlow.ts |
| Angular | 上記と同じ生の fetch トリガー関数をラップするインジェクタブルな CloudFlowService(ヘッダーと eventData ペイロードの形式を厳密に維持しない限り、HttpClient に切り替えないでください) | src/app/services/cloud-flow.service.ts |
| Astro | 通常の非同期ユーティリティ関数(フレームワークのラッパーは不要) | src/utils/cloudFlow.ts |
すべてのフロー関数を 1 つのファイルにまとめます。フローごとに個別のファイルを作成しないでください。
7.3 UI への組み込み
関連するページ/コンポーネントを読み込み、呼び出し箇所、ローディング状態、成功/エラー時のフィードバックを追加します。フローで処理する想定のプレースホルダーやモックのハンドラーがあれば置き換えます。
integration-only フローの場合、これがスキル実行全体の主要な成果物です。フローを組み込む新しい対象ページまたはコンポーネントを特定し(ユーザーのリクエストと Phase 3.3 のシナリオに基づきます)、既存のトリガー関数をインポートして、適切なローディング/エラー処理とともに組み込みます。すでに正常に動作している既存の呼び出し箇所は変更しないでください。
7.4 Git コミット
サービスファイルと UI の変更をコミットします。
出力:作成または更新した cloudFlowService.{ts,js}(または相当するもの)、UI への組み込み
Phase 8:検証と要約
目標:作成したすべての YAML を検証し、スキルの使用状況を記録し、要約を提示して、デプロイを提案します
アクション:
8.1 各 YAML を検証する
integration-onlyフローではスキップしてください — これらの YAML は今回の実行で作成も変更もされていません。newフローの YAML のみを検証してください。
作成した各 .cloudflowconsumer.yml について、次を確認してください。
-
idが有効な UUID である -
processidがフローのworkflowEntityIdと一致する -
adx_CloudFlowConsumer_adx_webroleが空でない - 配列内のすべてのロール UUID に対応する
.webrole.ymlファイルが存在する -
nameがフローの表示名と一致する -
adx_がプレフィックスのスカラー項目がない(adx_processid、adx_websiteid、adx_nameがない) -
statecodeとstatuscodeが存在しない
8.1b クライアント側の統合を検証する
フェーズ 7 で作成したサービスファイルを読み、次を確認してください。
- サービスファイルが想定されるパス(例:
src/services/cloudFlowService.tsまたはフレームワークに相当するパス)に存在する -
getCsrfTokenヘルパーが存在する — ファイル内で定義されているか、別のモジュールからインポートされている - 登録された各フローに対応するエクスポート済みのトリガー関数がある
- 各トリガー関数が
getCsrfToken()を呼び出し、必須のヘッダーを両方設定している__RequestVerificationTokenに CSRF トークンの値が設定されているX-Requested-With: XMLHttpRequest
- 各トリガー関数の fetch URL が、対応するフローの
/_api/cloudflow/v1.0/trigger/<workflowEntityId>と完全に一致する - リクエストボディが
JSON.stringify({ eventData: JSON.stringify(payload) })の形式でペイロードをラップしている —JSON.stringify(payload)のみではない - OData 固有のラッパー(例:
powerPagesFetch)が使用されていない — 生のfetchのみを使用している - 少なくとも 1 つの UI コンポーネントまたはページが、トリガー関数をインポートして呼び出している
いずれかの確認に失敗した場合は、続行する前にサービスファイルまたは UI の問題を修正してください。
8.1c 最終的なサイト整合性ゲート
すべてのクラウドフロー UI 統合とスキル固有の検証が完了した後、次を実行してください。
node "${PLUGIN_ROOT}/scripts/validate-site-integrity.js" --projectRoot "<PROJECT_ROOT>"
完了を提示する前、またはデプロイを依頼する前に、ブロッキングエラーをすべて修正してください。両方向からレビュー結果を確認して報告し、内容を展開してください。その後にソースを変更した場合は、このゲートを再実行してください。
8.2 スキルの使用を記録する
参照:
${PLUGIN_ROOT}/references/skill-tracking-reference.md
--skillName "AddCloudFlow" を使用してください。
8.3 概要を提示する
| 手順 | ステータス | 詳細 |
|---|---|---|
| 新しいフローの追加 | 完了 / N/A | 各 new フロー名を一覧表示(すべてが integration-only の場合は「N/A」) |
| integration-only フロー | 完了 / N/A | 各 integration-only フロー名と対象ページ/コンポーネントを一覧表示 |
| シナリオ | 特定済み | フローごとに 1 行 |
| Web ロール | 作成済み/既存/スキップ | ロール名を一覧表示(integration-only の場合はスキップ) |
| メタデータファイル | 作成済み/スキップ | 各 .cloudflowconsumer.yml のパスを一覧表示(integration-only の場合はスキップ) |
| クライアントサービス | 作成済み/更新済み | サービスファイルのパス |
| UI 統合 | 完了 | 更新したコンポーネント/ページ(すべてのフローに新しい呼び出し箇所) |
| HTML プラン | 作成済み | レンダリングスクリプトの出力にある実際のパス |
8.4 デプロイするか確認する
🚦 ゲート(plan · add-cloud-flow:8.4.deploy): 実装後のデプロイ確認プロンプト — デプロイされるまでフローは起動しません。
トリガー: すべてのフロー YAML とクライアント統合の準備が完了しています。 確認する理由: 自動デプロイでは、誤った環境が選択されます。 キャンセルした場合: 何も起きません。成果物はディスクに残り、デプロイは実行されません。
AskUserQuestion を使用します。
| 質問 | 選択肢 |
|---|---|
| すべて準備ができました。フローを有効にするため、サイトをデプロイしますか? | はい、今すぐデプロイする(推奨)、いいえ、後でデプロイする |
🚦 ゲート(plan · add-cloud-flow:8.4.test): デプロイ後の検証プロンプト —
/test-siteを呼び出し、フローのトリガーエンドポイントが 202/200 を返すことを確認します。トリガー: 前のゲートでデプロイが成功しました。 確認する理由: スキップしても問題ありません(手動テストは引き続き可能です)。自動で
/test-siteを呼び出すと、実行時間が延び、Playwright のトラフィックが発生します。 キャンセルした場合: 何も起きません。デプロイはすでに完了しています。
「はい」の場合:/deploy-site を呼び出します。成功した後、AskUserQuestion を使用します。
| 質問 | 選択肢 |
|---|---|
クラウドフローの統合をエンドツーエンドで検証するため、/test-site を実行しますか? | はい、テストを実行する、いいえ、手動でテストする |
「はい、テストを実行する」の場合:コンテキストを指定して /test-site を呼び出します。フロー API がトリガーされるシナリオをテストします。サイト上で、/_api/cloudflow/v1.0/trigger/<workflowEntityId> を呼び出す操作(フォームの送信やボタンのクリックなど)を行い、リクエストが 202 Accepted または 200 OK を返すことを確認し、Power Automate の実行履歴でフローが実行されたことを確認します。
「いいえ」の場合:デプロイするまでフローとクライアント側の呼び出しは機能しないことをユーザーに伝え、デプロイ済み環境でフローのトリガーが正しく機能するかを検証するため、後で /test-site を実行するよう提案します。
8.5 デプロイ後の注意事項
- フローのトリガー URL:デプロイ後、ポータルのランタイムによって自動的に設定されます。Power Pages デザインスタジオで確認してください。
- テスト:
/test-siteを使用して統合を検証します。割り当てられたロールを持つユーザーとしてサインインし、フローをトリガーする操作を行い、/_api/cloudflow/v1.0/trigger/<id>が 202/200 を返すことを確認してから、Power Automate の実行履歴を確認します。 - 匿名フロー:シークレットウィンドウでテストしてください。
- ロールの変更:YAML の
adx_CloudFlowConsumer_adx_webroleを編集してから、再デプロイしてください。 - 後からフローを追加する場合:このスキルを再度実行してください。新しいフローはセットアップ全体に利用でき、登録済みのフローは別のページでの追加のフロントエンド統合に利用できます。
重要な注意事項
すべてのフェーズを通じて
- 複数のフロー:コミットする前、またはフェーズ 7 に進む前に、承認済みの計画にあるすべてのフローを処理します
- 最小限のロール:デフォルトで全ロールを割り当てないでください。シナリオに必要なものだけを使用します
- 匿名ユーザー:計画と確認ステップで、必ず明示的に提示します
- 作成時にトリガー URL が空欄:想定どおりです。デプロイ時にポータルのランタイムによって設定されます
- fileSlug と flowName:
--fileSlugはファイル名のみ、--flowNameは YAML のnameフィールドです - クライアントサービスファイル:フローごとに 1 ファイルではなく、すべてのフローを 1 つのサービスファイルにまとめます。確認を求めず、必ず UI に接続します
- CSRF ヘッダーは必須:すべてのフロートリガー関数で
getCsrfToken()を呼び出し、__RequestVerificationTokenとX-Requested-With: XMLHttpRequestの両方を送信する必要があります。どちらかを省略すると 500 エラーになります - ペイロードの形式:リクエストボディは
JSON.stringify({ eventData: JSON.stringify(payload) })でなければなりません。クラウドフローのエンドポイントは、eventDataキーの下にネストされた、二重に文字列化された JSON 文字列としてペイロードを受け取ります - 統合のみのフロー:すでに登録されているフローでは、フェーズ 4~6(ロールとメタデータ)を省略します。主な成果物は、フェーズ 7 で新しいフロントエンドの呼び出し箇所を追加することです。これらのフローについて、既存の
.cloudflowconsumer.ymlファイルや Web ロールの割り当ては変更しないでください。サービスファイルに既存のトリガー関数がある場合はそれを再利用し、新しい UI の呼び出し箇所だけを追加します - 利用可能なフローがない場合:環境に PowerPages トリガーを持つフローがない場合(API の結果が 0 件の場合)、ワークフローを停止し、まず Power Automate で「When a Power Pages flow step is run」トリガーを使ってフローを作成するようユーザーに案内します
主な判断ポイント(ユーザーの応答を待つ)
- フェーズ 1.3:今すぐデプロイするか、キャンセルするか(
.powerpages-siteがない場合) - フェーズ 3.1:追加または統合するフロー(新規および/または登録済み)
- フェーズ 3.3:フローごとのシナリオ/対象ユーザーを明確化する(不明確な場合)
- フェーズ 5.3:ファイルを書き込む前に HTML 計画を承認する
- フェーズ 8.4:今すぐデプロイするか、後でデプロイするか
進行状況の追跡
フェーズ 1 を開始する前に、TaskCreate を使用してすべてのフェーズを含むタスクリストを作成します:
| タスクの件名 | activeForm | 説明 |
|---|---|---|
| 前提条件を確認 | 前提条件を確認中 | プロジェクトを探し、.powerpages-site を確認し、Web ロールと既存のフローを読み取り、フレームワークを検出する |
| 利用可能なフローを一覧表示 | クラウドフローを取得中 | Flow RP API を呼び出し、PowerPages トリガーを持つフローを取得する |
| フローを選択し、シナリオを把握 | シナリオの詳細を確認中 | ユーザーが 1 つ以上のフローを選択し、シナリオと関数名を決定する |
| Web ロールを決定 | ロール要件を分析中 | フローごとに、ロール単位の理由を添えて最小限のロールを提案する |
| 計画を確認 | ユーザーと計画を確認中 | すべてのフローの HTML 計画を表示し、承認を得る |
| メタデータを作成 | クラウドフローのメタデータを書き込み中 | 不足している Web ロールを作成してから、各フローの YAML を書き込む |
| クライアント側の統合 | クライアント側コードを生成中 | 型付きサービス関数を作成し、UI に接続する |
| 検証して要約 | 検証して要約中 | YAML を検証し、スキルの使用状況を記録し、概要を提示して、デプロイを提案する |
各タスクの開始時に TaskUpdate を使用して in_progress にし、完了時に completed にします。
フェーズ 1:前提条件の確認から開始してください