# MVP 验收手册

## 1. 验收结论口径

本仓库中的实现分为三层证据：

1. **自动化通过**：可由仓库测试重复验证的领域、协议、持久化或 API 行为。
2. **本机冒烟通过**：可运行 JAR 在全新数据目录完成 Flyway 迁移、健康检查、鉴权和 HTTP/OPC 双端口启动。
3. **目标环境门禁**：依赖参考硬件、真实上游服务器、两种外部 OPC UA Client、72 小时时间窗口或发布扫描平台，不能由一次本机测试替代。

只有目标环境门禁也完成后，才能把 release candidate 标记为可发布 MVP。

## 2. 自动化基线

```powershell
.\mvnw.cmd test
Set-Location frontend
npm ci
npm run typecheck
npm test -- --run
npm run build
Set-Location ..
docker build --tag opc-hub:test .
```

2026-08-11 的本机证据：后端 9 个 Reactor 模块构建成功，43 项 JUnit 测试通过；前端类型检查通过，1 项 Vitest 通过，生产构建成功；可运行 JAR 打包成功。Docker CLI 未安装，因此镜像构建留给 CI 的 `image` Job 复核。

进程冒烟结果：

| 检查 | 结果 |
| --- | --- |
| 全新 `/data` 启动及 Flyway 迁移 | 通过 |
| `/actuator/health/readiness` | `UP` |
| 未认证访问 `/_admin/api/connections` | `401` |
| 管理员认证访问 Connection 列表 | `200`，返回空列表 |
| OPC UA TCP 端口 | 可连接 |
| 测试后进程停止 | 通过 |

## 3. UC-001 至 UC-011

每个场景都从全新 Connection 开始。保存草稿、点击“校验并发布”、启用，然后从 Run 历史打开节点轨迹和只读快照。涉及秘密时只使用凭据库引用，不在节点 JSON 中输入明文。

| 用例 | 配置与动作 | 通过标准 | 仓库证据 |
| --- | --- | --- | --- |
| UC-001 | 手工/定时触发 → `opcua-read` → convert/JSON → `rest-client` | REST 测试服务收到转换后的当前值；Run 每节点成功且含质量码/时间戳 | OPC Read 节点和 REST Client 集成测试；DAG 测试 |
| UC-002 | `rest.trigger` → `opcua-write` → `response` | `/api/...` 同步返回；目标节点值变化；逐节点 StatusCode 可见 | REST Dispatcher API 测试；OPC Write 节点测试 |
| UC-003 | `rest.trigger` → `opcua-read` → JSON/`response` | 响应为目标 JSON，含正确值；生成的 `/api/openapi.json` 包含路由 | REST Dispatcher/OpenAPI 集成测试；OPC Read 测试 |
| UC-004 | cron/interval → `opcua-history-read` → `rest-client` | UTC 边界、记录上限、节点身份和错误 StatusCode 正确；远端收到历史序列 | HistoryRead 节点测试；需用真实 Historian 现场复核 continuation point |
| UC-005 | `opcua.data-change` → 可选关联 `opcua-read` → `rest-client` | 值变化创建独立 Run；断线恢复后重新订阅且不需重新发布 | Milo Subscription/更新集成测试；需故障注入现场复核恢复事件 |
| UC-006 | 画布创建、实时校验、保存、发布、启停、手工运行、草稿试运行 | 错误图不能发布；草稿试运行不替换生产版本；停用后自动触发停止 | Validator/发布/API/草稿试运行测试；前端构建 |
| UC-007 | 制造节点失败并打开 Run | 失败节点、状态、耗时、错误摘要、输入输出可定位；秘密显示为 `***` | Run 快照和脱敏集成测试 |
| UC-008 | 在运行期间重启 OPC/REST 测试服务 | OPC Client 重建连接；REST 按策略重试；无需重新发布 | Client 缓存失效重连和 REST 重试实现；需网络故障注入现场复核 |
| UC-009 | 打开历史 Run 快照 | 显示当次 `publishedVersionId`、节点轨迹和脱敏输出；不产生新 Run | 发布版本绑定、gzip 快照还原测试 |
| UC-010 | `opcua-server-update` 更新发布变量；外部客户端订阅 | Browse/Read 成功，更新产生 DataChange；重启后 NodeId 稳定 | 内嵌 Server Browse/Read/Subscription 集成测试；需两种外部 Client 复核 |
| UC-011 | 外部客户端 Write 可写变量 | 校验并成功入队后返回 Good；只读/类型错误/队列满给出 Bad StatusCode；Run 带 Session/身份摘要 | 内嵌 Server Write/队列/身份集成测试；需两种外部 Client 复核 |

