zcbot/docs/windows-node-mvp-intranet.md

265 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Windows Node MVP 实施方案(内网版)
> **当前有效的第一阶段开发依据。**本文件取代 `windows-node-mvp.md` 中的 MVP 通信与注册方案。
> 长期演进边界见 `windows-node-design.md`。
> 首批能力:`origin.plot@v1`。
## 1. 适用边界
本方案成立的前提:
- zcbot 与 Windows Node 位于同一受控内网、云 VPC 或专用 VPN
- 两端使用固定私网地址或内网 DNS
- zcbot 的 Node 接口只监听私网地址;
- 安全组仅允许指定 Node IP 访问指定 zcbot 端口;
- 通信不经过公网、访客网或不可信办公终端所在网络。
MVP 使用:
```text
注册、状态和文件HTTP
任务控制长连接WS
节点认证:每个 Node 独立的长期 Bearer Token
```
HTTP/WS 不加密传输Node Token、输入数据、截图和产物在链路上均为明文。如果上述网络边界发生变化必须先升级 HTTPS/WSS。
## 2. MVP 架构
```mermaid
flowchart LR
Z["内网 zcbot"] <-->|"HTTP + WS<br/>独立 Node Token"| N["Windows Node.exe<br/>登录会话自动启动"]
N --> P["Origin Python Worker"]
P --> O["Origin / OriginPro"]
P --> F["独立任务目录"]
N -->|"状态、截图、产物"| Z
```
第一版只有两个进程:
- `Zcbot.WindowsNode.exe`.NET 10负责注册、自动连接、任务状态、进程控制、截图和上传
- `OriginAdapter.Worker`:固定 Python 环境,使用 `originpro` 生成 OPJU、PNG、SVG 和 PDF。
Node 首期运行在持续登录的专用 Windows 用户会话,通过计划任务在登录后自动启动。暂不拆 Windows Service 与 DesktopRunner。
## 3. Node 注册
### 3.1 操作流程
1. 管理员在 zcbot 管理端创建一次性注册码,默认 10 分钟有效。
2. Windows Node 首次启动时输入 zcbot 内网地址、节点名称和注册码。
3. Node 调用内网注册接口。
4. zcbot 原子消费注册码并返回 `node_id + node_token`
5. Node 使用 Windows DPAPI 加密保存 Token。
6. 此后 Node 或 Windows 重启时自动建立 WS 连接,不再要求人工输入。
```mermaid
sequenceDiagram
participant A as 管理员
participant Z as zcbot
participant N as Windows Node
A->>Z: 创建一次性注册码
A->>N: 输入内网地址和注册码
N->>Z: HTTP POST /v1/compute/nodes/enroll
Z->>Z: 校验并原子消费注册码
Z-->>N: node_id + node_token + 配置
N->>N: DPAPI 加密保存 node_token
N->>Z: 携带 Bearer Token 建立 WS
Z-->>N: active
```
注册请求:
```http
POST http://zcbot.internal:8765/v1/compute/nodes/enroll
Content-Type: application/json
```
```json
{
"enrollment_code": "ZCN-7H4K-9P2M",
"node_name": "win-origin-01",
"install_id": "019...",
"node_version": "0.1.0",
"os_version": "Windows 11 Enterprise 24H2",
"capabilities": ["origin.plot@v1"]
}
```
注册响应:
```json
{
"node_id": "019...",
"node_token": "仅返回一次的高熵随机 Token",
"heartbeat_seconds": 15,
"max_concurrency": 1
}
```
### 3.2 注册与 Token 底线
- 注册码一次性、短期有效,云端只保存哈希;
- 注册码可以绑定预期节点名称和允许能力;
- 注册成功或达到失败尝试上限后立即失效;
- 每个 Node 使用不同 Token禁止共享全局永久 Token
- Token 至少包含 32 字节密码学安全随机数;
- zcbot 数据库只保存 Token 强哈希,明文仅在注册响应返回一次;
- Node 使用 Windows DPAPI `LocalMachine` 加密 Token并用文件 ACL 限制为 Node 运行账号可读;
- Token 只放 `Authorization` Header不进入 URL、查询参数或日志
- Node 不上传 Windows 密码、许可证密钥或完整硬件指纹;
- 管理员可以禁用 Node 或轮换 Token禁用后立即拒绝连接、任务和上传
- Windows 重装、本地身份丢失或克隆云盘后必须重新注册。
## 4. 自动连接与重连
### 4.1 WS 连接
```http
GET ws://zcbot.internal:8765/v1/compute/nodes/connect
Authorization: Bearer <node_token>
X-Node-Id: <node_id>
Upgrade: websocket
```
HTTP 注册、状态、文件上传下载和 WS 长连接使用相同的 Node Token不增加短期 connection token、HMAC、nonce、时间戳签名或证书体系。
连接后 Node 上报:
- Node、OS 和 Origin 版本;
- capability 和可用 slot
- 本机磁盘和桌面会话状态;
- 本地运行中或尚未确认终态的 job 摘要。
同一 `node_id` 只保留一个活动连接。新连接成功后关闭旧连接。MVP 单节点场景下,发现相同身份来自不同 `install_id` 时拒绝新连接并提示重新注册,避免云盘克隆产生双执行者。
### 4.2 重连策略
- 断线后按 1、2、5、10、30、60 秒并加随机抖动重连;
- 最大间隔 60 秒;
- 正在运行的 Origin 任务不因 WS 断开而终止;
- 重要终态与上传状态写入本地 SQLite重连后补报
- `401/403` 表示 Token 失效,停止高频重试并显示“需要重新注册”;
- 连接超时和 `5xx` 继续退避重试;
- Windows 网络恢复时立即触发连接尝试。
## 5. 内网安全配置
最低网络规则:
```text
zcbot Node API 绑定zcbot 私网 IP:8765示例
zcbot 入站安全组:只允许 Windows Node 私网 IP → TCP 8765
Windows Node 出站:只允许 zcbot 私网 IP → TCP 8765
Windows Node 入站:不开放 Node 业务端口
RDP不向公网开放使用 VPN、堡垒机或云安全登录
```
即使在内网,应用层仍拒绝:
- 任意 PowerShell、Python、LabTalk 和命令行;
- 任意 URL、绝对路径和 UNC 路径;
- 未声明 capability
- 越权 job 和伪造 artifact ID
- 超出大小、类型和配额限制的文件。
建议在日志中记录 Node、job、用户、动作和结果但不得记录注册码或 Token。
## 6. MVP 状态与数据
云端首期只增加:
```text
compute_nodes(
node_id pk, name, install_id, token_hash, status,
capabilities jsonb, last_seen_at,
created_at, updated_at
)
compute_jobs(
job_id pk, user_id fk, task_id fk,
idempotency_key, capability, request jsonb,
node_id fk, status, progress,
error jsonb, artifact_manifest jsonb,
created_at, terminal_at, updated_at
)
```
MVP 状态:
```text
queued
running
succeeded
failed
cancelled
disconnected
```
Node 断线且本地任务可能仍在执行时标记 `disconnected`不得自动重派。Node 重连后按 `job_id + request_digest` 和本地终态对账。
## 7. Origin 任务闭环
当前实现进度:云端任务账本、幂等提交、短期 offer、Node 本地原子保存与 accept/reject 已落地。输入以任务绑定的 artifact UUID 下载Node 流式校验大小和 SHA-256 后原子保存。固定 Worker 使用管理员安装的隔离 Python 运行时与随程序发布的 `worker.py` 驱动 Origin生成 OPJU、PNG、SVG、PDF、plot spec、provenance 和原子 `terminal.json`;运行不绑定单次 WebSocket断线后继续执行。同一进程按 job 去重Node 重启后不重复启动已留启动标记但无可信终态的任务。成功产物逐项流式上传到云端隐藏暂存区,云端复核任务身份、固定文件名、大小和 SHA-256 后,一次性发布到 `<working_dir>/origin/<job_id>/` 并登记平台 artifact UUIDNode 以 `upload-complete.json` 恢复中断上传。
```text
用户上传 CSV/XLSX
→ zcbot 生成受控 plot spec
→ Node 接收 origin.plot@v1
→ 先持久化 job再启动 Origin Worker
→ originpro 生成 OPJU/PNG/SVG/PDF
→ terminal.json 原子记录终态
→ Node 通过 HTTP 上传最终截图和产物
→ zcbot 导入 working_dir 并发布
```
MVP 保留:
- 一次性注册与自动连接;
- 每 Node 独立 Token、DPAPI、禁用和轮换
- 幂等提交;
- 独立任务目录;
- 断线不终止计算;
- SQLite 和 `terminal.json`
- SHA-256 校验;
- 协作取消与精确进程回收;
- 最终截图和产物上传。
MVP 暂缓:
- HTTPS/WSS
- 短期连接令牌、HMAC、nonce
- 客户端证书和 mTLS
- 完整任务租约和多节点调度;
- 独立 DesktopRunner
- 分块断点上传;
- 自动更新;
- 任意 Computer Use
- 视频直播。
## 8. 验收标准
1. 新 Node 能凭一次性注册码完成注册。
2. Node 或 Windows 重启后无需人工操作即可自动连接。
3. zcbot 能显示在线状态、最后心跳、Origin 版本和 slot。
4. Token 不出现在 URL、日志或 zcbot 数据库明文中。
5. 禁用 Node 后,现有连接关闭且无法重新连接或上传。
6. 复制 Node 配置到不同 `install_id` 的机器不能形成两个活动执行者。
7. 同一幂等键不会创建两个 Origin 任务。
8. WS 中断时 Origin 继续运行,重连后能补报状态和产物。
9. Node 重启后能识别已有终态,不重复绘图。
10. zcbot 能接收并发布 OPJU、PNG、SVG 和 PDF。
11. 连续运行 50 个任务,无残留 Origin 进程或许可证泄漏。
12. 从非白名单内网 IP 访问 Node API 被安全组拒绝。
## 9. 升级触发条件
出现以下任一情况,先将通信升级到 HTTPS/WSS
- Node 与 zcbot 跨 VPC、跨安全域或经过公网
- 同一网络出现不受信任终端;
- 输入、截图或产物属于敏感数据并要求链路加密;
- 安全审计明确要求传输加密。
升级时保持 URL path、Node ID、Bearer Header 和任务协议不变,只把 `http/ws` scheme 改为 `https/wss` 并部署服务端证书。设备身份治理进一步提高时,再升级客户端证书和 mTLS。