拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Claudian Collab 私有云 Bootstrap:八阶段绑定状态机、持久化 Host 围栏与失败即恢复的设计解析

Claudian Collab 私有云 Bootstrap八阶段绑定状态机、持久化 Host 围栏与失败即恢复的设计解析【免费下载链接】claudianAn Obsidian plugin that embeds Claude Code/Codex as an AI collaborator in your vault项目地址: https://gitcode.com/GitHub_Trending/cl/claudian本文以 Claudian一个把 Claude Code/Codex 嵌入 Obsidian 知识库的插件Collab 协作子系统中的私有云 Bootstrap 模块为核心完整解析 bootstrap 模块规约 定义的职责边界、八阶段绑定生命周期、持久化转换记录的存储与单调性保证、former-Host 停止围栏、双成员就绪报告以及激活后“只前进不回头”的恢复语义。读完后你可以理解该模块如何把一个局域网LAN权威项目安全切换到云权威哪些状态必须落盘、哪些操作失败即封禁项目、恢复路径为什么保证不会回滚 LAN 权威。模块定位私有云 Bootstrap 只做什么、绝不做什么bootstrap 模块的第一条规约划清了职责边界该作用域只拥有以下能力——保留的私有双客户端 readiness/report 固定夹具fixtureformer-Host源主机停止围栏stop fence开发环境的激活请求与重放development activation request/replay客户端本地的绑定转换client-local binding transition。而生产权威转移、语义检查点捕获/导入、转移声明claims、源端放弃source relinquishment、目标代际target generation与终态响应器全部属于 authority-transfer 模块并且“绝不允许调用或包装本模块”。这是一个严格的单向依赖约束生产路径永远不依赖 bootstrap 的私有能力bootstrap 也不会反过来侵入生产权威转移。从源码结构看这个边界体现在模块内只有“development bootstrap”命名空间的实现CloudBootstrapCoordinator.ts 面向的DevelopmentBootstrapCloudPort接口方法activate/begin/cancel/get/report/upload全部对应claudian-collab/protocol协议包中的DevelopmentBootstrap*请求类型每个响应都经过对应 operation 的 codec 解码decodeStatus防止服务端返回结构污染本地状态机。转换记录唯一的阶段权威规约指出“一条转换记录是唯一的阶段权威”。在 CloudBootstrapTransitionRecord.ts 中这个“唯一权威”被实现为一张严格解码的 JSON 记录当前 schema 版本为CLOUD_BOOTSTRAP_TRANSITION_SCHEMA_VERSION 2第 31 行。八阶段生命周期阶段集合是冻结常量第 33–42 行与规约逐字一致export const CLOUD_BOOTSTRAP_TRANSITION_PHASES Object.freeze([ intent, readiness-confirmed, origin-rotated, cloud-verified, membership-replaced, index-repaired, lan-authority-retired, fence-terminal, ] as const);推进阶段只有一个入口advanceCloudBootstrapTransitionPhase第 582–612 行它强制三条规则attempt 必须已激活current.attemptState ! activated时直接抛错即本地绑定阶段只属于“云端已激活”之后严格单步前进nextIndex ! currentIndex 1即拒绝不存在跳阶段或回退终态围栏前置条件进入fence-terminal要求 fence 处于host-stopped或not-applicable否则抛错。CloudBootstrapBindingFinalizer中的NEXT_PHASE映射表CloudBootstrapBindingFinalizer.ts 第 32–40 行与上述阶段序列一一对应finalize主循环在每一轮先verifyActivation复核激活结果再执行当前阶段对应的本地副作用最后才推进阶段并持久化——这是规约中“激活后的恢复只把绑定阶段向前驱动”的具体实现。记录的字段与不变量CloudBootstrapTransitionRecord接口第 70–105 行携带attemptId/attemptStatepending|activated|cancelled与activationResult含activationOperationId、placementGeneration、activatedAtmanifest与manifestSha256对 manifest 的规范化 JSON 做 SHA-256见第 221–227 行oldAuthority旧 LAN 端点、Git URL、CA 指纹、源 Host 成员 ID与newAuthority云端serverUrl、gitRemoteUrl、绑定/线协议版本repositoryIdentitymainOid、personalRefOid、objectFormat为sha1/sha256fenceHost 围栏见下节、terminalCleanupCompleted、ownerInstallationKeyv2 新增标记恢复所有权。解码函数decodeCloudBootstrapTransitionRecord第 291 行起执行一组“不可能状态”校验其中值得注意的有developmentActorId必须等于memberId——这是规约“actor-bound report”报告必须绑定发起成员在记录层的强制manifestSha256必须与重新计算值一致且oldAuthority的 CA 指纹、repositoryIdentity的各 OID 必须与 manifest 完全吻合cancelled状态只允许 fence 为released-before-activation或not-applicablefence-terminal阶段与fence.state active互斥terminalCleanupCompleted为真时 attempt 不能仍处于pending。持久化存储目录 fsync、单调性检查与损坏即封禁CloudBootstrapTransitionStore.ts 实现了规约中“转换目录及其父目录条目持久同步后才算返回”的全部细节路径与限额活动记录位于.claudian/collab/cloud-bootstrap-transitions/{projectId}.json已取消的历史归档在.claudian/collab/cloud-bootstrap-transition-history/{projectId}/{attemptId}.json单条记录序列化后不得超过MAX_TRANSITION_BYTES 128 * 1024第 25–27 行。独占创建 原子写create使用createCollabFileExclusively文件模式0o600目录0o700save使用writeCollabFileAtomically写后调用syncTransitionStorage()——它连续对转换目录与.claudian/collab父目录做syncCollabVaultDirectoryDurably第 303–306 行。任何一层目录 fsync 失败都会以operation-failed错误向上抛即规约所说的“directory-sync failure fails closed”。单调性守卫assertMonotonic第 91–118 行在每次save前校验不可变身份字段immutableIdentity含 manifest、双端 authority、仓库身份等不得变化阶段索引不得倒退attempt 状态只允许pending → activated/cancelledfence 状态只允许active → host-stopped/released-before-activation与host-stopped → released-before-activation/terminalupdatedAt不得回退。损坏即封禁list()启动目录枚举对超大或损坏的记录不抛错而是把项目 ID 收进blockedProjectIds并置retryRequired读失败同样封禁并触发重试。被blockedLifecycleProjectIds封禁的项目inspectLifecycleOwner会返回nonterminal——即它作为“非终态生命周期所有者”阻止普通项目工作继续。这正是规约“不可读、超大或损坏的记录既挂起普通项目工作也让 Host 启动以失败关闭”的落点。取消归档只有cancelled且terminalCleanupCompleted的记录才能被archiveCancelled移入 history 目录之后才允许用新的 pending 记录替换路径上的活动记录——对应规约“只有带该检查点的取消记录才可归档替换”。Former-Host 停止围栏失败关闭的双重挂起规约要求“在源 Host 开始 bootstrap 之前持久化 Host 围栏以及 token 挂起的项目准入和工作会话”。实现分布在两个文件CloudBootstrapLocalFence.ts 的closeAndDrain第 61–76 行按固定顺序执行先suspendProjectAdmission挂起项目准入再suspendProject挂起工作会话挂起失败则回滚准入挂起然后drainAdmittedOperations排空已准入操作最后把项目标记为 quiesced。恢复路径resumeSuspendedProject第 86–101 行体现了规约中最微妙的一条补偿规则先恢复工作会话若随后准入恢复失败则立即用一对新的挂起替换并保留再抛出durable-progress-recovery-requiredCLOUD_BOOTSTRAP_ADMISSION_RESUME_FAILED_REASON——“重试永远不会使用陈旧 token”。CloudBootstrapCoordinator.ts 的stopFormerHost第 329–354 行在closeAndDrain之后调用formerHost.stopAndDrain并把返回证据逐项断言为autoStartDisabled true resourcesDrained true routeUnregistered true任何一项缺失都以cloud-bootstrap-host-stop-incomplete失败关闭成功后markCloudBootstrapHostStopped把 fence 推进到host-stopped并持久化。围栏对启动路径的约束是全局的。在组合根 ClaudianCollabService.ts第 377 行附近中LanHostCoordinator的runWithProjectStartGuard被包进cloudBootstrapTransitions.runWithLanHostStartGuard。该守卫Store 第 195–217 行的语义是只要存在 fence 为active/host-stopped/terminal且本安装是恢复所有者的记录任何启动尝试显式启动、恢复、项目创建、host-transfer 恢复都会抛cloud-bootstrap-host-fence-active而遗留的无主记录ownerInstallationKey undefined则以cloud-bootstrap-legacy-owner-missing要求恢复。这就是规约“单一LanHostCoordinator.startProject权威把持久化转换守卫应用到每一个调用方”的实现证据。另外两点与规约一致工作会话挂起“自行完成 close 和 drain”bootstrap 不得终态 drain 被挂起的项目只有“持久化观察到的激活前取消”才允许恢复那对精确的挂起 token且不会自动启动 LAN见cancel后settleLocalTerminal中resumeAfterCancellation的调用链。双成员就绪报告各自的 actor-bound 证据规约规定“两个成员提交独立的 actor-bound 报告”并给出上传黑名单任何路径都不得上传 SQLite、凭据、CA 材料、项目目录归档、未发布文件、本地-only 提交或私有草稿。Coordinator 侧的实现印证了这条黑名单的“正向白名单”设计collectReport第 356–396 行构造的DevelopmentBootstrapReport只包含clientReadiness由CloudBootstrapReadinessCollector采集、manifest 的comparison段、报告者成员 ID、观察到的个人 ref OID源 Host 额外附加hostStopAttestationfence ID、stoppedAt、manifestSha256 等停止证据且只有 fence 为host-stopped时才允许签发——“源 Host 不能替另一个成员背书”。报告先经decodeDevelopmentBootstrapReport解码再以submitDevelopmentBootstrapReport提交assertActorMatchesMember强制developmentActorId memberId。规约强调“quiesced 准入只证明停止了新的项目工作”就绪检查仍必须巡检所有持久化生命周期所有者publication操作非空、Manager-responsibility 回执处于offered/acknowledged都视为非终态。Store 的inspectLifecycleOwner第 180–193 行正是这类巡检端口之一把本地转换记录自身也归入“absent/nonterminal/terminal”三类判定。源 Host 激活主流程捕获、上传、激活与恢复CloudBootstrapCoordinator.startFormerHost第 171–200 行串起完整链路捕获 manifestsource.captureManifest(projectId)随后校验 manifest 的projectId/sourceHostMemberId与输入一致创建转换记录createTransition先localIdentity.load加载本地 LAN 权威身份交叉校验 CA 指纹、成员 ID、以及“fenceId 是否存在 ⇔ 是否拥有权威”的等价关系再落盘记录。若创建失败discardBundle(manifest)立即丢弃 bundle——对应规约“捕获中、无主、已取消或已激活的产物经唯一 intent 所有者丢弃”停止 former Host上节围栏驱动激活driveFormerHost第 398–451 行按序执行begin→ 若服务端状态未含本成员则report→ 若bundleState missing则以application/x-git-bundle流式upload携带byteCount与sha256→ 仅当state ready时调用activate。服务端返回recovery-required/rejected时抛出durable-progress-recovery-required。参与方非源 Host走submitParticipant先断言自己不是源 Host创建记录closeAndDrain后采集并直接提交报告。recoverProject第 222–263 行是幂等的恢复入口cancelled/activated状态走本地终态结算fence 仍active先补做停止随后拉取远端 attempt 状态源 Host 在远端不存在记录时重新驱动begin否则补交未含的参与者报告。规约中“步骤 5 可能在云端已激活、双端仍持有本地转换意图时完成终态绑定等待步骤 6 的快照与 upload-pack”描述的正是这种“远端先行、本地收尾”的窗口由settleLocalTerminal统一收口丢弃 bundle、取消则恢复挂起 / 激活则执行binding.finalize并completeAfterActivation最后markCloudBootstrapTerminalCleanupCompleted打上检查点。绑定收尾membership-replaced 与 lan-authority-retired 的原子性CloudBootstrapBindingFinalizer.ts 的finalize主循环第 49–81 行把每一阶段的“效果执行 阶段推进 持久化”绑成一个不可分割的序列并且每一轮先verifyActivation复核进入index-repaired和lan-authority-retired阶段前额外执行revalidateCloudBindingverifyCloud→replaceMembership→repairIndex——对应规约“在安静之后、第一个云操作之前重新验证完整捕获的权威与 Git-ref 快照”membership-replaced阶段执行replaceMembership从每个权威有效成员重建并安装严格带标签的云端成员身份文件index-repaired执行repairIndex——对应规约“该阶段原子安装成员身份并是适配器选择边界独立的项目索引随后重建两个文件互不复制阶段、互不隐藏无关项目”lan-authority-retired只移动 former Host 的精确无权威目录效果由组合层注入的effects.retireLanAuthority完成另一客户端记录为 no-op保留数据是惰性诊断态永不打开、永不自动启动、也绝不作为回滚权威。fence-terminal时围栏状态被advanceCloudBootstrapTransitionPhase原子置为terminal随后markCloudBootstrapTerminalCleanupCompleted要求“已激活且阶段为fence-terminal”才允许落检查点CloudBootstrapTransitionRecord.ts 第 563–580 行与规约“激活恢复把绑定阶段向前驱动、仅在云成员身份权威后重开被挂起项目、再检查点化终态清理”的次序完全一致。启动目录、后台恢复与重试策略CloudBootstrapService.ts 是模块的编排层本地恢复屏障prepareLocalRecovery先transitions.list()枚举全部有效转换记录把所有“不确定”项目blockedProjectIds 本安装拥有的非终态记录逐一fenceUncertainProject任何围栏失败整体以cloud-bootstrap-local-recovery-fence-failed失败关闭并调度目录重试。规约的“启动在组合根发布 feature 服务之前目录化每个有效的项目键转换文件并围栏所有损坏或终态不完整的项目”即此屏障已终态完成的激活/取消记录不重复围栏terminalCleanupCompleted直接跳过。后台工件恢复屏障之后才调用recoverLocalArtifacts规约中“工件与远端转换恢复保持为该屏障之后的后台工作”。指数退避重试目录级与项目级重试共用delayMs min(1000 * 2^(n-1), 30000)第 238、311 行任何pending结果或异常都会#requestRetryclose()时中断全部 AbortController 并取消挂起重试保证插件退出干净。恢复只前进recoverRecord中每条记录都先assertRecoveryOwner#assertActorBinding规约要求恢复时“重读精确的云 attempt并在每个激活后阶段之前匹配其激活操作、放置代际、激活时间戳、项目、manifest 与 attempt 身份”这些匹配由observeCloudBootstrapAttemptStatusCloudBootstrapTransitionRecord.ts 第 635–682 行的attemptId/projectId/manifestSha256一致性断言以及activationPhase completed、fence 必须已host-stopped/not-applicable的激活完整性校验共同保证。激活后恢复“只向前或保持可见的 pending”cancel对已激活记录直接抛cloud-bootstrap-already-activated不存在恢复 LAN 权威或清除终态围栏的路径。云端成员身份的字段白名单规约最后一条对云端成员身份给出了精确的字段白名单可从newAuthority的强制解码中逐条对照serverUrl必须是https协议的规范 origincanonicalCloudOrigingitRemoteUrl必须严格等于cloudProjectGitRemoteUrl(serverUrl, projectId)推导出的地址第 376 行即“派生 Git URL”bindingVersion/wireVersion必须等于协议包的COLLAB_CLOUD_BINDING_VERSION/COLLAB_PROTOCOL_VERSION记录中的developmentActorId即开发 actor ID。而oldAuthorityLAN 端点、CA 指纹等只留在本地转换记录里不进入云端成员身份——“不含活动 LAN 凭据、CA、Host 所有权或恢复阶段”由此在解码层被结构性保证。同时整个流程通过保留本地 bundle 与“只上传 bundle 流”的设计全程保住了未发布文件、本地提交与私有草稿的可重建性。小结bootstrap 模块的工程质量集中体现为三件事单一事实源一条转换记录 八阶段冻结序列、失败即关闭目录 fsync、围栏守卫、损坏封禁、单调性断言全部 fail-closed、恢复即前进激活后无回滚、取消只补偿、重试带指数退避直至终态检查点。如果你要继续深入建议按以下顺序阅读规约与实现对照AGENTS.md → CloudBootstrapTransitionRecord.ts → CloudBootstrapTransitionStore.ts协调与编排CloudBootstrapCoordinator.ts → CloudBootstrapService.ts → CloudBootstrapBindingFinalizer.ts围栏与组合装配CloudBootstrapLocalFence.ts、ClaudianCollabService.tsrunWithLanHostStartGuard装配处、集成测试 FormerHostFence.test.ts。【免费下载链接】claudianAn Obsidian plugin that embeds Claude Code/Codex as an AI collaborator in your vault项目地址: https://gitcode.com/GitHub_Trending/cl/claudian创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门