# 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 5(processFlow.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で上書き済み(2026-09-05、コントローラー実施、HTTP 200)。** - 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`)。設定値取得もfilter付き単一キーGetから一括取得+Codeフィルタへ変更済み - ワークフロー `HC-WA: LINEWORKS応答受信`: `0i0Ze3Gq0Waof3Fa` - ファイル: `workflows/hc-wa-lineworks-response.json` - Webhook: `https://n8n32.next-hd.net/webhook/healthcheck-lineworks-response`(LINE WORKS本体からの直接コールバック、`x-works-signature`検証) - active化済み(2026-09-05、コントローラーが新規デプロイ・activate、HTTP 200) - **プロジェクト全体の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ノードからの削減という趣旨は達成している) - LINEWORKS Developer Console側のBot Callback URL設定・疎通テストは未実施。ユーザー確認後に実施する - ノード構成(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-SUB(Task 9)が`healthcheck_bot_state`に保存する`pendingProcesses`は`{processId, label, tooltip}`のみで`ValidateInputs`を持たないため、none分岐での`classifyAwaitInput`実行時はHC-WA内で`サイト設定取得`(getsite)を再実行し、ProcessId一致でフルのProcess定義を引き直す設計にした(Task 9側のファイルは変更していない) ## n8nフォルダ - フォルダ `健康診断ワークフロー`: `hOx8WKrdOucllbcU`(projectId `LOcxF69Gm4PvnkqA`配下に2026-09-05作成) - HC-SUB/HC-WP/HC-WAの3ワークフローをこのフォルダへ移動する予定だが、Public APIの`/workflows/{id}/transfer`は別プロジェクトへの移動専用(同一プロジェクト内移動は拒否される)で、実行するとactive状態が解除される副作用があるため、**ユーザーがn8n UI上で手動ドラッグして移動する**運用にした(コントローラーからは未実施) ## workflow_config_values 追加登録キー(2026-09-05、healthcheck-survey-bot用) 既存の`workflow_config_values`(`bNkadTyDgDepYx2p`、org-master-sync用と共用)に以下を追加登録済み: - `LW_BOT_CLIENT_ID` / `LW_BOT_CLIENT_SECRET` / `LW_BOT_SERVICE_ACCOUNT`(LINEWORKS通知送信ワークフローと同じBot認証情報) - `HEALTHCHECK_SITE_ID`(508971)/ `LINEWORKS_BOT_MASTER_SITE_ID`(484184)/ `HEALTHCHECK_DATA_TABLE_ID`(`jqMDa2YZTI4f0iQ7`) - `HEALTHCHECK_WP_API_KEY`(HC-WP Webhook認証用に新規生成) - `LINEWORKS_BOT_SECRET`(署名検証用。値は現状プレースホルダー`UNSET_PENDING_BOT_CALLBACK_CONFIRMATION`。LINEWORKS Developer ConsoleでBot Callback URL設定時に実際のBot Secretへ更新が必要)