# 4B WebApi contract 草案 / 實作前確認表

本文件承接 [第四階段標準 / 文件 / 施作範圍 / 驗收條件總表](phase-four-standards-scope-acceptance.md)、[第四階段 4B / 4C / 4D 執行切分表](phase-four-execution-split-plan.md) 與使用者於 2026-06-06 的確認結果，整理 4B WebApi 進入第一版程式實作前的 route、DTO、錯誤格式、Application mapping、API 測試、DB 測試與停止線。

本文件已取得本輪 4B 目標模式確認，確認紀錄見 [4B WebApi 決策確認紀錄](phase-four-b-webapi-decision-confirmation.md)。本次確認只授權最小 WebApi 第一版與 API / 非破壞性 DB 驗收基準，不代表同意建立 `ServiceHost`、Plugin Loader、外部 DLL 載入、正式 DB DDL、正式 Apply、認證授權套件、部署設定或真實硬體控制。

## 0. 確認狀態

| 項目 | 內容 |
|---|---|
| 文件狀態 | 已確認 |
| 整理日期 | 2026-06-06 |
| 確認日期 | 2026-06-06 |
| 對應階段 | 第四階段 4B WebApi |
| 程式 repo | `hs-device-control-template` |
| 程式 branch | `poc/nmodbus-tcp` |
| 程式基準 commit | `a158551 新增 3D Application contract 第一版` |
| 本次目標 | 建立最小 WebApi 第一版與 API / DB 非破壞性驗收基準 |
| 使用者確認 | `確認項目依照您的建議` |
| 本次可做 | 新增 `HS.DeviceControl.WebApi`、新增 WebApi 測試、建立最小 route / DTO / error response、執行 API 測試與非破壞性 DB 測試 |
| 本次不做 | 不建立 ServiceHost、不建立 Plugin Loader、不加 auth / Swagger / 部署設定、不做 DB DDL / ALTER / Apply、不保存敏感連線資訊 |

## 1. 第一版定位

4B WebApi 第一版的定位是「HTTP 邊界與 Application contract mapping」，不是新的流程引擎，也不是背景服務。

| 原則 | 說明 |
|---|---|
| WebApi 只做入口 | Controller / endpoint 只負責 request / response、DTO mapping、錯誤格式與狀態碼。 |
| 流程仍在 Application / Core | WebApi 不寫 Workflow node 邏輯，不直接修改 TaskStateMachine。 |
| 設備仍走 Adapter 邊界 | WebApi 不直接操作 PLC、COM、TCP、UDP、Modbus 或真實硬體。 |
| DB 不直接裸露 | WebApi 不直接拼 SQL，不保存 connection string，不執行 DDL。 |
| Preview 不等於 Apply | Schema preview 只回傳 `ManualApplyPreview` 結果，不提供 Apply endpoint。 |
| 第一版非正式外網服務 | 未導入 auth、rate limit、正式部署與敏感資訊管理前，不可視為正式對外 API。 |

## 2. 建議專案與引用方向

| 項目 | 建議 |
|---|---|
| 新增專案 | `src/HS.DeviceControl.WebApi/HS.DeviceControl.WebApi.csproj` |
| 新增測試專案 | `tests/HS.DeviceControl.WebApi.Tests/HS.DeviceControl.WebApi.Tests.csproj` |
| Target framework | `net5.0`，與現有 solution 一致 |
| WebApi 引用 | `HS.DeviceControl.Application` |
| WebApi 不引用 | `HS.DeviceControl.ConsoleHost`、`HS.DeviceControl.Infrastructure.MySql`、未來 `ServiceHost`、Plugin Loader |
| 測試引用 | `HS.DeviceControl.WebApi` 與必要的 fake Application service |

引用方向：

```text
HS.DeviceControl.WebApi -> HS.DeviceControl.Application -> Core / Adapters
HS.DeviceControl.Infrastructure.MySql -> Core
HS.DeviceControl.ServiceHost -> HS.DeviceControl.Application
```

## 3. 第一版 route 候選

