ken_nogi/NodeSrv/apps/healthcheck-survey-bot/README.md
Kenichiro NOGI 83d568a493 feat(healthcheck-survey-bot): HC-WAワークフローを60ノードから14ノードへ全面リビルド
分岐ロジック・Pleasanter/LINEWORKS API呼び出しをCodeノードへ集約する新ルールに
合わせて再構築。IF/JWT/Execute Workflow/Data Tableは専用ノードのまま維持しつつ、
業務ロジックは4つのCodeノードに集約した。デプロイ・n8n API呼び出しは未実施。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 18:29:30 +09:00

87 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# healthcheck-survey-bot
健康診断管理(SiteId 508971)×LINEWORKS Bot連携。508971の`SiteSettings.Processes`
をフロー定義として使い、n8n上でBot対話型のStatus管理を行う。
設計書: `NodeSrv/docs/superpowers/specs/2026-09-05-healthcheck-lineworks-survey-n8n-design.md`
実装計画: `NodeSrv/docs/superpowers/plans/2026-09-05-healthcheck-lineworks-survey-n8n.md`
## 実機調査メモ2026-09-05確認
508971への新規テストProcess追加なしで、既存本番プロジェクト「実行予算WF申請」SiteId 376872
取得済み`processes.json``Pleasanter/実行予算WF申請/configs/production/site-376872_実行予算WF申請/processes.json`
に入力検証タブを使ったProcessの実例があり、そこからJSON構造を確認できた。
Processの入力検証タブは`SiteSettings.Processes[].ValidateInputs`配列として保存される。
各要素は`{"Id": number, "ColumnName": string, "Required": boolean}`(実例: `{"Id": 1, "ColumnName": "Class021", "Required": true}`)。
配列名は`Validations`ではなく`ValidateInputs`。値を設定していない項目(クライアント/サーバ正規表現、エラーメッセージ、最小/最大等)は
キー自体が省略される可能性が高い(今回の実例では未設定のため確認できていない)。
Task 5processFlow.jsの`getValidationColumnNames`はこの構造(`process.ValidateInputs[].ColumnName`)を前提に実装する。
## n8nリソースID一覧
(Task 8〜11完了後、ここに作成したData Table ID・ワークフローIDを記録する)
- Data Table `healthcheck_bot_state`: `jqMDa2YZTI4f0iQ7`
- projectId: `LOcxF69Gm4PvnkqA``org-master-sync`用プロジェクトを流用)
- 列: `resultId`, `targetEmail`, `currentStatus`, `pendingProcesses`, `awaitInput`, `awaitProcessId`, `awaitColumn`すべてstring型
- 注記: 設計上の8列目`updatedAt`はn8n Data Tableのシステム予約列名`POST /data-tables`が`400 Column name "updatedAt" is reserved as a system column name.`を返すのため、列定義には含めていない。各行の更新日時はn8nが自動管理する`updatedAt`メタデータで代替する。
- ワークフロー `HC-SUB: プロセス実行と案内送信`: `XRqcykbG2LuAjGG2`
- ファイル: `workflows/hc-sub-run-process-and-notify.json`Execute Workflow Trigger、入力`{resultId, processId}`
- **プロジェクト全体のn8nワークフロー構築ルール2026-09-05改訂に合わせて7ード構成へ全面リビルド。旧19ード版個別キーごとのData Table Getード×7、HTTP Requestード×6を並べた構成を置き換える。** 同じワークフローID`XRqcykbG2LuAjGG2`へのPUTで上書きする想定デプロイはコントローラーが実施、本タスクではJSON作成・ローカル検証のみ
- active化済みExecute Workflow Triggerサブワークフローは呼び出し元から実行可能にするためactive必須、`asKvC5LSVg3q8tuU`と同じ運用)— 再デプロイ後も設定は維持される想定
- ード構成7ード、リニア接続:
1. `Execute Workflow Trigger`(入力: `resultId`, `processId`
2. `Data Table`「設定値一括取得」: `workflow_config_values``bNkadTyDgDepYx2p`)を`filters`無し・`returnAll:true`で一括取得個別キーごとのGetードを廃止
3. `Code`「Pleasanter照会・選択肢組み立て」: 設定値のMap化、(任意)Process実行、レコード取得、サイト設定取得(getsite)、Botマスタ取得(484184)、対象者メール解決、選択肢組み立てまでを1ードに集約。Pleasanter API呼び出しはすべて`this.helpers.httpRequest`n8n Codeード公式ヘルパーで発行
4. `Code`「JWTクレーム組み立て」: JWTクレームJSON文字列の組み立てとLINEWORKS `button_template`のactions配列組み立てを1ードに集約
5. `JWT`ード「Sign JWT」`operation: sign`, `algorithm: RS256`, Credential: 「LINEWORKS Bot Private Key (v4)」id `Hw0qlEaGfLPnQWp1`
6. `Code`「アクセストークン取得・LINEWORKS送信」: LINEWORKSアクセストークン取得とメッセージ送信を1ードに集約`this.helpers.httpRequest`
7. `Data Table`「状態更新」: `healthcheck_bot_state``jqMDa2YZTI4f0iQ7`)へ`insert`
- 秘密情報・SiteId等はすべて`workflow_config_values``bNkadTyDgDepYx2p`から「設定値一括取得」1ードで取得し、直後のCodeードで`configKey`→`configValue`のMapに変換して参照。ワークフローJSONに秘密値のハードコードなし
- Execute Workflow Triggerの入力`resultId`/`processId`)は、後続ノードの直接の入力でない箇所では必ず`$('Execute Workflow Trigger').item.json...`のようにード名を明示して参照している旧版にあった「Data Tableード通過後に裸の`$json`を参照してしまうバグ」の再発防止)
- 未検証・要判断の暫定実装ありTask 12以降で要確認:
①484184(`LINEWORKS_BOT_MASTER_SITE_ID`)からのBotId解決ロジック実データ構造未調査のため`SiteSettings.BotIds`または`Processes[].BotId`を仮定し、無ければ例外を投げる。「JWTクレーム組み立て」ードに実装
②`/api/users/get`のレスポンス形状(配列/単一オブジェクト両対応の防御的実装、「Pleasanter照会・選択肢組み立て」ードに実装
③LINEWORKSトークン取得は`URLSearchParams`インスタンスをそのまま`body`に渡す形に修正済み(`.toString()`化や`json:true`併用はn8nのform-urlencoded自動処理と衝突する懸念があったため回避。レスポンスは文字列/オブジェクトいずれでも`access_token`を読めるよう防御的にパースしている。ただしn8n本体での実機動作は本タスクでは未検証
④`Data Table`Insertードの`columns.mappingMode`/`value`/`schema`の形状旧19ード版から流用。旧版はデプロイ実績があるためスキーマ自体は疑わしくないが、実書き込みでの動作は本タスクでは未再検証
- テスト実行Step 4相当は本タスクでは未実施。次回、捨てレコードでの疎通確認とユーザー確認が必要
- ワークフロー `HC-WP: Statusプッシュ通知`: `swXfpoDtwZDT3Hwk`
- ファイル: `workflows/hc-wp-status-push.json`
- Webhook: `https://n8n32.next-hd.net/webhook/healthcheck-status-push``X-Api-Key`ヘッダー認証、body `{resultId, processId}`
- active化済み
- `X-Api-Key`は`workflow_config_values`の`HEALTHCHECK_WP_API_KEY`と照合。秘密値のハードコードなし
- 実際のcurl疎通テスト本番508971書き込み・LINEWORKS実送信を伴うは未実施。ユーザー確認後に実施する
- デプロイ・活性化はサブエージェントのBashサンドボックスが実APIキー使用を一律ブロックしたためコントローラーが直接実行した詳細: `task-10-report.md`
- ワークフロー `HC-WA: LINEWORKS応答受信`: **ローカルJSON作成のみ、n8n未デプロイ**id未採番
- ファイル: `workflows/hc-wa-lineworks-response.json`
- **プロジェクト全体のn8nワークフロー構築ルール2026-09-05改訂に合わせて14ード構成で全面リビルド。旧60ード版個別キーごとのData Table/HTTP Requestードを積み上げ、awaitInput分岐をSwitch+各分岐に案内送信一式を重複配置した構成)はこのタスクでの再構築に伴い置き換えた。**IF・JWT・Execute Workflow・Data Tableは各ルールに従い専用ードのままだが、それらは機械的に必要な最小限IF×2, JWT×1, Execute Workflow×1, Data Table×3であり、本来Codeードに集約可能な分岐ロジック・Pleasanter/LINEWORKS API呼び出しはすべて4つのCodeードに集約したブリーフの目安「11ード」に対し実際は14ードだが、これはIF/JWT/Execute Workflowを専用ードに保つというルール自体が要求する固定オーバーヘッドであり、60ードからの削減という趣旨は達成している
- 本タスクの担当範囲はワークフローJSONのローカル作成・検証までで、n8n Public APIの呼び出しデプロイ・activateは一切実施していない。コントローラー側での`node scripts/deploy-workflow.js workflows/hc-wa-lineworks-response.json`実行後、実際のワークフローIDをこの行に追記すること
- ード構成14ード:
1. `Webhook``healthcheck-lineworks-response`, `rawBody:true`
2. `Data Table`「設定値一括取得」: `workflow_config_values`を`filters`無し・`returnAll:true`で一括取得
3. `Code`「署名検証・対象レコード特定」: HMAC-SHA256署名検証、対象者メール→PleasanterUserId解決、508971の対象レコード検索`ColumnFilterHash`までを1ードに集約。0件/複数件はthrow自動判定しない
4. `Data Table`「待機状態取得」: `healthcheck_bot_state`から該当resultIdの行を取得
5. `Code`「分岐処理・アクション決定」: `awaitInput`none/date/file、または待機状態自体が無い場合に応じた分岐ロジック全体を1ードに集約。`action`execute/send/errorと次の待機状態`nextAwaitInput`/`nextAwaitProcessId`/`nextAwaitColumn`を1つのJSONオブジェクトとして出力する
6. `Data Table`「状態更新」: 5の出力を使い`healthcheck_bot_state`を無条件で`update`
7. `IF`「action==execute」: true→8、false→9
8. `Execute Workflow`「HC-SUB実行」Task 9, `XRqcykbG2LuAjGG2`→13
9. `IF`「action==send」: true→10、false→14
10. `Code`「JWTクレーム組み立て」: 484184からのBotId解決とJWTクレーム・LINEWORKSメッセージ内容の組み立てを1ードに集約
11. `JWT`「Sign JWT」`operation:sign`, `RS256`, Credential: 「LINEWORKS Bot Private Key (v4)」`Hw0qlEaGfLPnQWp1`
12. `Code`「アクセストークン取得・LINEWORKS送信」: LINEWORKSアクセストークン取得とメッセージ送信を1ードに集約→13
13. `Respond to Webhook(成功)`: 8と12の両方から接続される共有の成功応答ード
14. `Respond to Webhook(異常系)`: 9のfalse分岐action=="error")専用
- **分岐ノードの出力の流れ方(設計上の重要ポイント)**: ード5は「今回どうするかaction/processId/messageText」と「次に書き込む待機状態next*」を1つの出力オブジェクトにまとめて返す。ード6状態更新ード5の直接の後続ードなのでそのまま`$json.next*`を参照して無条件更新するが、ード6通過後の`$json`はData Table Updateの返り値更新後の行データに置き換わり、ード5の`action`/`processId`/`messageText`等は失われる。そのため、ード7以降IF・Execute Workflow・JWTクレーム組み立て・Respond to Webhook(異常系))はすべて裸の`$json`ではなく`$('分岐処理・アクション決定').item.json...`とード名を明示して参照しているHC-SUBの`$('Execute Workflow Trigger').item.json`と同じ規約)
- 秘密情報・SiteId等はすべて`workflow_config_values``bNkadTyDgDepYx2p`から「設定値一括取得」1ードで取得し、直後のCodeードで`configKey`→`configValue`のMapに変換して参照。ワークフローJSONに秘密値のハードコードなし
- 未検証・要判断の暫定実装・既知の未実装あり(詳細は`task-11-rebuild-report.md`:
①Data Table `update`操作のパラメータ形状get/insertは実機確認済みだが、updateは本タスクで初採用のため未検証、ブリーフ記載のサンプル形状をそのまま採用
②`/api/users/get`・`api/items/{SiteId}/get`ColumnFilterHash検索のレスポンス形状はHC-SUB・旧WA版と同じ想定を踏襲
③484184(`LINEWORKS_BOT_MASTER_SITE_ID`)からのBotId解決ロジックはHC-SUBと同じ暫定実装`SiteSettings.BotIds`または`Processes[].BotId`を仮定)
④**LINEWORKSファイル添付`awaitInput:"file"`分岐)の実処理は未実装。** ファイルダウンロード(`GET /v1.0/bots/{botId}/attachments/{fileId}`にはLINEWORKS Bot APIのアクセストークンが必要だが、JWT署名は専用のJWTードード11、action=="send"経路にのみ存在しード5より後段でしか行えないため、ード5内ではトークンを取得する手段がない。現状はこのケースを検出すると`action:"send"`でユーザーに「準備中」メッセージを返し、待機状態は`file`のまま維持するユーザーが詰まらないための安全側実装。実装するにはグラフ構成の見直しファイル受信専用のJWT/Tokenペアを追加する等が必要で、フォローアップタスクで対応すること
- 設計上の注記: HC-SUBTask 9が`healthcheck_bot_state`に保存する`pendingProcesses`は`{processId, label, tooltip}`のみで`ValidateInputs`を持たないため、none分岐での`classifyAwaitInput`実行時はHC-WA内で`サイト設定取得`(getsite)を再実行し、ProcessId一致でフルのProcess定義を引き直す設計にしたTask 9側のファイルは変更していない