# MySQL TaskTraceStore 查詢邊界設計

## 1. 文件目的

本文件承接 [MySQL DB LogWriter / TraceStore 邊界設計](mysql-db-logwriter-tracestore-boundary-design.md)、[MySQL DB LogWriter / TraceStore 第一版實作紀錄](mysql-db-logwriter-tracestore-implementation-record.md) 與 [MySQL DB LogWriter 真實 DB 驗證前確認清單](mysql-db-logwriter-tracestore-real-db-precheck.md)，整理 `TaskTraceStore` 的查詢邊界。

本文件只做設計分析與後續實作前依據，不新增 `TaskTraceStore` public interface、不修改 `ITaskStore`、不修改 `ILogWriter`、不連真實 DB、不執行 DDL，也不導入 WebApi / ServiceHost。

## 2. 目前狀態

| 項目 | 狀態 | 說明 |
| --- | --- | --- |
| `task_log_traces` schema class | 已完成 | 已可由 C# class 維護欄位、索引與描述。 |
| `MySqlLogWriter` | 已完成第一版 | 可將 `LogEntry` 映射為 trace row，並具備 fake gateway 測試與 fallback。 |
| Payload sanitizer | 已完成第一版 | 可遮罩 password、token、secret、authorization 與 connection string 類資訊。 |
| manual-only xUnit 入口 | 已完成 | `HS_MYSQL_LOGWRITER_*` gate 預設關閉，不連 DB、不寫入。 |
| 真實 DB 驗證前確認清單 | 已完成 | 已固定 `task_log_traces` 寫入 / 查詢 / cleanup 前置條件。 |
| 真實 DB 寫入 / 查詢 / cleanup 驗證 | 尚未完成 | 需使用者確認測試 DB 與 gate 後才能執行。 |
| `TaskTraceStore` 查詢介面 | 尚未實作 | 本文件先定義查詢邊界，不新增 public contract。 |

## 3. 為什麼需要獨立 TaskTraceStore

`task_log_traces` 是診斷 trace table，資料量與查詢目的不同於 `task_executions`、`node_executions`。

| 資料來源 | 定位 | 不適合承擔的事 |
| --- | --- | --- |
| `ITaskStore` | 任務主檔與節點摘要 | 不應保存大量 Raw / Metadata 診斷資料。 |
| `ILogWriter` | 寫入 log / trace | 不應承擔查詢 API 或任務狀態回復。 |
| `TaskTraceStore` | trace read-side 查詢 | 不應改變 Workflow 狀態、不應寫入任務主檔。 |

因此建議後續採用獨立 read-side 邊界：

```text
LogEntry -> MySqlLogWriter -> task_log_traces
                                      ↓
                              TaskTraceStore
                                      ↓
              Query by TaskId / NodeId / DeviceId / ErrorCode / TimeRange
```

## 4. 第一版查詢目標

第一版只建議支援診斷查詢，不支援報表、統計、即時監控或跨案場查詢。

| 查詢目標 | 必要性 | 說明 |
| --- | --- | --- |
| 依 `TaskId` 查完整 trace | 必要 | 驗證單一任務發生了哪些節點、設備命令與錯誤。 |
| 依 `NodeId` 查 trace | 建議 | 協助定位特定 Workflow 節點問題。 |
| 依 `DeviceId` 查 trace | 建議 | 協助定位特定設備或 Adapter 問題。 |
| 依 `CommandName` 查 trace | 建議 | 協助定位特定命令問題。 |
| 依 `ErrorCode` 查 trace | 建議 | 協助統一錯誤碼排查。 |
| 依 `CreatedAt` 時間區間查詢 | 必要 | 避免一次查出過多 trace。 |
| 分頁 / 上限 | 必要 | 避免大量資料造成 API 或工具卡住。 |

## 5. 建議查詢條件

後續若進入實作，查詢 request 建議具備以下欄位，但是否建立 public DTO 需另行確認：

| 欄位 | 型別草案 | 規則 |
| --- | --- | --- |
| `TaskId` | `string` | 可選；若有值，查指定任務。 |
| `NodeId` | `string` | 可選；查指定節點。 |
| `DeviceId` | `string` | 可選；查指定設備。 |
| `CommandName` | `string` | 可選；查指定命令。 |
| `Level` | `string` | 可選；例如 `Info`、`Warning`、`Error`。 |
| `ErrorCode` | `string` | 可選；查特定錯誤。 |
| `CreatedFrom` | `DateTime?` | 可選；若未提供，需搭配安全預設區間。 |
| `CreatedTo` | `DateTime?` | 可選；不得早於 `CreatedFrom`。 |
| `Limit` | `int` | 必填或預設；建議預設 100，最大 500。 |
| `Offset` | `int` | 可選；第一版可先用 offset paging。 |
| `SortDescending` | `bool` | 預設 `true`，先看最新 trace。 |