| 類型 | Method | Route | 目的 | 第一版邊界 |
|---|---|---|---|---|
| Health | `GET` | `/health` | 回傳 WebApi 與 Application health 摘要。 | 不暴露 secret、connection string 或完整 stack trace。 |
| Task | `POST` | `/api/tasks` | 建立任務請求並回傳 `TaskId` 或錯誤。 | 不同步等待 workflow 完成，不新增 queue。 |
| Task | `GET` | `/api/tasks/{taskId}` | 查詢任務狀態與節點摘要。 | 只讀 Application status，不直接查 DB gateway。 |
| Task | `POST` | `/api/tasks/{taskId}/cancel` | 提出取消請求。 | 遵守終態不可回到 running；第一版可回傳 accepted / rejected。 |
| Device | `GET` | `/api/devices/status` | 查詢單一或多個設備狀態。 | read-only，不呼叫 `Execute()`。 |
| Schema | `POST` | `/api/schema/preview` | 產生 schema preview、風險與 `PlanHash`。 | 不提供 Apply，不執行 DDL。 |

## 4. DTO 草案

| DTO | 欄位草案 | 對應 Application contract |
|---|---|---|
| `TaskStartApiRequest` | `workflowId`、`requestId`、`operator`、`source` | `TaskStartRequest` |
| `TaskStartApiResponse` | `success`、`taskId`、`status`、`code`、`message`、`error` | `TaskStartResult` |
| `TaskStatusApiResponse` | `success`、`taskId`、`workflowId`、`status`、`startedAtUtc`、`endedAtUtc`、`timeTakenMs`、`nodes`、`error` | `TaskStatusResult` |
| `TaskCancelApiRequest` | `reason`、`operator` | `TaskCancelRequest` |
| `TaskCancelApiResponse` | `success`、`taskId`、`accepted`、`status`、`code`、`message`、`error` | `TaskCancelResult` |
| `DeviceStatusApiResponse` | `success`、`items`、`error` | `DeviceStatusResult` |
| `SchemaPreviewApiRequest` | `targetSchemaName`、`correlationId`、`source`、`operator` | `SchemaPreviewRequest` |
| `SchemaPreviewApiResponse` | `success`、`planHash`、`canApply`、`ddlExecutionAllowed`、`items`、`warnings`、`error` | `SchemaPreviewResult` |
| `HealthApiResponse` | `success`、`status`、`checkedAtUtc`、`dependencies`、`error` | `HealthStatusResult` |

## 5. 錯誤格式

第一版錯誤格式需維持可追蹤，但不得外洩敏感資訊。

| 欄位 | 說明 |
|---|---|
| `success` | 固定為 `false`。 |
| `code` | 對應 Application / Core error code，例如 `APP-03xx` 或既有 `ErrorCode`。 |
| `message` | 可讀錯誤摘要，不包含密碼、connection string、完整 SQL。 |
| `traceId` | WebApi request trace id 或 correlation id。 |
| `details` | 第一版只放安全摘要，不放完整 exception stack trace。 |

建議 HTTP status：

| 情境 | Status |
|---|---|
| request 格式錯誤 | `400 Bad Request` |
| 找不到 task / device | `404 Not Found` |
| 狀態不允許或取消被拒 | `409 Conflict` |
| Application service 回傳標準失敗 | `400` 或 `409`，依錯誤語意決定 |
| 未預期例外 | `500 Internal Server Error`，但 response 不暴露敏感細節 |

## 6. 測試策略

| 測試 | 目的 | 是否本輪執行 |
|---|---|---|
| WebApi project compile | 確認專案與引用方向正確。 | 是 |
| Route / DTO mapping tests | 確認 request / response mapping 與錯誤格式。 | 是 |
| Health API test | 確認 `/health` 可回傳安全摘要。 | 是 |
| Task API tests | 確認建立、查詢、取消 request 可轉交 Application fake service。 | 是 |
| Device Status API tests | 確認 read-only，不下控制命令。 | 是 |
| Schema Preview API tests | 確認 preview response 固定不開放 Apply / DDL。 | 是 |
| 本機 HTTP 驗收 | 若可啟動 WebApi，使用本機 URL 驗證 route。 | 是，若啟動條件具備 |
| DB 非破壞性測試 | 執行現有 MySQL 測試中不需真實 DB 或 manual gate disabled 的測試。 | 是 |
| 真實 DB manual-only 測試 | 需要測試 DB、環境變數、AllowRead / AllowWrite 與 cleanup 確認。 | 否，另行確認 |

