# 安全 Flow JSON 範例庫

這個目錄提供可匯入 Node-RED 5.0.2 的最小 Flow 陣列；Home Assistant 節點依 `node-red-contrib-home-assistant-websocket` 0.80.3 的目前持久化欄位建立。範例只供離線閱讀、匯入與逐節點審查，不代表可直接使用的環境設定。

## 安全模型

- 每個 JSON 根節點都是陣列，含一個分頁與完整的同檔案接線目標。
- 所有 Inject 都只能手動按下，`once` 固定為 `false`；沒有啟動時自動送出訊息的節點。
- Home Assistant、HTTP、MQTT、Catch、Status 與 Complete 等外部或運作型節點皆以 `d: true` 明確停用，即使用途只有查詢或監聽也相同。
- 純核心範例可保持啟用，但入口仍是手動 Inject；函式範例只做訊息內的確定性運算。
- 範例不含 credentials 區塊、權杖、密碼、真實主機、網址、IP、實體識別碼、主題或環境值。
- 佔位符不會被自動解析；替換前必須確認用途、最小權限、資料方向與可能的副作用。

> **非部署警告：請勿匯入後直接部署，也不要為了試跑而一次啟用所有停用節點。** 匯入不等於核准。任何啟用、部署或連線都必須在副本中逐節點審查，並依組織的變更程序另外核准。

## 範例索引

| 檔案 | 節點數 | 內容 | 預設安全狀態 |
|---|---:|---|---|
| `01-first-flow.json` | 4 | 手動 Inject → Change → Debug | 僅手動入口 |
| `02-switch-routing.json` | 5 | Switch 雙路條件分流 | 僅手動入口 |
| `03-context-counter.json` | 4 | Change 更新 flow context 計數 | 僅手動入口 |
| `04-events-state.json` | 3 | Events: state，schema version 6 | 監聽節點停用 |
| `05-current-state.json` | 4 | Current State，schema version 3 | 查詢節點停用 |
| `06-get-entities.json` | 4 | Get Entities，schema version 1 | 查詢節點停用 |
| `07-action.json` | 5 | 手動 Inject 只到準備 Debug；Action v7 無上游且保持停用 | 動作節點停用且入口斷開 |
| `08-wait-until.json` | 4 | Wait Until v3；10 秒 timeout，成功接有限 Debug、逾時留空 | 等待節點停用 |
| `09-jsonata-transform.json` | 4 | JSONata 資料轉換 | 僅手動入口 |
| `10-pure-function.json` | 4 | 純 JavaScript 訊息運算 | 僅手動入口 |
| `11-debug-catch-status.json` | 12 | 三個手動模式觸發正常 payload、測試 error、有界 status；Complete 監看示範 Function，四條獨立 Debug 投影 | Catch、Status 與 Complete 停用 |
| `12-http-endpoint.json` | 4 | HTTP In → Change → HTTP Response | 端點與回應皆停用 |
| `13-outbound-http-request.json` | 4 | 手動 Inject → HTTP Request → Debug | 對外請求停用 |
| `14-mqtt-in-out.json` | 6 | MQTT In、Out 與 broker config node | 兩個可執行節點停用 |

### `11-debug-catch-status.json` 固定輸出

此範例的三個 Inject 都是手動入口；一次只可在隔離副本啟用一個對應的運作型觀察器，測完恢復 `d: true`。

- 正常：按「手動測試正常輸出」，payload Debug 顯示 `{"caseName":"normal","doubled":8}`，不產生 Catch。
- Catch：只啟用 Catch 後按「手動測試 Catch」，error Debug 的 `msg.error.message` 是 `TEST_ERROR`，`source` 指向 ID `b000000000000005`、type `function`、name「產生有限診斷事件」；正常 payload Debug 沒有訊息。
- Status：只啟用 Status 後按「手動測試 Status」，status Debug 顯示 fill `blue`、shape `dot`、text `TEST_STATUS`，`source` 指向同一 Function；正常 payload Debug 沒有訊息。
- Complete：只啟用 Complete 後按「手動測試正常輸出」，complete Debug 顯示 `{"source":{"id":"b000000000000005","type":"function","name":"產生有限診斷事件"}}`；這是 `msg.complete` 投影。正常 payload Debug 仍獨立顯示正常結果。

## 匯入與審查程序

1. 先在版本控制中閱讀 JSON 與本文件，不要在正式 Node-RED 執行個體操作。
2. 在隔離的編輯器副本選擇 **Import → Clipboard**，一次只匯入一個完整 JSON 陣列，並選擇匯入到新 Flow。
3. 確認只新增一個分頁，所有接線都停留在該分頁，而且沒有 Inject 設為啟動時執行。
4. 逐一打開紅色停用節點，檢查節點版本、輸入覆寫、目標、資料、逾時、URL、主題與輸出位置；完成審查前保持停用。
5. Home Assistant 範例的 `server` 是刻意無法解析的整值佔位符。請在每個 HA 節點的 **Server** 下拉選單選取由管理者事先建立並核准的設定節點；不要把匯出檔中的參照字串當成設定節點 ID，也不要在 JSON 內貼入真實 ID。
6. MQTT 範例已附不含帳密的 broker config node。請開啟該設定節點逐欄替換主機與 client ID，另在 MQTT In／Out 節點替換各自主題；需要認證時應透過受控的 Node-RED credentials 儲存，而不是寫回範例檔。
7. HTTP 路徑只能換成經核准且不衝突的相對路徑；對外 HTTP URL 必須是經核准的 HTTPS 端點，並另外檢查重新導向與回傳資料。
8. 重新執行 repository 驗證，再由另一位審查者確認差異。此程序結束仍不授權部署；部署必須另走正式變更程序。

### Get Entities 輸入覆寫注意事項

Get Entities 0.80.3 的目前節點沒有 **Block Input Overrides** 選項。它會讀取 `msg.payload.*` 覆寫，包括 `rules`、`outputType`、`outputEmptyResults`、`outputLocationType`、`outputLocation` 與 `outputResultsCount`。因此，上游訊息即使來自看似安全的節點，也可能改變查詢規則或輸出位置；啟用前必須驗證或移除不受信任的 `msg.payload` 欄位。本範例將 Get Entities 保持停用，不能把 JSON 內的規則視為不可覆寫的安全邊界。

## 佔位符

每個精確 token 只在本節登錄一次；相同 token 可由多個 JSON 範例重複使用。

- `PLACEHOLDER_HA_SERVER_CONFIG`：匯入後在節點編輯器選取的既有 Home Assistant Server config；不要直接改成或提交真實 config node ID。
- `PLACEHOLDER_ENTITY_ID`：由審查者選取的 Home Assistant 實體識別碼。
- `PLACEHOLDER_HA_ACTION`：經核准的 Home Assistant action 名稱。
- `PLACEHOLDER_ENTITY_STATE`：Wait Until 要比較的預期實體狀態。
- `PLACEHOLDER_HTTP_PATH`：經核准且不衝突的 HTTP In 相對路徑片段。
- `PLACEHOLDER_HTTPS_URL`：經核准的完整 HTTPS 對外端點，不得改用明文 HTTP。
- `PLACEHOLDER_MQTT_BROKER_HOST`：經核准的 MQTT broker 主機名稱；不得放入帳密或連線 URL。
- `PLACEHOLDER_MQTT_CLIENT_ID`：此範例連線專用且經核准的 MQTT client ID。
- `PLACEHOLDER_MQTT_INPUT_TOPIC`：MQTT In 訂閱主題。
- `PLACEHOLDER_MQTT_OUTPUT_TOPIC`：MQTT Out 發佈主題。