## 6. 回傳資料邊界

查詢回傳應是已摘要化與已遮罩的 trace row，不還原原始 object，也不回傳密碼、token 或完整 connection string。

| 欄位 | 是否建議回傳 | 說明 |
| --- | --- | --- |
| `TraceId` | 是 | trace row 識別碼。 |
| `TaskId` | 是 | 任務識別碼。 |
| `NodeId` / `NodeName` | 是 | 節點資訊。 |
| `DeviceId` / `CommandName` | 是 | 設備命令資訊。 |
| `Level` / `Status` | 是 | 診斷與狀態判讀。 |
| `RetryCount` | 是 | 可判斷重試行為。 |
| `TimeTakenMs` / `AdapterTimeTakenMs` | 是 | 可判斷耗時。 |
| `ErrorCode` | 是 | 可快速篩選錯誤。 |
| `Message` | 是 | 可讀摘要。 |
| `DataSummary` | 是 | 已摘要化資料。 |
| `RawRequestSummary` | 是 | 必須已遮罩與截斷。 |
| `RawResponseSummary` | 是 | 必須已遮罩與截斷。 |
| `MetadataSummary` | 是 | 必須已遮罩與截斷。 |
| 原始未處理 Raw object | 否 | 不應由 TraceStore 還原或輸出。 |

## 7. SQL 查詢邊界

第一版查詢需遵守：

- Table name 必須通過既有 identifier 檢查，不直接串接未驗證字串。
- Where 條件必須使用參數化查詢。
- `Limit` 必須有最大值，不允許無上限查詢。
- 預設排序使用 `created_at DESC`。
- 不在 query store 內做資料遮罩，遮罩責任仍屬寫入前的 `LogEntry` mapper / sanitizer；查詢端只驗證不可輸出敏感原文。
- 不提供任意 SQL 查詢入口。

## 8. 不納入第一版的項目

| 項目 | 原因 |
| --- | --- |
| WebApi trace endpoint | 屬第三階段正式平台邊界。 |
| ServiceHost trace 查詢 | 屬第三階段正式背景服務。 |
| WinForms Debug Tool | 屬現場工具，不屬第二階段 B 必要收斂。 |
| 跨 database / 多案場查詢 | 會擴大平台邊界。 |
| 報表統計 | 需要另一套聚合需求，不應塞進 trace store 第一版。 |
| retention / purge job | 屬維運策略，需另行設計。 |
| public query interface | 會新增 public contract，需使用者確認後才可實作。 |

## 9. 後續實作前確認項目

若要從設計進入實作，需先確認：

1. 是否允許新增 `TaskTraceStore` public interface。
2. 查詢介面要放在 `Infrastructure.MySql` 內部，還是先以 internal helper 驗證。
3. 是否要建立獨立 query request / result model。
4. 是否要支援 `TaskId` 必填，還是允許時間區間查詢。
5. 最大 `Limit` 要採 100、500 或其他值。
6. 是否需要回傳總筆數。
7. 查詢結果是否要保留 Raw summary，或只回傳 message / error / metadata summary。
8. 是否需要與未來 WebApi 的 contract 對齊。

## 10. 建議測試策略

| 測試 | 目的 |
| --- | --- |
| Query builder 測試 | 確認不同 filter 會產生參數化 SQL。 |
| Limit 上限測試 | 確認過大 limit 會被拒絕或縮到最大值。 |
| Identifier 安全測試 | 確認 table name 不允許 SQL injection。 |
| Row mapper 測試 | 確認 trace row 能轉成查詢結果。 |
| Sanitized output 測試 | 確認查詢結果不含敏感原文。 |
| Fake gateway 查詢測試 | 不連 DB 驗證 command 與參數。 |
| manual-only 真實 DB 查詢 | 使用者確認後，搭配 `task_log_traces` 真實 DB 驗證紀錄執行。 |

## 11. 建議結論

`TaskTraceStore` 應作為 `task_log_traces` 的 read-side 邊界，不應與 `ITaskStore` 或 `ILogWriter` 混在一起。

目前第二階段 B 已具備 DB LogWriter 第一版與 manual-only xUnit 入口；下一步在未確認 public contract 前，建議先維持本文件作為設計邊界。若使用者同意新增查詢 contract，再進入 `TaskTraceStore` 實作前確認清單。