## 7. DB 驗收邊界

本輪 DB 測試只建立「WebApi 不破壞 DB 邊界」的基準。

| 分類 | 可執行 | 不可執行 |
|---|---|---|
| 自動測試 | solution tests、Application tests、Infrastructure.MySql fake/gateway/mock 類測試、manual gate disabled 測試。 | 不要求真實 MySQL 連線。 |
| Schema preview | 可測 `CanApply=False`、`DdlExecutionAllowed=False`、risk / PlanHash。 | 不執行 DDL。 |
| 真實 DB | 只在另行確認測試 DB 與 gate 後執行。 | 不碰正式 DB，不保存 connection string。 |
| Cleanup | 只允許既有 manual 測試中有 prefix guard 的 cleanup。 | 不刪除不符合 prefix 的資料。 |

## 8. 七項確認表

使用者已確認採用以下建議，可進入 4B 最小 WebApi 第一版實作：

| 編號 | 決策項 | 確認結果 | 實作影響 |
|---:|---|---|---|
| 1 | 先固定文件 repo 第四階段標準包 | 同意，已 commit / push 文件 repo。 | 4B 有文件基準可追溯。 |
| 2 | 允許新增 WebApi 專案與測試專案 | 同意。 | 可新增 `HS.DeviceControl.WebApi` 與 `HS.DeviceControl.WebApi.Tests`。 |
| 3 | 最小 WebApi，不先加 auth / middleware / Swagger / 部署設定 | 同意。 | 降低套件、部署與安全設定風險。 |
| 4 | API 測試以本機自動測試與本機啟動驗收為準 | 同意。 | 需要 route / DTO / error / health 測試。 |
| 5 | DB 測試先跑非破壞性與 manual gate disabled | 同意。 | 真實 DB 測試另行確認。 |
| 6 | 明確禁止 DB DDL、ALTER TABLE、正式 Apply | 同意。 | 本輪不改 schema、不執行 Apply。 |
| 7 | 4C / 4D 只保留 contract，不在本輪一起實作 | 同意。 | ServiceHost 與 Plugin Loader 留到後續節點。 |

使用者確認文字：

```text
確認項目依照您的建議
```

## 9. 第一版候選檔案

以下為進入程式 repo 前的候選範圍，實際修改前仍需先盤點程式 repo 結構與現有 Application service。

| 類型 | 候選檔案 |
|---|---|
| WebApi 專案 | `src/HS.DeviceControl.WebApi/HS.DeviceControl.WebApi.csproj` |
| WebApi 啟動 | `src/HS.DeviceControl.WebApi/Program.cs`、`src/HS.DeviceControl.WebApi/Startup.cs` |
| API DTO | `src/HS.DeviceControl.WebApi/Models/*` |
| Controller / endpoint | `src/HS.DeviceControl.WebApi/Controllers/*` |
| API 測試 | `tests/HS.DeviceControl.WebApi.Tests/*` |
| Solution | `HS.DeviceControl.sln` |
| 文件 | 本文件、實作紀錄、完成稽核、commit / push 前確認、線上或本機驗收紀錄 |

## 10. 仍需停止的項目

即使本文件已確認，仍不得自動執行以下項目：

- 不新增 `HS.DeviceControl.ServiceHost`。
- 不建立 Plugin Loader。
- 不掃描 plugin folder。
- 不載入外部 DLL。
- 不新增認證授權套件、Swagger、正式部署設定或正式外網公開設定。
- 不修改 Core / Adapters / Infrastructure / Application public method 簽章。
- 不修改 `devices.json` / `workflows.json` / `appsettings.json` schema。
- 不執行 DB DDL、ALTER TABLE、正式 Apply 或正式 DB 寫入。
- 不保存密碼、Token、IP、Port、完整 connection string 或正式環境資訊。
- 不接真實硬體或案場客製邏輯。

## 11. 建議下一步

本文件確認後，建議先唯讀盤點程式 repo 的 `Application` contract、現有測試專案與 `.sln` 結構，再回報預計新增 / 修改的程式檔案。確認後可進入最小 WebApi 第一版實作與 API / DB 非破壞性測試。
