# TaskTraceStore 第一版查詢實作紀錄

本文件承接 [TaskTraceStore 第一版 public contract 決策紀錄](task-trace-store-public-contract-decision-record.md)，記錄第三階段 3A Trace 查詢能力第一版程式實作結果。

本次只完成已確認的 public contract 與 fake gateway 查詢實作，不執行真實 DB 查詢、不執行 DDL、不新增 WebApi / ServiceHost、不導入外部 DLL 或 Plugin Loader。

## 實作摘要

| 項目 | 內容 |
|---|---|
| 實作日期 | 2026-06-03 |
| 程式 repo | `hs-device-control-template` |
| 分支 | `poc/nmodbus-tcp` |
| 程式 commit | [`f2958d3`](https://github.com/Hongsen-tw/hs-device-control-template/commit/f2958d3b501c5d31bd08a23d2591dfc1d37d83a8) |
| 目前狀態 | 3A Trace 查詢第一版 fake gateway 實作完成 |
| 驗證方式 | Core / MySQL / WorkflowSimulation / Adapters / ModbusPoC 非 Manual 全測試 |
| 測試結果 | `dotnet test HS.DeviceControl.sln --filter "FullyQualifiedName!~Manual"` 通過 406 個測試 |

## 已新增 public contract

| 類型 | 位置 | 說明 |
|---|---|---|
| `ITaskTraceStore` | `HS.DeviceControl.Core.Logging` | Trace read-side 查詢入口。 |
| `TaskTraceQueryRequest` | `HS.DeviceControl.Core.Logging` | Trace 查詢條件與分頁設定。 |
| `TaskTraceQueryResult` | `HS.DeviceControl.Core.Logging` | 查詢結果、`HasMore`、耗時與錯誤資訊。 |
| `TaskTraceItem` | `HS.DeviceControl.Core.Logging` | 對應 `task_log_traces` 的查詢回傳項目。 |
| `TraceQueryInvalidRequest` | `HS.DeviceControl.Core.Common.ErrorCodes` | 查詢條件不合法，例如沒有任何 filter。 |
| `TraceQueryDatabaseFailed` | `HS.DeviceControl.Core.Common.ErrorCodes` | 查詢來源或資料庫存取失敗。 |

## MySQL 第一版實作

| 元件 | 說明 |
|---|---|
| `MySqlTaskTraceStore` | 實作 `ITaskTraceStore.Query(...)`。 |
| `MySqlTaskTraceStoreOptions` | 定義 MySQL 連線與 `task_log_traces` table 設定。 |
| `MySqlTaskTraceStoreOptionsValidator` | 驗證 host、port、database、user、password、table name 與 timeout。 |
| `MySqlTaskTraceStoreSqlBuilder` | 產生參數化 SELECT SQL，依 filter 組合 WHERE。 |
| `IMySqlTaskTraceStoreGateway` | internal gateway，方便 fake gateway 單元測試。 |
| `MySqlTaskTraceStoreGateway` | 真實 MySQL 查詢 gateway；本次沒有執行真實 DB 測試。 |
| `MySqlTaskTraceDataRecordMapper` | 將 `IDataRecord` 轉為 internal row。 |
| `MySqlTaskTraceStoreErrorMapper` | 查詢失敗時遮蔽密碼後回傳錯誤訊息。 |

## 查詢規則

| 規則 | 第一版作法 |
|---|---|
| 查詢方法 | 同步 `Query(TaskTraceQueryRequest request)`，符合現有 MySQL infrastructure 慣例。 |
| 必要 filter | 至少需要一個 filter，避免無條件全表查詢。 |
| 支援 filter | `TaskId`、`NodeId`、`DeviceId`、`CommandName`、`Level`、`Status`、`ErrorCode`、`CreatedFrom`、`CreatedTo`。 |
| 分頁 | `Limit` 預設 100、上限 500；`Offset` 不可小於 0。 |
| 下一頁判斷 | 使用 `Limit + 1` 查詢並回傳 `HasMore`，不做 `COUNT(*)`。 |
| 排序 | 依 `created_at` 排序，預設新到舊，可設定由舊到新。 |
| SQL 安全 | 只使用參數化查詢；table name 只允許安全 identifier。 |
| 敏感資訊 | 查詢結果中的 message / raw summary / metadata 會再經 sanitizer 遮蔽 password、token、secret、authorization、connection string。 |

## 本次沒有納入

- 沒有執行真實 DB 查詢。
- 沒有執行 DDL、ALTER TABLE 或 cleanup。
- 沒有新增 WebApi endpoint。
- 沒有新增 ServiceHost。
- 沒有新增 WinForms Debug Tool。
- 沒有導入 Plugin Loader 或外部 DLL 載入機制。
- 沒有新增 `Result<T>` 泛型結果型別。
- 沒有修改 `ITaskStore` 或 `ILogWriter` public method 簽章。

## 驗證結果

| 驗證 | 結果 |
|---|---|
| `dotnet test tests\HS.DeviceControl.Core.Tests\HS.DeviceControl.Core.Tests.csproj` | 通過 180 個測試。 |
| `dotnet test tests\HS.DeviceControl.Infrastructure.MySql.Tests\HS.DeviceControl.Infrastructure.MySql.Tests.csproj --filter "FullyQualifiedName!~Manual"` | 通過 77 個測試。 |
| `dotnet test HS.DeviceControl.sln --filter "FullyQualifiedName!~Manual"` | 通過 406 個測試。 |
| GitHub Actions | 程式 repo `通知文件 repo 更新開發狀態` workflow 成功。 |

## 目前完成度判斷

3A Trace 查詢能力目前已完成第一版 public contract 與 fake gateway 查詢實作，可以支撐後續 Debug Tool、ServiceHost 或 WebApi 設計時引用同一個 read-side contract。

尚未代表可以由 API 查詢線上資料，也尚未代表已完成真實 DB 查詢驗證。真實 DB read-only 查詢入口已於 [TaskTraceStore manual-only 查詢驗證入口紀錄](task-trace-store-manual-query-verification-entry-record.md) 補上，但仍需使用者確認測試 DB 與 `AllowRead` 後才可執行。

## 建議下一步

建議下一步做「TaskTraceStore 真實 DB read-only 查詢驗證」，先確認測試 DB、查詢條件、ExpectedMinRows 與 `AllowRead`，再執行 gated manual-only 測試並回填實際驗證紀錄。
