2b: 退订交接(继任者全量 ack 门禁 + 本地彻底清理,无 tombstone) - #51
Merged
Merged
Conversation
POLICY-INVARIANTS:namespace_handoff 审计行 + 横切不变量 10(无 tombstone、__policy__ 保留、全量 ack 门禁复用既有 ack、验前不删+幂等续跑、成员闸门不退化为 legacy、force 仅本地如实记录)。 SEALING §3 事件类型 + 2b 语义;§4 退订交接标记已做(重订阅恢复留 2c)。
grantPolicy:NAMESPACE_HANDOFF_EVENT + NamespaceHandoffRecord(不参与推导)。 SyncManager.forgetNamespace:清理后丢弃该分区本地水位/ack(不产生事件)。 Mebular.planNamespaceHandoff(复用 getPendingEvents,排除继任者自证事件)/ leaveNamespace(验前不删 → 成员注销+交接记录 → 图外意图 → 物理删除 → 清水位 → 去意图;force 如实记录;幂等续跑;__policy__ 保护)。 BREAKING CHANGE: 退订方本地彻底删除该分区数据(无 tombstone)。
handoff.test:覆盖足清理+policy保留+B/C不丢、覆盖不足中止、force、中断续跑无 tombstone、成员闸门仍在、__policy__ 保护。 grant.test:fleet planHandoff/leaveNamespace/doctor 交接状态。
…态 + ONBOARDING §12 onboard:planHandoff/leaveNamespace。cli:leave 子命令(force 仅本地)。 doctor:交接状态(存在图外意图 → FAIL 提示续跑)。
CLI 级:A/B 派活→B 全量 ack→leave 成功(A 数据消失、__policy__ 含 handoff、B exec 不变、无 tombstone);A2 未同步→leave 中止+原封不动;force 成功。verify:fleet:all 104/104。
B 执行 20/20 但 A 偶发只见到 19 条 done;本机 3× 7/7。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
2b · 退订交接(继任者全量 ack 门禁 + 本地彻底清理)
退订 = 成员资格退出(
namespace_membership(active:false))+ 本机彻底清理该分区数据;绝不产生 tombstone;默认继任者全量 ack 后才清理,门禁不过则保持原状;force仅本地 CLI 且如实记录;新增审计产物namespace_handoff(退订方签名写入__policy__)。core 语义变更,走封板纪律。关键实现(H1–H6)
planNamespaceHandoff用sync.getPendingEvents(successor)判断——退订方校验继任者已 ack 其在该分区的他人署名事件(继任者自证事件其本就拥有,排除以免误判)。不新增同步协议、不放宽快照门禁(SEALING §4 快照门禁不动)。--successor <deviceId>;且必须是该分区生效成员,否则拒绝。forgetNamespace:清 per-(peer,ns) 水位与已删事件 ack);__policy__永不清理;意图记录落图外<storagePath>.handoff.json(0600 原子写)→ 可幂等续跑。forced/缺失明细)→ 写意图 → 删除 → 清意图。fleet leave --dry-run给验证明细;doctor增交接状态(有意图 → FAIL 提示续跑)。planNamespaceHandoff/leaveNamespace+fleet leave;fleet 只调公共 API。主张 → 证据
2b ①(3 端 jest)+verify:fleet:handoffCLI2b ②+ CLI「A2 未同步→中止,数据不变」forced:true如实记录2b ③+ CLI force2b ④(注入 deleteEvent 抛错)2b ⑤+ CLI「members.active」2b ⑤__policy__保护2b 保留分区保护+ CLI「含 namespace_handoff」verify:fleet:all104/104红 → 绿(断言原文)
purgeNamespace不删事件2b ① 数据消失✕ Expected 0 Received 3→ 还原 ✓if (!force)→if (false)2b ② 覆盖不足→中止✕(不该清理却清理)→ 还原 ✓verify:fleet:handoffdry-runFAIL dry-run {"ok":false,"pendingTotal":3}(15→10)→ 还原 15/15交接记录样例(
__policy__){"type":"namespace_handoff","namespace":"__policy__","author":"device-A","data":{"handoff":{ "handoffId":"<uuid>","namespace":"tasks","successor":"device-B","forced":true, "pendingCount":1,"missingAuthors":["device-A"],"issuedAt":1789736…,"note":"test"}}}跨端 E2E 原始输出(
verify:fleet:handoff,15/15)三端(A/B/C)B、C 数据不丢由
tests/sync/handoff.test.ts ①断言(真实 InMemoryHub 同步)。SEALING / 矩阵 diff 要点
POLICY-INVARIANTS.md:新增namespace_handoff审计行(不参与推导)+ 横切不变量 10(无 tombstone、__policy__保留、全量 ack 门禁复用既有 ack、验前不删+幂等续跑、成员闸门不退化为 legacy、force 仅本地如实记录)。SEALING.md§3:事件类型加namespace_handoff+ 2b 语义 + 破坏性说明(退订方本地彻底删数据;旧节点无交接概念 → 不清理,安全);§4 退订交接标记已做,仅剩「重订阅恢复」属 2c。给 2c 的接口/语义清单(重订阅恢复需要什么)
namespace_membership(active:true)可重新在册;getNamespaceMembers(生效成员);forgetNamespace已清该分区本地水位(恢复时从零水位重建)。peerWatermarks清空后的首次拉取语义(避免把“无水位”当成“已全有”);③ 重入时的授权/成员再校验;④ tombstone-free 前提下如何区分“从未有”与“已清理”(本机可用图外标记,但不得同步)。未做项 / 风险
测试方式
npm ci && npm run build npm run test:coverage npm run verify:fleet:all node scripts/verify-fleet-handoff.mjs