推荐外部客户端至少选 UaExpert 和另一套非 Milo 客户端。安全连接必须使用 `Basic256Sha256 / SignAndEncrypt`；None Endpoint 仅限显式启用的本机开发验证。

## 4. 安全验收

- 未认证访问所有 `/_admin/api/**` 必须返回 `401`，健康探针除外。
- 首次启动不提供 `OPCHUB_ADMIN_PASSWORD` 必须失败；数据库中不得出现明文密码。
- 创建 Basic、Bearer、API Key、OPC 密码和证书密码凭据，导出 Connection、查询 API、Run 和日志，确认均不出现明文。
- URL 使用 `file:`、非 HTTP(S)、环回/链路本地/云元数据地址或 DNS rebinding 目标时，REST/OpenAPI 导入必须拒绝，除非目标属于明确允许的部署策略。
- 非回环 HTTP 且未启用 TLS/风险确认时启动必须失败；非回环 OPC UA 默认关闭 Anonymous 和 None Endpoint。
- 导入未信任 OPC 证书时记录主题、指纹和有效期；只有显式加入 CLIENT/SERVER scope 信任库后才允许建立对应安全连接。
- 对管理 API 和业务 REST 发送超过配置上限的请求，确认返回有界错误而非占满内存。
- 对镜像执行组织标准的 SBOM、许可证及 CVE 扫描；高危/严重项必须修复或记录风险接受。

## 5. 故障、容量与稳定性门禁

在 4 vCPU、8 GiB、SSD、`/data` 至少 30 GiB 的参考环境执行：

- 50 个启用 Connection、1,000 个 OPC UA Client MonitoredItem、20 个并发 REST 请求。
- 平均 1 Run/s，短时峰值 20 Run/s；验证 QUEUE、SKIP_NEW、CANCEL_OLD 和 ALLOW_PARALLEL。
- 1,000 个公开 Server Variable、10 个外部 Session、5,000 个 Server MonitoredItem，并验证超限 StatusCode。
- 构造 35 天等效触发/Run/HistoryRead 数据，验证常用时间轴和单 Run 回放 P95 小于 2 秒、过期清理和小时聚合。
- 注入断网、DNS 失败、上游重启、慢响应、部分 OPC 节点失败、证书变化和 Edgeservice 进程重启；每次恢复都不得要求重新发布。
- 连续运行 72 小时，采集进程存活、堆/线程/文件句柄、SQLite 大小、Run 成功率、订阅最后事件时间和重连次数；不得崩溃、持续内存增长或订阅静默失效。

## 6. 备份恢复门禁

1. 创建包含已发布 Connection、凭据、证书、Run 和审计数据的源实例。
2. 通过 `POST /_admin/api/backups` 创建并下载归档。
3. 在干净实例按 [部署文档](DEPLOYMENT.md) 恢复数据库、主密钥和证书材料。
4. 验证管理员登录、Connection/发布版本、凭据解析、证书指纹、Server NodeId 和历史 Run。
5. 分别执行一个草稿试运行、一个正式 REST Trigger 和一个 OPC Server Write。

## 7. 发布签字清单

- [ ] 后端、前端和镜像 CI 全绿。
- [ ] UC-001 至 UC-011 在目标协议环境逐项留存 Run ID/截图/日志摘要。
- [ ] 两种外部 OPC UA Client 双向互操作通过。
- [ ] 故障注入、容量、35 天等效数据和 72 小时报告通过。
- [ ] 备份、恢复、升级和回滚演练通过。
- [ ] 依赖/镜像安全扫描无未处置高危或严重漏洞。
- [ ] 生产证书、密码、主密钥、网络 ACL、磁盘告警和备份保管责任人已落实。
