@twinsearth/w2m-dsh-plugin 2.0.8 → 2.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +8 -0
- package/TEST-CASES-JOINT-FLEET-2.0.8.md +119 -0
- package/TEST-PLAN-JOINT-FLEET-2.0.8.md +99 -0
- package/codex/mcp-servers.toml +1 -1
- package/docs/DSH-UPGRADE-2.0.8.md +129 -0
- package/docs/TRANSFER-LAYER.md +162 -0
- package/docs/acceptance/2.0.9/RELEASE-2090.json +24 -0
- package/docs/adr/0002-p2p-transport.md +67 -0
- package/lib/client.js +29 -3
- package/package.json +5 -3
- package/plugin.json +1 -1
- package/src/agent/agent.mjs +7 -0
- package/src/agent/discovery.mjs +81 -0
- package/src/agent/iroh-sidecar.mjs +149 -0
- package/src/agent/p2p-node.mjs +11 -1
- package/src/agent/p2p-race.mjs +105 -0
- package/src/agent/p2p.mjs +105 -18
- package/src/agent/path-scheduler.mjs +106 -0
- package/src/agent/transfer/artifact-ref-v3.mjs +93 -0
- package/src/agent/transfer/ferry.mjs +12 -1
- package/src/agent/transfer/router.mjs +80 -0
- package/src/agent/transfer/want-block.mjs +46 -0
- package/src/agent/transport.mjs +146 -0
- package/src/plugin/tools.mjs +35 -25
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
},
|
|
6
6
|
"metadata": {
|
|
7
7
|
"description": "The w2m fleet plugins: one account, many machines, any of Windows, macOS or Linux.",
|
|
8
|
-
"version": "2.0.
|
|
8
|
+
"version": "2.0.9"
|
|
9
9
|
},
|
|
10
10
|
"plugins": [
|
|
11
11
|
{
|
|
12
12
|
"name": "w2m-fleet",
|
|
13
13
|
"source": "./",
|
|
14
14
|
"description": "Read fleet state and dispatch commands across the machines registered to one account. Read-only MCP surface: the five exposed tools cannot change anything.",
|
|
15
|
-
"version": "2.0.
|
|
15
|
+
"version": "2.0.9",
|
|
16
16
|
"author": {
|
|
17
17
|
"name": "TwinsEarth"
|
|
18
18
|
},
|
|
@@ -26,5 +26,5 @@
|
|
|
26
26
|
]
|
|
27
27
|
}
|
|
28
28
|
],
|
|
29
|
-
"version": "2.0.
|
|
29
|
+
"version": "2.0.9"
|
|
30
30
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "w2m-fleet",
|
|
3
3
|
"description": "Drive the same project on online Windows, macOS and Linux machines from one account: read fleet state, dispatch commands and read results. The MCP surface is deliberately read-only.",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.9",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "TwinsEarth"
|
|
7
7
|
},
|
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,14 @@ All notable changes to this project are documented here.
|
|
|
7
7
|
- `w2m_intent`: structured intents mapped onto allow-listed commands; unknown actions, parameters and types
|
|
8
8
|
are refused by name (the fleet does not invent commands).
|
|
9
9
|
|
|
10
|
+
## [2.0.9] - 2026-10-30
|
|
11
|
+
|
|
12
|
+
- P2P 可靠性:ACK 驱动窗口、自适应窗口、RFC 6298 RTT/自适应 RTO;明文通道复用改为强制新握手。
|
|
13
|
+
- 传输抽象:P2PTransport / udp-v1、能力协商 + 竞速、PathScheduler 评分与 make-before-break、iroh sidecar 契约(假二进制测试)。
|
|
14
|
+
- 传输层:ArtifactRef v3(SHA-256 Merkle + BLAKE3 回退标记)、xfer 帧路由、P0-a 通道适配器、verifyRefV2 自洽校验与冲突驱逐。
|
|
15
|
+
- 编队:w2m_status.fleet / FLEET_UNBOUND、fleetKey 自动重新准入、底部状态栏(本编队/全服/Relay 圆点)。
|
|
16
|
+
- 测试:新增 transport/race/scheduler/discovery/iroh-sidecar/xfer-channel/router/recovery/ref-v3 等套件。
|
|
17
|
+
|
|
10
18
|
## [2.0.8] - 2026-10-29
|
|
11
19
|
|
|
12
20
|
- P2P 加密:新增 RFC 8439 ChaCha20-Poly1305 纯 JS 回退,Electron/BoringSSL 缺少 chacha 时自动启用,wire 字节与原生实现一致;保留 P2P_CIPHER_UNAVAILABLE 诊断。
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# 联合开发 & 编队协作测试用例 v2.0.8
|
|
2
|
+
|
|
3
|
+
图例:✅ 已执行通过;⚠️ 部分通过/有限证据;🚫 被环境阻断;⬜ 计划未执行。
|
|
4
|
+
配套计划:[TEST-PLAN-JOINT-FLEET-2.0.8.md](TEST-PLAN-JOINT-FLEET-2.0.8.md)
|
|
5
|
+
|
|
6
|
+
## A. 联合开发(JD)
|
|
7
|
+
|
|
8
|
+
| ID | 级别 | 前置 | 步骤 | 预期 | 状态 / 证据 |
|
|
9
|
+
|---|---|---|---|---|---|
|
|
10
|
+
| JD-01 | P0 | CLI/stateDir | `w2m-joint plan` 创建 2 步计划 | 返回 plan_sha256;可 list/get;命令哈希稳定 | ✅ 既有 evidence(joint plan 92e299aa…) |
|
|
11
|
+
| JD-02 | P0 | 无签名审批 | `--allow-unsigned-approval` 派发 | 拒绝 `UNKNOWN_FLAG`,无 POST | ✅ joint-cli |
|
|
12
|
+
| JD-03 | P0 | operator key | 审批后派发一次 | relay 收到 1 次;审计 sending→sent;审批被消费 | ✅ 真实 relay 2.0.5 |
|
|
13
|
+
| JD-04 | P0 | 已消费审批 | 重放同一审批 | `APPROVAL_ALREADY_USED`,0 次 POST | ✅ joint-cli |
|
|
14
|
+
| JD-05 | P0 | 伪造/过期审批 | 篡改签名或超 TTL | `APPROVAL_SIGNATURE_INVALID` / `APPROVAL_EXPIRED` | ✅ plan-store/operator-key |
|
|
15
|
+
| JD-06 | 🛡 | 审批字段 | 改 plan_sha / base / target | 拒绝,绑定字段不符 | ✅ merge-approval;JOINT-R5 |
|
|
16
|
+
| JD-07 | P0 | DSH 在线 | 计划含 DSH/ToFuture 两步,派发 | 两步均 done;progress=complete | ⚠️ 曾 s1 done/s2 refused(allowlist);需复测 |
|
|
17
|
+
| JD-08 | P0 | 已合并 | rollback ref 恢复 | 目标回旧 head;审批不可复用 | ⬜ 现场演练 |
|
|
18
|
+
| JD-09 | P1 | 合并冲突 | 3-way/CAS 冲突 | 具名冲突,不静默覆盖 | ✅ merge-engine 套件 |
|
|
19
|
+
|
|
20
|
+
## B. 编队协作(FC)
|
|
21
|
+
|
|
22
|
+
| ID | 级别 | 前置 | 步骤 | 预期 | 状态 / 证据 |
|
|
23
|
+
|---|---|---|---|---|---|
|
|
24
|
+
| FC-01 | P0 | relay 在线 | `w2m_devices` | 只返回本编队设备,口径含 online/offline_reason | ✅ ToFuture/DSH/macmini 004945 |
|
|
25
|
+
| FC-02 | P0 | 两机 | 派发 `node --version`(assignee) | verdict=consistent;签名=signed | ✅ 任务 01M64TEK…(ToFuture) |
|
|
26
|
+
| FC-03 | P0 | 两机 | 不指定 assignee 派发 | **测试纪律禁止**;应显式目标 | ✅ TD-01 已固化 |
|
|
27
|
+
| FC-04 | P0 | 一机离线 | 派发到离线机 | lease expired → partial,不伪造 ok | ✅ 任务 01M64TR…(DSH expired) |
|
|
28
|
+
| FC-05 | P1 | 两机在线 | 编队聊天收发 | 双方可读,密文 v2 门控生效 | ✅ 既有 chess 会话 |
|
|
29
|
+
| FC-06 | P1 | composer | 选择目标机后派发 | 仅选中机收到任务 | ⚠️ 需 UI 现场复核 |
|
|
30
|
+
| FC-07 | P0 | 设备 token | `fleet_id` 为空 | 不显示“已加入”,返回 FLEET_UNBOUND | ✅ fleet-binding 单测 4/4 |
|
|
31
|
+
| FC-08 | P0 | 同机双 agent | 同时起两份 localside | 必须拒绝/二选一,避免版本跳变 | ⬜ 需负例演练 |
|
|
32
|
+
| FC-09 | P1 | 结果回传 | P2P 结果 ACK 超时 | 回退 relay 并显式记录 | ✅ P2P_ACK_TIMEOUT 可见 |
|
|
33
|
+
|
|
34
|
+
## C. 编队绑定与版本(FB)
|
|
35
|
+
|
|
36
|
+
| ID | 级别 | 前置 | 步骤 | 预期 | 状态 / 证据 |
|
|
37
|
+
|---|---|---|---|---|---|
|
|
38
|
+
| FB-01 | P0 | token 有效 | 读取自身设备记录 | `fleet_id` 非空 → state=bound | ✅ ToFuture fleet_id=004945 |
|
|
39
|
+
| FB-02 | P0 | token 有效 + fleet_id=null | 启动 agent | `FLEET_UNBOUND`;有 fleetKey 时自动 re-admission | ✅ 单测 + 真实修复 |
|
|
40
|
+
| FB-03 | P0 | 错 relay 的 token | 启动 | 401 → 重新配对,不静默 | ✅ 实测 202.182→43.142 |
|
|
41
|
+
| FB-04 | P0 | 无 fleetKey | 启动 | 返回可执行 remedy,不显示已加入 | ✅ fleet-binding 单测 |
|
|
42
|
+
| FB-05 | P0 | 配置 2.0.8 | `w2m_status.fleet` | 含 fleet_id/state/code/token_present/remedy | ✅ 宿主 2.0.8 输出 |
|
|
43
|
+
| FB-06 | P0 | 三机同名 | 读 relay caps | 版本稳定,无 2.0.7/2.0.8 跳变 | ⚠️ macmini 仍 2.0.7 |
|
|
44
|
+
| FB-07 | P1 | 备用链路 | 起 secondary-link | 不得覆盖主 device.json / 不得抢编队 | ✅ 已禁用 keeper |
|
|
45
|
+
| FB-08 | P1 | 计划任务 | 禁用 standby keeper 后重启 | 本机不再出现 ToFuture-standby | ✅ 已禁用 |
|
|
46
|
+
|
|
47
|
+
## D. P2P 加密握手(PH)
|
|
48
|
+
|
|
49
|
+
| ID | 级别 | 前置 | 步骤 | 预期 | 状态 / 证据 |
|
|
50
|
+
|---|---|---|---|---|---|
|
|
51
|
+
| PH-01 | P0 | Electron 宿主 | 探测 chacha | 原生缺失时 fallback 可用 | ✅ 宿主 native=false,caps 6/6 |
|
|
52
|
+
| PH-02 | P0 | JS/原生双端 | AEAD 交叉验证 | 密文逐字节一致、双向可解、篡改拒绝 | ✅ 52/52 |
|
|
53
|
+
| PH-03 | P0 | 非本机目标 | 派发一次任务 | 两端 handshakes≥1、encrypted≥1、refused=0 | ⚠️ 2026-10-30 复测 task 01M64WBW…:`Unknown cipher` 消失,但 `P2P_FRAGMENT_UNACKED` + `P2P_CHANNEL_CLOSED`;DSH 仍 `COMMAND_NOT_ALLOWED`;handshakes 仍 0 |
|
|
54
|
+
| PH-04 | P0 | 本机自派 | 向 ToFuture 派发 | 明文是设计行为,不作握手证据 | ✅ 已确认 NO_KEY/PLAINTEXT_PEER |
|
|
55
|
+
| PH-05 | P1 | 旧版对端 | 2.0.7 对 2.0.8 | 明确错误/拒绝,不静默降级 | ⬜ 需 macmini 升级前后对比 |
|
|
56
|
+
| PH-06 | P1 | stateDir 缺失 | 结果回传 | `P2P_NO_STATE_DIR` 可见,回退 relay | ✅ 任务 01M64TE… envelope 证据 |
|
|
57
|
+
|
|
58
|
+
## E. 文件 E2E(XF)
|
|
59
|
+
|
|
60
|
+
| ID | 级别 | 前置 | 步骤 | 预期 | 状态 / 证据 |
|
|
61
|
+
|---|---|---|---|---|---|
|
|
62
|
+
| XF-01 | P0 | 本地 | 分块 + bitmap + 逐块校验 | 乱序/续传/篡改/穿越均拒绝 | ✅ xfer-foundation/ferry 12/12 |
|
|
63
|
+
| XF-02 | P0 | relay 在线 | publishRef → listPublishedRefs | 同 rootCid 可读回,控制面无字节 | ✅ 真实 relay 2.0.5 |
|
|
64
|
+
| XF-03 | P0 | 单机 | sender/receiver 双进程 loopback | rootCid/落盘 SHA 一致 | ✅ 262144B verified=true |
|
|
65
|
+
| XF-04 | P0 | 单机 | `--peer` 候选地址探测 | 选中候选(192.168.56.1),verified=true | ✅ 131072B,artifact.ready=true |
|
|
66
|
+
| XF-05 | P0 | 两机 | 跨机 sender/receiver | 对端落盘一致,relay 零字节 | 🚫 DSH 离线;macmini allowlist |
|
|
67
|
+
| XF-06 | P0 | 传输中断 | kill 接收端再重启 | bitmap 续传,根哈希最终一致 | ⬜ 计划 |
|
|
68
|
+
| XF-07 | 🛡 | 路径穿越 | destination=`../x` | 拒绝(safeRelative) | ✅ ferry 单测 |
|
|
69
|
+
| XF-08 | P0 | 完成 | artifact.ready | relay 决策可见,仅元数据 | ✅ 实测 artifact_ready_published=true |
|
|
70
|
+
|
|
71
|
+
## F. 发布门禁(RG)
|
|
72
|
+
|
|
73
|
+
| ID | 级别 | 步骤 | 预期 | 状态 / 证据 |
|
|
74
|
+
|---|---|---|---|---|
|
|
75
|
+
| RG-01 | P0 | commit | 目标分支含 v2.0.8 | ✅ `0ecedb4c…b526d7` |
|
|
76
|
+
| RG-02 | P0 | tag | `v2.0.8` 指向同一 commit | ✅ |
|
|
77
|
+
| RG-03 | P0 | GitHub Release | 200,正文含变更/回滚 | ✅ |
|
|
78
|
+
| RG-04 | P0 | npm | 2.0.8=latest,shasum 一致 | ✅ `adf91572…` |
|
|
79
|
+
| RG-05 | P0 | CI | success | ✅ |
|
|
80
|
+
| RG-06 | P0 | Compat | success | ✅ 双 run |
|
|
81
|
+
| RG-07 | P0 | Release workflow | success | ✅ |
|
|
82
|
+
| RG-08 | P0 | healthz | relay 在线且 features 符合 | ✅ 2.0.5 + chat-enc-v2 |
|
|
83
|
+
| RG-09 | P0 | preflight | GREEN,0 fail | ✅ 3267 tests / 3246 pass / 21 skip |
|
|
84
|
+
|
|
85
|
+
## G. 安全负例(SEC)
|
|
86
|
+
|
|
87
|
+
| ID | 级别 | 步骤 | 预期 | 状态 |
|
|
88
|
+
|---|---|---|---|---|
|
|
89
|
+
| SEC-01 | 🛡 | 伪造审批签名 | 拒绝,无派发 | ✅ |
|
|
90
|
+
| SEC-02 | 🛡 | 重放审批 | 拒绝 | ✅ |
|
|
91
|
+
| SEC-03 | 🛡 | 空 allowlist 派发 | agent 拒绝,具名 COMMAND_NOT_ALLOWED | ✅ macmini/旧 ToFuture |
|
|
92
|
+
| SEC-04 | 🛡 | token 写入文档/技能 | 扫描拒绝 | ✅ skills/preflight |
|
|
93
|
+
| SEC-05 | 🛡 | relay 存文件字节 | 拒绝 DATA_PLANE_REFUSED | ✅ |
|
|
94
|
+
| SEC-06 | 🛡 | 明文聊天镜像 | 无 feature 时保持 v1 | ✅ chat-crypto-aad |
|
|
95
|
+
|
|
96
|
+
## H. 混合版本治理(MV)
|
|
97
|
+
|
|
98
|
+
| ID | 级别 | 步骤 | 预期 | 状态 |
|
|
99
|
+
|---|---|---|---|---|
|
|
100
|
+
| MV-01 | P0 | 统计 26 台名册 | 区分 bound/unknown/old,不用 state 字段 | ✅ 26 台 / 20 台 null / ~20 编队 |
|
|
101
|
+
| MV-02 | P0 | 三机统一 2.0.8 | 三机 caps=2.0.8 | ⚠️ ToFuture/DSH 2.0.8,macmini 2.0.7 |
|
|
102
|
+
| MV-03 | P0 | 版本门 | 混合期 warn,不 enforce | ✅ 默认 warn |
|
|
103
|
+
| MV-04 | P1 | 发布后 10 分钟 | devices_unbound=0 | ⬜ 需监控指标上线 |
|
|
104
|
+
|
|
105
|
+
## I. 测试纪律(TD)
|
|
106
|
+
|
|
107
|
+
| ID | 要求 | 状态 |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| TD-01 | 派发必须显式 assignee/target_machines | ✅ 已固化 |
|
|
110
|
+
| TD-02 | 禁止裸 replicate 全 fleet | ✅ 本轮 23 台泛洪已取消并记录 |
|
|
111
|
+
| TD-03 | 无 assignee 负例仅隔离环境且立即取消 | ✅ |
|
|
112
|
+
| TD-04 | plugin_version=null 只观测,不纳入验收 | ✅ |
|
|
113
|
+
| TD-05 | 未实跑项标 PLANNED/BLOCKED,不写成通过 | ✅ 本文档执行 |
|
|
114
|
+
|
|
115
|
+
## 当前汇总
|
|
116
|
+
|
|
117
|
+
- P0 已通过:JD 1–6、FC 1/2/4/7、FB 1–5、PH 1/2/4、XF 1–4/7/8、RG 1–9、SEC 1–6;
|
|
118
|
+
- 阻断:PH-03、XF-05(DSH 离线 / macmini allowlist);
|
|
119
|
+
- 待补:JD-07 复测、JD-08 回滚、FC-08 双实例、XF-06 续传、MV-02 三机统一。
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# 联合开发 & 编队协作测试计划 v2.0.8
|
|
2
|
+
|
|
3
|
+
状态:执行中(v2.0.8 已发布,三机版本尚未统一)
|
|
4
|
+
基线:commit `0ecedb4c658914bbf3dd901419f11c4920b526d7` / npm `2.0.8`
|
|
5
|
+
配套用例:[TEST-CASES-JOINT-FLEET-2.0.8.md](TEST-CASES-JOINT-FLEET-2.0.8.md)
|
|
6
|
+
|
|
7
|
+
## 1. 目标与范围
|
|
8
|
+
|
|
9
|
+
验证两条主能力:
|
|
10
|
+
|
|
11
|
+
1. **联合开发(Joint Dev)**:计划 → Ed25519 人工审批 → relay 派发 → 执行 → 进度投影 → 审计 → 合并/回滚;
|
|
12
|
+
2. **编队协作(Fleet)**:设备发现/编队绑定 → 聊天 → 目标机选择 → 跨机派发 → 结果回收 → 文件 E2E。
|
|
13
|
+
|
|
14
|
+
新增 v2.0.8 专项:
|
|
15
|
+
|
|
16
|
+
- 编队绑定诊断 `w2m_status.fleet` 与 `FLEET_UNBOUND` 自动纠正;
|
|
17
|
+
- P2P 加密握手(ChaCha20-Poly1305 纯 JS 回退);
|
|
18
|
+
- 文件传输 want-block / sender-receiver 双角色 / 候选地址探测;
|
|
19
|
+
- 八项发布门禁。
|
|
20
|
+
|
|
21
|
+
不在范围:relay 升级(保持 2.0.5)、CRDT(ADR only)、未发布客户端适配。
|
|
22
|
+
|
|
23
|
+
## 2. 环境与实例
|
|
24
|
+
|
|
25
|
+
| 实例 | 机器 | 角色 | 已知状态 |
|
|
26
|
+
|---|---|---|---|
|
|
27
|
+
| E1 | ToFuture `b53a37f4…` | 发射台 / 本机 | agent 2.0.8 在线,编队 004945,allowlist `["node"]` |
|
|
28
|
+
| E2 | DSH `1bef9935…` | 跨机执行 | 编队 004945;2026-10-30 曾离线,需先恢复 |
|
|
29
|
+
| E3 | macmini `b1b19d49…` | 跨机执行 | 2.0.7,allowlist 空,SSH 未开 |
|
|
30
|
+
| R1 | relay 43.142.74.71 | 主 relay | 2.0.5 冻结,features:target-machines/result-projection/chat-enc-v2 |
|
|
31
|
+
| R2 | relay 202.182.123.154 | 备用 relay | 仅备用链路,不参与主验收 |
|
|
32
|
+
|
|
33
|
+
名册口径(必须按此判定):
|
|
34
|
+
|
|
35
|
+
- 真正在线:`online===true && offline_reason===null`;
|
|
36
|
+
- 版本未知:`caps.plugin_version` 缺失,**不等于旧版**;
|
|
37
|
+
- 全服设备数来自 `/healthz`,逐台版本只来自 `/v1/devices`(按编队过滤)。
|
|
38
|
+
|
|
39
|
+
## 3. 测试分层
|
|
40
|
+
|
|
41
|
+
| 层 | 内容 | 入口 |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| L0 静态 | lint、schema、claims、Skills、Agent Plugins | `node scripts/preflight.mjs` |
|
|
44
|
+
| L1 单元 | fleet-binding、chacha、xfer、joint、chat、version gate | `node --test test/<name>.test.mjs` |
|
|
45
|
+
| L2 契约 | MCP 工具、relay 路由、acceptance records | preflight 内建 |
|
|
46
|
+
| L3 单机 E2E | plan→approve→dispatch→progress→audit(同机) | `bin/w2m-joint.mjs` |
|
|
47
|
+
| L4 双机 E2E | 跨机派发、聊天、文件 sender/receiver | relay + 两机 |
|
|
48
|
+
| L5 发布门禁 | commit/tag/Release/npm/CI/Compat/Release workflow/healthz | GitHub + npm |
|
|
49
|
+
|
|
50
|
+
## 4. 进入/退出准则
|
|
51
|
+
|
|
52
|
+
进入:
|
|
53
|
+
|
|
54
|
+
- 代码冻结点明确(v2.0.8 commit);
|
|
55
|
+
- preflight GREEN(允许 host 观测项 UNVERIFIABLE,但不允许 FAIL);
|
|
56
|
+
- 主 relay 在线,E1 的 `fleet_id=004945`;
|
|
57
|
+
- E2/E3 至少一台可执行(allowlist 非空且在线)。
|
|
58
|
+
|
|
59
|
+
退出(视为通过):
|
|
60
|
+
|
|
61
|
+
1. P0 用例 100%,P1 ≥95%,无 S1/S2 缺陷;
|
|
62
|
+
2. 联合开发:计划/审批/派发/审计/进度五段均有真实 relay 证据;
|
|
63
|
+
3. 编队:跨机任务 verdict=consistent 且签名有效;
|
|
64
|
+
4. P2P:跨机 `handshakes≥1`、`encrypted_channels≥1`、`refused=0`;
|
|
65
|
+
5. 文件:两机 rootCid 与落盘 SHA-256 一致,relay 无文件字节;
|
|
66
|
+
6. 八项发布门禁全绿,npm shasum 与 Release 资产一致;
|
|
67
|
+
7. 所有失败具名(错误码/机器/版本/relay)。
|
|
68
|
+
|
|
69
|
+
阻断判定:E2 离线或 E3 allowlist 为空时,L4 只能标 BLOCKED,不得用单机结果替代。
|
|
70
|
+
|
|
71
|
+
## 5. 执行顺序
|
|
72
|
+
|
|
73
|
+
1. 环境基线:三机版本、编队绑定、allowlist、relay 版本;
|
|
74
|
+
2. L0/L1:preflight + 新专项套件;
|
|
75
|
+
3. L3:联合开发单机闭环;
|
|
76
|
+
4. L4-A:编队聊天 + 目标选择 + 跨机派发;
|
|
77
|
+
5. L4-B:P2P 握手验证(只对非本机派发);
|
|
78
|
+
6. L4-C:文件 E2E(sender/receiver + 候选地址);
|
|
79
|
+
7. L5:发布门禁证据归档;
|
|
80
|
+
8. 失败项回归与报告。
|
|
81
|
+
|
|
82
|
+
## 6. 证据规则
|
|
83
|
+
|
|
84
|
+
- 每条用例记录:时间、机器、relay、版本、任务/ref ID、结果;
|
|
85
|
+
- 不把“代码已实现”当“现场通过”;
|
|
86
|
+
- 不接受自派发(ToFuture→ToFuture)作为 P2P 加密证据(设计为明文);
|
|
87
|
+
- 版本证据必须同一时间窗采集:package.json / 进程启动时间 / relay caps 三者相差 ≤5 分钟;
|
|
88
|
+
- 敏感信息(token/key/聊天明文)不得进入证据。
|
|
89
|
+
|
|
90
|
+
## 7. 风险
|
|
91
|
+
|
|
92
|
+
| 风险 | 影响 | 对策 |
|
|
93
|
+
|---|---|---|
|
|
94
|
+
| DSH 离线 | 跨机全阻断 | 到场恢复;或先修 macmini allowlist |
|
|
95
|
+
| macmini 2.0.7 + allowlist 空 | 版本不齐/拒绝执行 | 本机升级 2.0.8、写入 allowlist 后重启 |
|
|
96
|
+
| stateDir:null | FLEET_UNPAIRED、结果回退 relay | 配置 stateDir 并重启宿主 |
|
|
97
|
+
| 名册 26 台 / 20 台版本未知 | 统计口径混乱 | 用 §2 口径;只统计 004945 |
|
|
98
|
+
| 自派发明文 | 误判握手失败 | 禁止作为 PH 证据 |
|
|
99
|
+
| 手工 tarball 与 npm 字节差异 | 版本证据弱 | 比对 npm shasum 与本地包 |
|
package/codex/mcp-servers.toml
CHANGED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# DSH 机器升级 2.0.8 + allowlist 修复清单
|
|
2
|
+
|
|
3
|
+
目标:DSH 侧具备 2.0.8 的 ChaCha20-Poly1305 纯 JS 回退与 peer key 逻辑,并让 allowlist 真正生效。
|
|
4
|
+
前置:DSH 机器本机操作;relay 保持 43.142.74.71:8787;编队 004945。
|
|
5
|
+
|
|
6
|
+
## 1. 升级前快照
|
|
7
|
+
|
|
8
|
+
```powershell
|
|
9
|
+
$profile = "$env:USERPROFILE\.dsh\profiles\desktop"
|
|
10
|
+
$plugin = "$profile\node_modules\@twinsearth\w2m-dsh-plugin"
|
|
11
|
+
Copy-Item "$profile\..\xclient\device.json" "$env:TEMP\device.json.dsh-bak" -Force
|
|
12
|
+
if (Test-Path $plugin) {
|
|
13
|
+
(Get-Content "$plugin\package.json" -Raw | ConvertFrom-Json).version
|
|
14
|
+
}
|
|
15
|
+
Get-CimInstance Win32_Process -Filter "name='node.exe'" |
|
|
16
|
+
Where-Object { $_.CommandLine -match 'w2m-localside' } |
|
|
17
|
+
Select-Object ProcessId, CommandLine
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
记录:当前版本、localside 启动参数、`device.json` 位置。
|
|
21
|
+
|
|
22
|
+
## 2. 下载并校验 2.0.8
|
|
23
|
+
|
|
24
|
+
```powershell
|
|
25
|
+
$tmp = Join-Path $env:TEMP 'w2m-2.0.8.tgz'
|
|
26
|
+
Invoke-WebRequest 'https://registry.npmjs.org/@twinsearth/w2m-dsh-plugin/-/w2m-dsh-plugin-2.0.8.tgz' -OutFile $tmp
|
|
27
|
+
(Get-FileHash $tmp -Algorithm SHA256).Hash.ToLower()
|
|
28
|
+
# 期望:700c06ba81195fc36c129bc2e9337c2cf2b678965decd456d3a73d05b9aa1251
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## 3. 停旧进程(不要在这个窗口里启动升级脚本后再停自己)
|
|
32
|
+
|
|
33
|
+
```powershell
|
|
34
|
+
# 停独立 localside
|
|
35
|
+
Get-CimInstance Win32_Process -Filter "name='node.exe'" |
|
|
36
|
+
Where-Object { $_.CommandLine -match 'w2m-localside' } |
|
|
37
|
+
ForEach-Object { Stop-Process -Id $_.ProcessId -Force }
|
|
38
|
+
|
|
39
|
+
# 若由计划任务/WinSW 托管
|
|
40
|
+
Stop-ScheduledTask -TaskName 'W2M Localside agent' -ErrorAction SilentlyContinue
|
|
41
|
+
# 或:Restart-Service w2mlocalside
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 4. 替换插件树(脚本方式)
|
|
45
|
+
|
|
46
|
+
在 DSH 机器上执行:
|
|
47
|
+
|
|
48
|
+
```powershell
|
|
49
|
+
powershell -ExecutionPolicy Bypass -File .\scripts\dsh-install-2.0.8.ps1 -ProfileName desktop
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
脚本会:校验 sha256 → 备份旧插件目录 → 解包 2.0.8 → 打印版本与新插件路径;**不会重启 DSH**。
|
|
53
|
+
|
|
54
|
+
手动等价步骤:
|
|
55
|
+
|
|
56
|
+
```powershell
|
|
57
|
+
$backup = "$plugin.bak-$(Get-Date -Format yyyyMMddHHmmss)"
|
|
58
|
+
Move-Item $plugin $backup
|
|
59
|
+
New-Item -ItemType Directory -Force $plugin | Out-Null
|
|
60
|
+
tar -xzf $tmp -C $plugin --strip-components=1
|
|
61
|
+
node -e "console.log(require('$($plugin -replace '\\','/')/package.json').version)"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 5. 重启宿主 + 修复 allowlist
|
|
65
|
+
|
|
66
|
+
先重启 DSH(外部执行):
|
|
67
|
+
|
|
68
|
+
```powershell
|
|
69
|
+
Stop-Process -Name 'DeepSeek Harness' -Force
|
|
70
|
+
Start-Sleep 3
|
|
71
|
+
Start-Process 'E:\DS\DeepSeek Harness.exe'
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
allowlist 必须落到**实际运行的 agent**:
|
|
75
|
+
|
|
76
|
+
### A. 独立 localside
|
|
77
|
+
|
|
78
|
+
```powershell
|
|
79
|
+
node "$plugin\bin\w2m-localside.mjs" `
|
|
80
|
+
--rabbit http://43.142.74.71:8787 `
|
|
81
|
+
--name DSH `
|
|
82
|
+
--state "$env:USERPROFILE\.dsh\xclient\localside" `
|
|
83
|
+
--fleet-key <004945 的 fleet key> `
|
|
84
|
+
--allowed-commands '["node"]'
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### B. 插件 autoStartAgent(没有独立进程)
|
|
88
|
+
|
|
89
|
+
在 DSH 的项目根放 `.w2m.json`:
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{ "allowedCommands": ["node"] }
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
再重启 DSH。
|
|
96
|
+
|
|
97
|
+
## 6. 验收
|
|
98
|
+
|
|
99
|
+
```powershell
|
|
100
|
+
# 版本
|
|
101
|
+
node -e "console.log(require('$($plugin -replace '\\','/')/package.json').version)" # 2.0.8
|
|
102
|
+
|
|
103
|
+
# 执行(从 ToFuture 派发)
|
|
104
|
+
# w2m_run assignee=DSH command=["node","--version"]
|
|
105
|
+
# 期望:outcome=ok / exit_code=0;不再 COMMAND_NOT_ALLOWED
|
|
106
|
+
|
|
107
|
+
# P2P(ToFuture 侧)
|
|
108
|
+
# w2m_status.p2p.encryption:
|
|
109
|
+
# handshakes >= 1
|
|
110
|
+
# encrypted_channels >= 1
|
|
111
|
+
# refused = 0
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## 7. 回滚
|
|
115
|
+
|
|
116
|
+
```powershell
|
|
117
|
+
Stop-Process -Name 'DeepSeek Harness' -Force -ErrorAction SilentlyContinue
|
|
118
|
+
Remove-Item $plugin -Recurse -Force
|
|
119
|
+
Move-Item $backup $plugin
|
|
120
|
+
Start-Process 'E:\DS\DeepSeek Harness.exe'
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`device.json` 用第 1 步备份恢复;relay 不参与回滚。
|
|
124
|
+
|
|
125
|
+
## 已知边界
|
|
126
|
+
|
|
127
|
+
- 脚本只安装文件,不重启 DSH、不改 allowlist;
|
|
128
|
+
- 若 DSH 是 Intel Mac 或非 arm64/x64 平台,需单独确认 sidecar/平台能力;
|
|
129
|
+
- DSH 若仍使用旧宿主进程,版本显示 2.0.8 但握手仍会超时,必须真正重启宿主。
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# 文件传输与分块层(Transfer Layer)
|
|
2
|
+
|
|
3
|
+
状态:实现已存在(v2.0.8),本文固化契约;跨机链路仍受 P2P 握手/传输可靠性阻塞。
|
|
4
|
+
代码:`src/agent/transfer/{manifest,object-store,reference,ferry,want-block,publish}.mjs`
|
|
5
|
+
测试:`test/xfer-{foundation,ferry,publish,want-block}.test.mjs`
|
|
6
|
+
|
|
7
|
+
## 1. 分层
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Content Addressing manifest + rootCid + ArtifactRef
|
|
11
|
+
Chunk Store 分块文件、bitmap、原子 finalize
|
|
12
|
+
Transfer Session want/chunk 窗口、逐块校验、续传
|
|
13
|
+
Delivery / Sink dir / git / ssh,artifact_ready
|
|
14
|
+
Transport P2P(UDP/iroh 可替换),relay 永不承载字节
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 2. 内容寻址
|
|
18
|
+
|
|
19
|
+
- 每块:`chunkHash[i] = SHA-256(chunkBytes[i])`;
|
|
20
|
+
- 根:对“有序块摘要 + 块数 + 总大小 + 版本标签”做域分离哈希,得到 `rootCid = "sha256:<hex>"`;
|
|
21
|
+
- `ArtifactRef v2` 至少包含:
|
|
22
|
+
```json
|
|
23
|
+
{ "rootCid", "size", "chunkCount", "chunkBytes",
|
|
24
|
+
"originPeer", "sinkHint", "createdAt", "version": 2 }
|
|
25
|
+
```
|
|
26
|
+
- 读取端只接受 `verifyRefV2(ref)` 通过的引用;根不一致即拒绝,不做“尽力修复”。
|
|
27
|
+
|
|
28
|
+
## 3. 原语契约
|
|
29
|
+
|
|
30
|
+
### chunkFile(path, { chunkBytes })
|
|
31
|
+
|
|
32
|
+
- 输出 `{ ok, rootCid, size, chunkCount, chunkBytes, chunks[] }`;
|
|
33
|
+
- `chunkBytes` 默认 256 KiB,最小 16 KiB,最大 2 MiB;
|
|
34
|
+
- 分块读取,不一次性载入整个文件;
|
|
35
|
+
- 空文件/短读/权限错误返回具名错误码。
|
|
36
|
+
|
|
37
|
+
### createReceiver({ stateDir, sinkRoot, ref, destination })
|
|
38
|
+
|
|
39
|
+
- 建立 `<stateDir>/<transferId>/data.part` 与 `bitmap.json`;
|
|
40
|
+
- `destination` 必须经 `safeRelative` 校验,拒绝 `..`、绝对路径、盘符、NUL;
|
|
41
|
+
- 恢复时读取 bitmap,只请求缺失块。
|
|
42
|
+
|
|
43
|
+
### writeChunk(index, data, expectedSha256)
|
|
44
|
+
|
|
45
|
+
- 先校验 `index` 范围、`data.length`、`SHA-256(data) == expected`,全部通过才写入;
|
|
46
|
+
- 写 `data.part` 对应 offset,随后原子更新 bitmap(temp+rename);
|
|
47
|
+
- 重复块:哈希一致则幂等成功,不一致拒绝 `XFER_CHUNK_HASH_MISMATCH`;
|
|
48
|
+
- 不信任调用方给出的长度/哈希。
|
|
49
|
+
|
|
50
|
+
### finalizeTransfer(rootCid)
|
|
51
|
+
|
|
52
|
+
- 要求 bitmap 全满;
|
|
53
|
+
- 重算根(不信任 bitmap),与 `ref.rootCid` 比较;
|
|
54
|
+
- `fsync` 数据与目录,`rename` 到最终路径(同目录,原子);
|
|
55
|
+
- 幂等:已 finalize 且哈希一致则返回成功,不重复覆盖。
|
|
56
|
+
|
|
57
|
+
## 4. 可恢复传输
|
|
58
|
+
|
|
59
|
+
- bitmap 持久化 `<stateDir>/<transferId>/bitmap.json`,含 `chunks/chunk_bytes/last_chunk_bytes/hashes`;
|
|
60
|
+
- 崩溃恢复:只信任 bitmap 中标记完成且哈希复核通过的块;
|
|
61
|
+
- 会话状态:`transferId`、`rootCid`、已收块集合、最后错误;
|
|
62
|
+
- 传输中断不删除 `data.part`,由显式 abort/GC 清理;
|
|
63
|
+
- 同一 `rootCid` 允许多次会话,但同一 `transferId` 必须单写者(CAS/锁)。
|
|
64
|
+
|
|
65
|
+
## 5. 传输协议(want-block)
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
xfer.want { transferId, rootCid, indices[] } // 窗口 ≤ 8
|
|
69
|
+
xfer.chunk { transferId, index, sha256, size, data }
|
|
70
|
+
xfer.error { transferId, code, index? }
|
|
71
|
+
xfer.done { transferId }
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
- 接收端按 bitmap 缺口发窗口请求;
|
|
75
|
+
- 每块独立校验,坏块只重试该块;
|
|
76
|
+
- 发送端不得读取/发送未请求的块;
|
|
77
|
+
- 流控:窗口上限 + 超时重发;irho/UDP 只替换传输,不改帧语义;
|
|
78
|
+
- relay 只承载 ref/元数据(publishRef),**永不承载 chunk 字节**。
|
|
79
|
+
|
|
80
|
+
## 6. 安全与限制
|
|
81
|
+
|
|
82
|
+
| 项 | 规则 |
|
|
83
|
+
|---|---|
|
|
84
|
+
| 路径 | `safeRelative`:拒绝穿越、绝对路径、盘符、保留名 |
|
|
85
|
+
| 大小 | 单块 ≤2 MiB;单文件上限由配置控制;防止磁盘打满 |
|
|
86
|
+
| 哈希 | SHA-256;算法升级需新版本标签,不静默混用 |
|
|
87
|
+
| 权限 | sink 目录 0600/0700;不写入 stateDir 之外 |
|
|
88
|
+
| 元数据 | 只发布 ref;不发布路径、token、聊天明文 |
|
|
89
|
+
| 拒绝 | 无效 ref/哈希/索引 → 具名错误,不重试到无限 |
|
|
90
|
+
|
|
91
|
+
## 7. 错误码(稳定面)
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
XFER_SOURCE_INVALID / XFER_ROOT_INVALID / XFER_CHUNK_INDEX_INVALID
|
|
95
|
+
XFER_CHUNK_LENGTH_INVALID / XFER_CHUNK_HASH_MISMATCH
|
|
96
|
+
XFER_WINDOW_INVALID / XFER_TRANSFER_MISMATCH / XFER_ROOT_MISMATCH
|
|
97
|
+
XFER_READ_SHORT / XFER_FINALIZE_INCOMPLETE / XFER_PATH_UNSAFE
|
|
98
|
+
XFER_CHUNK_TOO_LARGE / XFER_TIMEOUT / P2P_NO_CANDIDATES / P2P_UNREACHABLE
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## 8. 当前实现与缺口
|
|
102
|
+
|
|
103
|
+
已实现并测试:
|
|
104
|
+
|
|
105
|
+
- chunkFile/分块校验/根计算(foundation 6/6);
|
|
106
|
+
- receiver/writeChunk/bitmap/续传/穿越拒绝(ferry 6/6);
|
|
107
|
+
- publishRef/listPublishedRefs(publish 3/3,真实 relay 验证);
|
|
108
|
+
- want-block 窗口/逐块校验/篡改拒绝(want-block 4/4);
|
|
109
|
+
- 同机 loopback 与 sender/receiver 候选探测(verified=true)。
|
|
110
|
+
|
|
111
|
+
缺口(阻塞跨机):
|
|
112
|
+
|
|
113
|
+
1. P2P 加密握手未完成(PH-03);
|
|
114
|
+
2. UDP 分片 ACK/重传(P2P_FRAGMENT_UNACKED);
|
|
115
|
+
3. 跨机 sender/receiver(XF-05)需 DSH/macmini 可执行;
|
|
116
|
+
4. 断点续传跨机演练(XF-06);
|
|
117
|
+
5. 大文件吞吐与背压(当前窗口 8 × 16 KiB 级)。
|
|
118
|
+
|
|
119
|
+
## 9. 验收
|
|
120
|
+
|
|
121
|
+
- 根与逐块哈希全部一致;
|
|
122
|
+
- 任意中断后重启,最终文件 SHA-256 与源一致;
|
|
123
|
+
- 路径穿越/篡改/错索引全部具名拒绝;
|
|
124
|
+
- relay 侧抓包/日志无文件字节;
|
|
125
|
+
- 两机 E2E:publish → want → finalize → artifact_ready;
|
|
126
|
+
- 性能目标(待定):LAN 1 GiB < 60s,跨网按 P2P 传输能力单独定。
|
|
127
|
+
|
|
128
|
+
## 10. iroh-blobs / BLAKE3 评估(参考,不立即替换)
|
|
129
|
+
|
|
130
|
+
iroh-blobs 提供:BLAKE3 内容寻址、Merkle 树 verified streaming、天然断点续传、多源 want-list。
|
|
131
|
+
W2M 现状:SHA-256 + 扁平块哈希 + bitmap + 单源 want-block。
|
|
132
|
+
|
|
133
|
+
| 能力 | W2M 现状 | iroh-blobs | 结论 |
|
|
134
|
+
|---|---|---|---|
|
|
135
|
+
| 哈希 | SHA-256(OpenSSL/JS 可用) | BLAKE3(更快) | 不急着换;BLAKE3 需纯 JS/原生依赖 |
|
|
136
|
+
| 流式校验 | 逐块到达即校验 | Merkle 证明,支持部分验证 | 可后续加 Merkle,不破坏现有 ref |
|
|
137
|
+
| 断点续传 | bitmap 已实现 | 协议内建 | 已等价,无需替换 |
|
|
138
|
+
| 多源 | 单源 | 块级多 peer 并行 | 值得自研 want-list 调度,不必引入完整栈 |
|
|
139
|
+
| 依赖 | 零依赖 | Rust/原生绑定 | 与 tarball/Electron 约束冲突 |
|
|
140
|
+
|
|
141
|
+
建议:
|
|
142
|
+
|
|
143
|
+
1. **v2.x 保持 SHA-256 + bitmap**,不改变 ArtifactRef v2 与现有测试;
|
|
144
|
+
2. **v2.2.2 增加 `ArtifactRef v3`(feature flag)**:
|
|
145
|
+
```json
|
|
146
|
+
{ "rootCid", "hashAlg": "blake3"|"sha256", "merkleRoot",
|
|
147
|
+
"chunkBytes", "chunkCount", "size", "originPeer", "version": 3 }
|
|
148
|
+
```
|
|
149
|
+
双哈希过渡:v3 同时携带 `sha256Root`,旧端只读 v2,新端优先 v3;
|
|
150
|
+
3. **多源调度先自研**:want-list + peer 评分(时延/丢包/已成功率)+ 块租约,避免重复下载;
|
|
151
|
+
4. **iroh-blobs 只作为 sidecar 试验**:与 iroh 传输一起评估,不进入默认分发;
|
|
152
|
+
5. 验收:同一文件 v2/v3 root 可互证;中断续传 SHA-256 一致;多源重复块不重复写;无 BLAKE3 运行时回退 SHA-256 并记录 `hashAlg`。
|
|
153
|
+
|
|
154
|
+
风险:BLAKE3 在 Electron 可能同样缺原生实现(需纯 JS 回退);Merkle 证明增加协议面;多源引入 Sybil/污染块,必须逐块哈希校验并限制来源。
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
- 根与逐块哈希全部一致;
|
|
158
|
+
- 任意中断后重启,最终文件 SHA-256 与源一致;
|
|
159
|
+
- 路径穿越/篡改/错索引全部具名拒绝;
|
|
160
|
+
- relay 侧抓包/日志无文件字节;
|
|
161
|
+
- 两机 E2E:publish → want → finalize → artifact_ready;
|
|
162
|
+
- 性能目标(待定):LAN 1 GiB < 60s,跨网按 P2P 传输能力单独定。
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "2.0.9",
|
|
3
|
+
"case": "RELEASE-2090",
|
|
4
|
+
"kind": "positive",
|
|
5
|
+
"machines": [
|
|
6
|
+
"b53a37f4-1464-4512-9259-33a7df091e3e"
|
|
7
|
+
],
|
|
8
|
+
"executed_at": "2026-10-30T04:33:38.890Z",
|
|
9
|
+
"executor": "lead",
|
|
10
|
+
"task_id": "pre-release-2090-1793334046781",
|
|
11
|
+
"requirement": "v2.0.9: P2P reliability (ACK/RTT/window), transport abstraction + race/scheduler, iroh sidecar contract, xfer router/ref v3, fleet diagnostics, status bar",
|
|
12
|
+
"result": {
|
|
13
|
+
"outcome": "ok",
|
|
14
|
+
"assertions": {
|
|
15
|
+
"p2p_reliability": "p2p-transport 28/28; RTT estimator 3/3; benchmark 4 MiB loopback 15.07 MiB/s",
|
|
16
|
+
"transport_abstract": "transport 3/3, race 4/4, scheduler 4/4, discovery 3/3",
|
|
17
|
+
"iroh_sidecar": "fake-sidecar contract 4/4 (real binary pending infra)",
|
|
18
|
+
"xfer": "channel 2/2, router 2/2, recovery 2/14 combined, ref-v3 4/4",
|
|
19
|
+
"release": "preflight to be recorded before tag",
|
|
20
|
+
"preflight": "GREEN: 16 pass, 0 fail, 1 host-only UNVERIFIABLE",
|
|
21
|
+
"build": "dist/twinsearth-w2m-dsh-plugin-2.0.9.tgz sha256 dee553dc10c3a26107803517cb5a0f6bc010b31c70fe2e4e7a74371fc975aac7"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# ADR 0002: P2P 传输路线(iroh 优先 + 多方案并行)
|
|
2
|
+
|
|
3
|
+
状态:Accepted(2026-10-30)
|
|
4
|
+
关联:ADR 0001(CRDT)、TRANSFER-LAYER.md、TEST-PLAN-JOINT-FLEET-2.0.8.md
|
|
5
|
+
|
|
6
|
+
## 决策
|
|
7
|
+
|
|
8
|
+
1. **传输抽象先行**:定义 `P2PTransport`(start/stop/send/onMessage/paths/diagnostics),
|
|
9
|
+
现有 UDP 实现为 `udp-v1`,iroh 为 `iroh-v1`,libp2p 仅作候选发现。
|
|
10
|
+
2. **iroh 优先,但不阻塞 UDP**:双方都声明 `p2p.transports` 时并行起跑,首个完成
|
|
11
|
+
加密握手 + 首帧 ACK 的路径胜出;总预算 ≤3s;失败具名,不静默回退。
|
|
12
|
+
3. **iroh 以 sidecar 集成**:不把原生 addon 加载进 Electron 主进程;子进程 IPC,
|
|
13
|
+
失败/超时可单独回滚;默认分发仍可只带 UDP。
|
|
14
|
+
4. **自建 iroh-relay(TLS 域名 + 80/443 + ACME)**:作为可选基础设施;
|
|
15
|
+
不复用 8787 relay,不修改 relay 2.0.5。
|
|
16
|
+
5. **中继语义边界**:允许 DERP 式**密文转发**;relay 不得解密、不得落盘、
|
|
17
|
+
不得记录内容;仅保留必要的连接元数据与速率限制。
|
|
18
|
+
6. **平台范围**:Apple Silicon macOS 为唯一 macOS 目标;不支持 Intel Mac;
|
|
19
|
+
不因 Intel 预编译缺失而阻塞 iroh 路线。
|
|
20
|
+
7. **身份**:iroh `EndpointId`(Ed25519)与现有 `device.key`(X25519)独立派生:
|
|
21
|
+
`hkdf(seed, 'iroh-ed25519')`;通过 offer 的 `p2p.iroh_ids` 交换,relay 不改协议。
|
|
22
|
+
8. **数据面与文件层解耦**:iroh/UDP 只替换传输;`xfer.want/chunk`、Merkle、
|
|
23
|
+
ArtifactRef 语义保持不变。
|
|
24
|
+
|
|
25
|
+
## 立即优先级(在 iroh 之前)
|
|
26
|
+
|
|
27
|
+
- P0-a:chunk 帧接入 `P2PChannel`,不再裸 `dgram.send`;
|
|
28
|
+
- P0-b:`onAck` 触发 `pump()`,窗口随 ACK/BDP 推进(当前 0.12 MiB/s 的结构性上限);
|
|
29
|
+
- P0-c:`verifyRefV2` 自洽校验 + 统一两套 v2 ref;
|
|
30
|
+
- P1:SHA-256 Merkle 树(逐块证明,作为多源准入条件);
|
|
31
|
+
- 之后才是 iroh sidecar 时间盒。
|
|
32
|
+
|
|
33
|
+
## 验收
|
|
34
|
+
|
|
35
|
+
| 指标 | 目标 |
|
|
36
|
+
|---|---|
|
|
37
|
+
| 加密覆盖率 | 同版本、双方有 key:100% |
|
|
38
|
+
| 跨机直连率 | 同 LAN ≥90%,跨网 ≥70% |
|
|
39
|
+
| 首帧时延 p95 | 直连 <300ms |
|
|
40
|
+
| 中继边界 | relay 无明文、无落盘、无内容日志 |
|
|
41
|
+
| 回滚 | `p2p.transports=['udp']` 即回退,无需重装 |
|
|
42
|
+
| 平台 | macOS arm64 + Windows x64 通过;Intel Mac 明确不支持 |
|
|
43
|
+
|
|
44
|
+
## 方案定位(冻结)
|
|
45
|
+
|
|
46
|
+
| 方案 | 定位 | 优势 | 短板 | 是否进入数据面 |
|
|
47
|
+
|---|---|---|---|---|
|
|
48
|
+
| **iroh** | 首选、高打洞成功率 | QUIC 原生打洞、DERP 回落、路径选择、加密/重传内建 | 需 sidecar + 自建 TLS relay;JS 绑定/原生二进制 | ✅ 是 |
|
|
49
|
+
| **现有 UDP** | 默认兜底、零新增依赖 | 已有加密栈、wire 兼容、无新进程 | 可靠性仍缺 RTT 采样/拥塞控制/PMTU | ✅ 是 |
|
|
50
|
+
| **libp2p** | 可选“全家桶”参照 | 模块化、DHT 发现、多传输 | 打洞率约 70%、依赖重、复杂度高 | ❌ 否,仅发现层 |
|
|
51
|
+
|
|
52
|
+
规则:
|
|
53
|
+
|
|
54
|
+
1. 数据面只允许 `iroh` 与 `udp`;`libp2p` 不得接管 send/ACK/加密;
|
|
55
|
+
2. libp2p 只作为 `discovery` provider(DHT/mDNS)产出候选,候选仍需 relay/offer 身份校验;
|
|
56
|
+
3. 未声明 iroh 的对端只走 UDP,行为与 v2.0.8 一致;
|
|
57
|
+
4. 竞速失败返回 `ALL_TRANSPORTS_FAILED`,数据面不回落 relay;
|
|
58
|
+
5. 发现层依赖放 sidecar,服务端 `dependencies` 保持为空;
|
|
59
|
+
6. DHT 记录必须签名,失败丢弃并记 `DHT_RECORD_INVALID`。
|
|
60
|
+
|
|
61
|
+
## 风险
|
|
62
|
+
|
|
63
|
+
- iroh JS 绑定滞后(npm 1.2.0 vs 上游 1.4.1):sidecar 锁版本;
|
|
64
|
+
- 自建 relay 的域名/证书/CN→JP RTT:上线前实测;
|
|
65
|
+
- sidecar 崩溃/升级:独立进程 + 健康检查 + 自动回退 UDP;
|
|
66
|
+
- 多源投毒:Merkle 未验收前禁止开多源;
|
|
67
|
+
- 中继流量合规:只转发密文、限速、不记内容,写入运维文档。
|