5A 最小 PluginLoader 實作測試案例與停止線稽核表
本文件承接 5A 最小 PluginLoader 實作前最後確認表 與 5A 最小 PluginLoader 最後確認表線上驗收紀錄,用於在等待使用者七項最後確認期間,先固定程式實作後的測試案例、停止線掃描與驗收基準。
本文件不修改程式 repo,也不代表使用者已同意 5A 最後確認七項。只要七項尚未確認,就不得新增 IPluginLoader、Loader DTO、Loader service 或 ApplicationErrorCodes public constant。
0. 文件狀態
| 項目 | 內容 |
| 文件狀態 | 已完成 |
| 建立日期 | 2026-06-07 |
| 對應節點 | 5A 程式實作測試矩陣與停止線稽核 |
| 程式 repo | hs-device-control-template |
| 程式 branch | poc/nmodbus-tcp |
| 程式 commit | 6f34bb9,4D 最小 Application plugin contract |
| 遠端基準 | main=a8b522b,poc/nmodbus-tcp=6f34bb9 |
| 工作樹 | 乾淨 |
| 是否修改程式 repo | 否,只做唯讀 refresh 與文件化 |
1. 唯讀 refresh 結論
| 檢查項目 | 結論 |
| 5A 候選類別 | IPluginLoader、PluginLoadRequest、PluginLoadResult、PluginLoaderOptions、PluginLoaderService、PluginLoaderServiceTests 仍未存在。 |
| Loader 錯誤碼 | APP-0341 到 APP-0345 仍未建立;目前 ApplicationErrorCodes 只到 APP-0335 plugin source invalid。 |
| 狀態語意 | PluginLoadState.Loaded 已存在但註解明確保留給未來 Loader lifecycle;5A 第一版不應產生真正 Loaded。 |
| production assembly loading | 未發現 Assembly.Load、LoadFrom、LoadFile、AssemblyLoadContext。 |
.dll 字串 | 只在既有 Application 測試用 C:\plugins\mock-light.dll 驗證 unsafe source,production code 未命中。 |
| Application.Tests | dotnet test tests\HS.DeviceControl.Application.Tests\HS.DeviceControl.Application.Tests.csproj --no-restore 通過 40 tests。 |
2. 實作後必跑測試
| 測試層級 | 指令 | 預期 |
| Application.Tests | dotnet test tests\HS.DeviceControl.Application.Tests\HS.DeviceControl.Application.Tests.csproj --no-restore | 需通過,且新增 PluginLoaderServiceTests。 |
| Solution tests | dotnet test HS.DeviceControl.sln --no-restore | 需通過,確認 5A 不破壞既有 tests。 |
| 停止線掃描 | rg -n "Assembly\.Load|LoadFrom|LoadFile|AssemblyLoadContext" src tests samples scripts | 不得命中新增 production code 或新增測試中的 assembly loading 呼叫。 |
| DLL 字串掃描 | rg -n "\.dll|plugin folder" src tests samples scripts | production code 不得命中;既有測試 mock path 可保留但不可擴大成真實載入。 |
| config schema 掃描 | 檢查 samples/config/appsettings.json、AppSettingsConfig.cs、ConfigValidator.cs | 5A 不得新增 plugin path、plugin folder、trust policy 或 loader config schema。 |
3. PluginLoaderServiceTests 建議案例
| # | 測試案例 | 建議測試名稱 | 預期結果 |
| 1 | 有效 metadata-only plugin 可被選取並回 Verified。 | LoadPlugin_ShouldReturnVerifiedForValidMetadata | Success=true、PluginId 正確、State=Verified、不產生 Loaded。 |
| 2 | request 為 null 或缺少 PluginId。 | LoadPlugin_ShouldRejectInvalidRequest | Success=false、Code=PluginLoadRequestInvalid、不丟 exception。 |
| 3 | catalog 找不到指定 plugin id。 | LoadPlugin_ShouldReturnNotFoundWhenPluginIsMissing | Success=false、Code=PluginLoadPluginNotFound。 |
| 4 | plugin disabled 且 options 未允許 disabled。 | LoadPlugin_ShouldRejectDisabledPluginByDefault | Success=false、State=Disabled 或 rejected result,訊息需保留 disabled reason 的安全摘要。 |
| 5 | expected contract version 與 metadata 不相容。 | LoadPlugin_ShouldRejectContractMismatch | Success=false、Code=PluginLoadContractMismatch、State=Rejected。 |
| 6 | expected checksum 與 metadata checksum 不一致。 | LoadPlugin_ShouldRejectChecksumMismatch | Success=false、Code=PluginLoadChecksumMismatch、不讀實體 DLL。 |
| 7 | catalog 回傳 unsafe source 或敏感 metadata。 | LoadPlugin_ShouldRejectUnsafeCatalogResult | 回標準錯誤,不暴露正式 path、password、token。 |
| 8 | catalog service 回傳失敗。 | LoadPlugin_ShouldReturnFaultedWhenCatalogFails | Success=false、State=Faulted 或 rejected result,需保留標準錯誤 code。 |
| 9 | options 允許 disabled 只做 metadata review。 | LoadPlugin_ShouldReturnDisabledWhenOptionsAllowDisabledReview | 可回 State=Disabled,但仍不得視為可載入或 Loaded。 |
| 10 | Loader result 需包含 verification checks。 | LoadPlugin_ShouldIncludeVerificationChecks | checks / warnings 可追溯,且不包含敏感資訊。 |
4. 實作後停止線稽核表
| 停止線 | 稽核方式 | 必須結果 |
| 不載入外部 DLL | 搜尋 Assembly.Load、LoadFrom、LoadFile、AssemblyLoadContext | 5A 新增檔案不得命中。 |
| 不掃描 plugin folder | 搜尋 Directory.GetFiles、EnumerateFiles、plugin folder、*.dll | 5A 新增檔案不得建立 folder scan。 |
| 不改 config schema | 比對 sample config 與 config 類別 | 不新增 loader path、plugin path、trust policy schema。 |
| 不寫 DB audit | 搜尋 DB audit table、DDL、CREATE TABLE、ALTER TABLE | 5A 不得新增 DB DDL 或寫入入口。 |
| 不改 WebApi auth / Swagger | 比對 WebApi 專案與設定 | 5A 不得新增 auth、Swagger 或正式部署設定。 |
| 不建立 Windows Service | 比對 ServiceHost 與 project file | 5A 不得新增 service installer、Windows Service package。 |
| 不接真實硬體 | 搜尋 Adapter / hardware call | 5A 不得直接操作 PLC、COM、TCP、UDP、Modbus 或真實設備。 |
5. 實作完成後驗收紀錄需包含
| 證據 | 內容 |
| 新增 / 修改檔案清單 | 明列 IPluginLoader、request、result、options、service、tests、error codes。 |
| 測試結果 | Application.Tests 與 solution tests 的通過數。 |
| 停止線掃描 | assembly loading、DLL、plugin folder、config、DB、auth、Windows Service 的掃描結果。 |
| 行為摘要 | valid metadata、invalid request、not found、disabled、contract mismatch、checksum mismatch、unsafe source 的結果。 |
| 程式 repo 狀態 | stage / commit 前確認與工作樹狀態。 |
| 文件同步 | 文件 repo 更新實作紀錄、驗收紀錄、status / progress / public。 |
6. 下一步門檻
目前仍需等待使用者確認:
5A 最小 PluginLoader 實作前最後確認: 1. 同意 2. 同意 3. 同意 4. 同意 5. 同意 6. 同意 7. 同意
確認前不可修改程式 repo;確認後才能依本測試矩陣進入 5A metadata-only PluginLoader 程式實作。