阶段十:MM 公网 IP 可替换架构整改方案(2026-09-25)
计划 ID:mm-public-ip-replaceable-architecture
原计划标题:MM 公网 IP 可替换架构整改方案(2026-09-25)
阶段位置:P10(阶段十);P9 已关闭,不再实施
🗂️ 目录
- 结论摘要
- 计划状态
- 原计划基线
- 叠加式修订记录
- 决策账本
- 技术栈与架构选型
- DNS 与稳定入口
- 网络底座整改
- 控制台与告警
- 目标、成果与验收契约
- 分布式底座接入声明
- 文档库治理
- CI/CD 自动部署恢复
- 验证与放行
- 回退方案
- 未决项与需要用户决策
📌 结论摘要
计划只追加修订,不重建身份。 原计划的目标、根因、稳定身份、动态地址、恢复链、测试和回退继续有效;后续讨论只改变具体决策、增加工作包或标记被否决项,不覆盖原始结论。
本次修订的核心变化是把公网入口从“MM 主机 IP”提升为稳定边缘身份 edge.yohan.fun,把 SSH、DERP、运行状态、文档库和控制台态势感知纳入同一整改主线。P10-0 至 P10-8 已完成收口并归档。 P10-4 已用现场路径确认 FullCone 后直连恢复;P10-5 与 P10-6 已交付聚合接口、冷连接金丝雀和控制台拓扑;P10-7 已完成隔离切换、非法地址拒绝和回滚演练。真实生产边缘主机切换仍需第二台完整边缘、独立证书、回源和 DNS 变更窗口,作为后续运维外部前置保留,不能伪装成已经执行。
🧾 计划状态
阶段状态:已完成并归档
计划状态:已完成
当前工作包:无;P10-8 已完成
计划来源:
| 项目 | 事实 | 依据 |
|---|---|---|
| 原计划时间 | 2026-09-25 21:55:21 CST | /root/.codex/sessions/2026/09/25/rollout-2026-09-25T21-00-51-01a0d8a7-811a-7162-a902-9f80c736dc44.jsonl |
| 原计划标题 | MM 公网 IP 可替换架构整改方案(2026-09-25) |
原计划正文 H1 |
| 修订方式 | 只追加、修订受影响的章节和账本,不替换整份计划 | 用户 2026-09-26 明确纠正 |
| 当前仓库事实 | 修订前没有独立的原计划文件,只有历史完成页和聊天正文 | docs/plans/ 只读盘点 |
P9 不写成“全部完成”。已实现的脚本、Runtime 接口和 Console 代码保留;未完成的三平台 ACL、真实接入、撤销清理和故障验收转入关闭记录,不再扩展 P9。
📊 原计划基线
原计划已经确定的根因是:系统把公网 IP 当成了节点身份,而 MM 实际只是可替换的公网边缘角色。因此以下是不可被后续版本静默覆盖的基线:
| 基线项 | 原计划要求 | 本次修订状态 |
|---|---|---|
| 稳定身份 | 域名、节点角色、服务身份是稳定契约 | 保留 |
| 动态地址 | IPv4、IPv6、网关、白名单来源和健康状态属于运行时数据 | 保留并强化 |
| 配置源 | 业务源配置不得保存当前 MM 公网 IP | 保留 |
| 统一入口 | 使用稳定边缘域名承载可替换入口 | 修订为 edge.yohan.fun |
| DNS 模型 | 地址更新应集中在少数权威记录 | 修订为静态 A/AAAA 加业务 CNAME |
| 恢复链 | MM 故障时仍能从其他管理路径恢复 | 保留并拆分公网与 Tailnet 双通道 |
| 防复发 | CI、运行期巡检、last-known-good 和换 IP 演练缺一不可 | 保留并扩展为金丝雀与文档门禁 |
| mTLS | 原计划把它列为高风险入口候选 | 用户明确否决,不再实施 |
原始方案中的“不批量替换旧 IP,而是建立逻辑身份和运行时派生数据”结论继续有效。后续修订只改变实现承载方式,不改变该根因判断。
🔁 叠加式修订记录
rev.0 是 2026-09-25 原计划;rev.1 只记录后续已经确认的增量和变更。未来修订继续追加到本表,禁止用新文件替换本文件。
| 版本 | 日期 | 变更类型 | 变更内容 | 原内容处理 |
|---|---|---|---|---|
rev.0 |
2026-09-25 | 原始基线 | 逻辑身份、动态地址、端点清单、渲染器、恢复链、CI 防复发 | 保留 |
rev.1 |
2026-09-26 | 修订 | 权威边缘域名改为 edge.yohan.fun,业务域名使用 CNAME |
新增到基线,不覆盖原原则 |
rev.1 |
2026-09-26 | 明确否决 | 不实施 mTLS,不增加客户端证书门禁 | 保留候选历史,标记“被否决” |
rev.1 |
2026-09-26 | 新增 | RR、101、Home 的公网与 Tailnet SSH 双通道;DD、MM 不获得反向管理权限 | 追加到恢复工作包 |
rev.1 |
2026-09-26 | 新增 | 直连优先、DERP 为辅;MM 为 region 900,DD 规划 region 901 | 追加到网络工作包 |
rev.1 |
2026-09-26 | 新增 | 101 双层 NAT 与 FullCone 问题单独处理,不归因于 SSH ACL | 追加到路径诊断 |
rev.1 |
2026-09-26 | 新增 | P9 关闭、P10 当前、docs/** 全量 review 和自托管 Runner 验收 |
追加到文档治理 |
rev.1 |
2026-09-26 | 新增 | 控制台首页网络拓扑、链路状态、动画、筛选和移动端要求 | 追加到 Console 工作包 |
rev.1 |
2026-09-26 | 新增 | 微信 ClawBot 部署在 RR,作为交互通道;邮件仍是主告警 | 追加到通知通道 |
rev.2 |
2026-09-26 | 根因修复 | P6 临时 RR 生产部署硬禁用遗留,四个无状态服务恢复仓库变量门禁 | 保留 P6 当时边界,不改写历史事实 |
rev.2 |
2026-09-26 | 防复发 | 增加 CI 契约检查和负向回归,禁止把临时停部署硬编码为 if: ${{ false }} |
追加到部署治理 |
rev.3 |
2026-09-26 | 细化 | 为 P10-0 至 P10-8 追加依赖、任务、文件、自动化、负向回归、回退和出口账本 |
保留原有目标和原则,只增加可执行细节 |
rev.3 |
2026-09-26 | 修复 | DERP Map 删除固定 IPv4,重启恢复脚本改为解析 edge.yohan.fun,增加仓库级硬编码门禁 |
旧迁移文档只保留历史标识 |
rev.3 |
2026-09-26 | 凭据边界 | GitHub Runner 使用短期 GITHUB_TOKEN 下载 Release bundle;RR 不保存发布用长期 GitHub PAT |
101 受保护凭据存储只供管理操作,不进入仓库和 RR |
rev.4 |
2026-09-26 | 生产验收 | 提交 c0f47e7 的六个 Actions 全部成功,四个无状态服务经 101 Runner 实际发布到 RR,Docs/DERP 公网回读通过 |
P10-0 仍因控制台登录态回读未完成而保持进行中 |
rev.5 |
2026-09-26 | 文档治理 | 49f4b64 完成实施计划与完成归档分层;文档站移除私有仓库匿名 API 元数据,公开页脚改用组织入口 |
历史文档中的旧仓库链接不再作为活跃配置 |
rev.6 |
2026-09-26 | 全量审计 | 新增机器可读文档清单、分类门禁和负向测试;63a2f52 的 Guardrails 与 Docs 生产部署成功 |
审计前 110 个 Markdown,新增审计报告后 111 个;控制台认证回读仍未关闭 |
rev.7 |
2026-09-26 | 生产回读 | d42a2f6 的 Repository Guardrails 与 Docs 构建/发布全部成功;公网页面已回读 rev.6、111 个文档和审计报告 |
P10-0 仍只等待合法管理员会话下的控制台计划 iframe 回读 |
rev.8 |
2026-09-26 | 验收关闭 | 使用临时管理 API Key 换取可撤销 HttpOnly 会话,管理员身份回读通过;控制台 #docsPlans iframe 实际加载 Docs 计划页并打开 P10 详情 |
P10-0 关闭;当前工作包切换为 P10-1,不记录 Key 值 |
rev.9 |
2026-09-26 | DNS 冻结 | 权威 NS、静态 A/AAAA、业务 CNAME、证书 SAN、TTL 和四类例外已对齐;端点解析器单测进入 Repository Guardrails |
P10-1 关闭;当前工作包切换为 P10-2,现网 DNS 本轮未改 |
rev.10 |
2026-09-26 | 端点收口 | RR、MM 已安装同一解析器与 timer;DERP Map、Nginx allow、Gemini wrapper 和恢复脚本读取受控来源,负向快照与渲染漂移测试通过 | P10-2 关闭;当前工作包切换为 P10-3 |
rev.11 |
2026-09-26 | SSH 收口 | 101、Home、RR 的公网与 Tailnet 别名均通过身份回读;管理公钥指纹已登记;DD、MM 无私钥且主动连接被 publickey 拒绝 |
P10-3 关闭;当前工作包切换为 P10-4 |
rev.12 |
2026-09-26 | 路径收口 | 360T7 FullCone 生效后,101 到 RR、DD、MM、Home 均为 Tailnet 直连;Home 到 RR、101、MM 直连,到 DD 由 DERP 转直连;RR 到 Home 采用多轮采样后判为直连 | P10-4 关闭;MM 不可达时仍保留直连与独立 SSH 管理边界 |
rev.12 |
2026-09-26 | 观测收口 | 网络拓扑器新增本机 Tailscale 健康、Home 多轮采样和错误分类;RR 的 ClawBot 状态 timer 已启用,脱敏 API 返回真实 down/unbound/openclaw_not_installed |
P10-5 关闭;单次 ping 波动不再把在线节点永久标成 down |
rev.12 |
2026-09-26 | 控制台收口 | 修复 Runtime 概览失败时错误覆盖独立 ClawBot 状态的前端缺陷;新增浏览器负向回归,并保留桌面、移动、筛选、缩放和 reduced-motion 验收 | P10-6 关闭;生产部署与公网回读纳入本修订的发布验收 |
rev.12 |
2026-09-26 | 切换演练 | 在 RR 隔离目录完成候选地址渲染、重复渲染一致性、非法 Tailnet 地址拒绝、last-known-good 哈希不变和回滚校验 | P10-7 关闭;真实生产边缘切换仍等待第二完整边缘的外部前置 |
rev.12 |
2026-09-26 | 文档收口 | 更新计划状态、架构正文、节点登记、计划历史和残余风险;不改变计划身份,不创建平行计划 | P10-8 关闭;当时阶段仍进行中,后由 rev.13 完成生产回读并归档 |
rev.13 |
2026-09-26 | 完成归档 | 完成控制台生产回读、最终本地与 CI 回归、P10 原始计划原地状态校正和独立完成归档;P11 仅建立后续需求评审占位,不创建平行 P10 计划 | P10-0 至 P10-8 归档;真实第二边缘切换继续作为明确外部前置 |
🧩 决策账本
决策账本是防止“后续讨论丢失”的主记录。任何新增讨论先进入本表,再修改对应正文;没有经过确认的内容只能写为候选或未决。
| 决策项 | 当前状态 | 生效结论 | 证据或来源 |
|---|---|---|---|
| 计划身份 | 锁定 | 继续使用原计划标题和计划 ID,P10 仅作为阶段映射 | 用户 2026-09-26 纠正 |
| 边缘域名 | 已确认 | 使用 edge.yohan.fun,不绑定 MM 主机名 |
当前 DNS 与用户决策 |
| DNS 维护方式 | 已确认 | edge 使用静态 A/AAAA;业务域名使用 CNAME |
当前 DNS 实测与用户确认 |
mail.yohan.fun |
保留独立 | 邮件记录不跟随 edge | DNS 清单 |
sz.yohan.fun |
只读 | NAS 独立动态 AAAA,禁止修改或改成 edge CNAME | NAS 内网接入要求 |
www.threedogs.vip |
独立治理 | 作为 Three Dogs 正式站点入口,裸域只做跳转 | Dynamo 管理与用户确认 |
disk/ota/6844 |
暂缓 | disk 为预留;ota/6844 为个人项目,不擅自改解析 |
用户明确边界 |
| mTLS | 被否决 | 不再作为 RR 回源、Nginx 或 UFW 的补强方案 | 用户明确否决 |
| DERP | 已确认 | 直连优先、DERP 为辅;MM 故障时 MM DERP 不能兜底自身 | 用户讨论与现场路径 |
| DD DERP | 已规划 | DD 作为第二 region 候选,不新增 DERP 域名 | 用户确认的兜底方向 |
| 管理权限 | 已确认 | RR、101、Home 可主动管理;DD、MM 不新增反向权限 | SSH 权限矩阵讨论 |
| Mac mini 授权 | 暂缓 | 当前保留,不上线,不删除 | 用户确认 |
| 公网数据面 | 已确认 | 业务大流量走公网 HTTPS;Tailnet 只承载控制面和小文件 | 项目宪法与用户确认 |
| 控制台拓扑 | 已完成 | 首页提供交互式网络态势感知,后端只返回脱敏真实事实 | 用户明确要求与 Playwright 回归 |
| 微信 ClawBot | 已确认 | 部署在 RR;邮件主告警,ClawBot 仅交互 | 生产节点与 24 小时窗口约束 |
| P10 计划状态 | 已完成 | P10-0 至 P10-8 已收口并归档,计划只追加修订 | 当前权威计划、完成归档与状态源 |
| 真实边缘切换 | 外部前置 | 当前没有第二台完整公网边缘,不能修改 DNS 冒充切换成功 | P10-7 隔离演练与现场约束 |
| 文档持续更新 | 强制 | 网络、端口、DNS、SSH、DERP、服务角色变化必须同批更新文档 | 用户明确要求 |
| 无状态自动部署 | 恢复 | docs-site、console-site、status-site、api-gateway 构建成功后经 101 Runner 自动发布到 RR |
用户规则与架构部署规范 |
| 临时停部署方式 | 锁定 | 只把仓库变量 AGENTMESHOS_ENABLE_RR_PRODUCTION_DEPLOY 设为 false,禁止改工作流为永久跳过 |
P6 遗留禁用的直接教训 |
| Stateful 发布 | 保持人工 | Runtime、Auth、CLI Gateway 继续使用独立备份、迁移和回滚门禁,不随无状态服务自动升级 | 现有部署安全边界 |
| Edge 地址维护 | 锁定 | edge.yohan.fun 使用权威 DNS 静态 A/AAAA;换边缘时只更新该记录,不使用 DDNS |
当前现场解析与稳定身份要求 |
| 业务域名接入 | 锁定 | mesh/cloud/auth/console/docs/status/api/omni/nomad/ai/disk/ota/6844 使用 CNAME;www.threedogs.vip 使用跨厂商 CNAME |
2026-09-26 dig 现场事实 |
| RR 发布凭据 | 锁定 | Runner 使用当次 Run 短期令牌;RR 只接收经过 stdin 的不可变 bundle 和临时 GHCR 登录令牌 | 防止长期 PAT 再次失效后形成静默阻塞 |
| 长期管理凭据 | 受限 | 管理 PAT 只允许保存在 101 的 0600 受保护凭据文件,禁止写入仓库、文档、日志、模型上下文或 RR;过期时先做有效性二次验证并向用户索取续期凭证,不得静默改造成新的长期依赖 |
用户明确提供、续期要求与项目凭据边界 |
🧱 技术栈与架构选型
本阶段继续使用现有 Headscale、Tailscale、OpenSSH、Nginx、完整路由器、GitHub Actions、FastAPI、SQLite 和 Vanilla JavaScript,不引入第二控制面或第二前端框架。
| 领域 | 采用方案 | 未采用方案与原因 |
|---|---|---|
| 边缘寻址 | edge.yohan.fun 加业务 CNAME |
不把 MM IP 写入每个业务源配置 |
| 运行时地址 | root-only 端点快照加受控渲染 | 不允许脚本各自维护公网 IP |
| 高风险回源 | 动态来源控制加服务自身认证 | 不采用 mTLS |
| 管理网络 | 公网 SSH 与 Tailnet SSH 独立配置 | 不依赖 SSH 自动猜测地址 |
| 节点互联 | Tailscale 直连优先,DERP 失败兜底 | 不把 DERP 当作常态主路径 |
| 控制台拓扑 | 现有 Vanilla JavaScript 与 SVG/CSS | 不引入第二套图表框架 |
| 文档治理 | 单一状态源、计划注册表、CI 门禁 | 不维护平行计划文件或手工重复导航 |
🌐 DNS 与稳定入口
当前已确认的 DNS 结构如下。正式复核以域名管理台截图和解析结果为准,文档不能替代后台事实。
| 名称 | 当前模型 | 角色 | 处理边界 |
|---|---|---|---|
edge.yohan.fun |
静态 A/AAAA | 唯一可替换边缘地址身份 | 2026-09-26 现场解析为当前 MM IPv4/IPv6;它是业务域名的别名目标,不是带独立证书的用户入口 |
mesh/cloud/auth/console/docs/status/api/omni/nomad/ai/disk/ota/6844 |
CNAME edge.yohan.fun |
AgentMeshOS 与既有项目入口 | 不保存 MM 公网 IP;由权威 DNS 自动返回边缘 A/AAAA |
mail.yohan.fun |
独立 A 与邮件记录 | 邮件服务 | 不跟随 edge |
www.threedogs.vip |
CNAME edge.yohan.fun |
Three Dogs 站点正式入口 | 跨域名厂商 CNAME 合法;Dynadot 管理,解析当前已生效 |
threedogs.vip |
独立 A 记录 | 裸域跳转入口 | 权威 DNS 同时返回两条当前值;裸域不能依赖普通 CNAME 语义,不承载 WooCommerce 会话 |
sz.yohan.fun |
动态 AAAA | NAS 内网穿透 | 只读核对,禁止修改 |
disk.yohan.fun |
CNAME edge | 私人云盘预留 | 暂未启用;不纳入当前业务健康验收 |
ota.yohan.fun、6844.yohan.fun |
CNAME edge | 个人项目 | 切换时做健康检查,不纳入 AgentMeshOS 服务清单 |
CNAME 是 DNS 别名,不是 HTTP 跳转。 浏览器地址栏不会变成 edge.yohan.fun。当前维护模型是“静态权威 A/AAAA 加业务 CNAME”,不是动态 DNS;edge 换址时由维护者更新 A/AAAA,其他业务域名自动跟随。跨域名厂商 CNAME 与域名是否属于同一注册商无关,只要求记录写入权威 DNS;证书、Host 和服务路由仍按最终业务域名验收。
Nginx allow、UFW 和 SSH 不能直接保存域名规则,必须由受控解析器读取 edge.yohan.fun 后生成 IP,或读取 root-only 运行时快照和 last-known-good。sz.yohan.fun 是 NAS 自己的动态 AAAA 例外,任何切换计划都不得把它改成 edge CNAME。
🔧 网络底座整改
硬编码根除必须覆盖代码、配置、部署脚本、恢复脚本、文档示例和运行状态。活跃配置只保存逻辑端点;当前地址只存在于 root-only 运行时快照和必要的 last-known-good。
| 对象 | 整改方向 | 验收证据 |
|---|---|---|
| DERP Map | 从逻辑端点或受控快照生成 | headscale configtest 通过,无固定 MM IP |
| 重启恢复脚本 | 解析 edge,失败时使用 last-known-good |
正负向测试和重启演练通过 |
| Nginx allow 与 UFW | 由端点快照生成,不在源文件写死 | nginx -t、规则回读和非法解析拒绝 |
| SSH 配置 | 公网与 Tailnet 分成明确 Host 块 | 两条路径分别登录并回读身份 |
| Gemini 出口 | 使用逻辑端点或运行时地址 | SOCKS 出口实测 |
| 文档示例 | 当前配置使用逻辑端点,历史值加历史标识 | 链接和事实源检查通过 |
101 的多层 NAT 与路由器 FullCone 是独立问题。诊断时必须区分“公网 SSH 可达”“Tailnet 应用层可达”“Tailnet 底层直连”和“DERP 中继”四种事实,不能把 DERP 结果写成 ACL 故障。
🖥️ 控制台与告警
控制台首页必须提供真实网络态势感知,而不是只显示节点在线数量。后端只返回节点、链路、路径类型、状态、延迟、新鲜度和脱敏错误码;前端不自行猜测链路类型。
| 要求 | 固定行为 |
|---|---|
| 节点与布局 | 按公网 edge、管理节点、边缘节点、存储节点和其他节点分层 |
| 连线 | 区分公网 HTTPS、Tailnet 直连、DERP、SSH 管理和公网数据面 |
| 状态颜色 | 绿色直连健康、黄色 DERP 或降级、红色离线或断链、灰色未知或过期 |
| 数据流动 | 只在真实探测更新或状态变化时显示,不给静态链路制造虚假流量 |
| 交互 | 支持悬停、点击详情、缩放、平移和路径筛选 |
| 可访问性 | 支持移动端和 prefers-reduced-motion |
控制台 #providers 页面调整为“平台运行与通知通道”,增加 RR 微信 ClawBot 的版本、绑定、最近收发、最近错误和 24 小时回复窗口状态。ClawBot 不是主动告警通道,不能替代邮件。
冷连接金丝雀至少覆盖 DNS、TCP、TLS、固定业务端点、DERP 和 MM 出口。连续失败达到阈值才告警,恢复后发送恢复事件;key-pool.mjs 的静默异常必须改为可诊断日志,不记录任何 Key 值。
🎯 目标、成果与验收契约
本计划的目标是消除 MM 公网 IP 对系统身份和恢复路径的绑定,建立可验证、可回退、可观测的稳定边缘入口。P10-0 已通过生产可见性验收;P10-1 只冻结 DNS 与域名事实,不得在冻结前修改现网记录,P10-1 退出前也不能宣称硬编码已全部清除。
| 工作包 | 内容 | 退出条件 |
|---|---|---|
P10-0 |
计划身份、文档库、计划板、状态机、CI/CD 发布门禁和生产可见性治理 | 所有计划分类唯一,P9 关闭,P10 状态一致,四个无状态工作流恢复受控自动部署,生产 docs-site 已部署且控制台计划模块回读可见 |
P10-1 |
DNS、CNAME、独立域名和例外清单冻结(已完成) | 域名表与后台截图一致,业务入口不依赖 MM IP |
P10-2 |
端点快照、渲染器和硬编码根除(已完成) | 正负向测试通过,活跃配置无固定 MM IP |
P10-3 |
SSH 双通道和权限矩阵收口(已完成) | RR、101、Home、DD、MM 逐项验证,越权入口不存在 |
P10-4 |
直连、DERP 900/901 与 101 路由器路径(已完成) | 直连和降级分类真实可测,MM 不可达边界明确 |
P10-5 |
网关拓扑接口、金丝雀和告警(已完成) | 故障可触发,恢复可关闭,敏感字段不返回 |
P10-6 |
控制台首页和通道状态(已完成) | 桌面、移动端、颜色、动画和交互验收通过 |
P10-7 |
边缘切换与完整回退演练(已完成可执行范围) | 隔离切换、非法输入拒绝、last-known-good 保持和回滚通过;真实第二边缘生产切换保留为外部前置 |
P10-8 |
架构正文、历史归档和残余风险收口(已完成) | 文档、GitHub、CI、镜像和线上状态一致 |
计划评审期间可以更新计划文件、状态源和导航;不得修改 DNS、MM、RR、DD、NAS、路由器、生产配置或恢复脚本。
📋 工作包执行账本
本节是 P10 的执行细则。每个工作包只有在自动化检查、负向回归、真实节点验收和回退点全部具备后才能关闭;局部成功、单页 200 或计划文字更新都不算完成。
P10-0 计划与发布治理
状态:已完成。
目标:先把计划身份、文档库、计划板、状态机和无状态自动部署恢复为一致、可审计、可重复的状态。该工作包不修改 DNS、Nginx、UFW、Headscale DERP Map、路由器或生产恢复脚本。
前置依赖:无;P10-0 已于 2026-09-26 完成生产可见性与控制台认证回读,P10-1 已满足前置条件。
具体任务:
- 对
docs/**做全量事实比对,把当前、进行中、完成归档、关闭、历史值和被否决候选分别归类。 - 保持唯一权威计划为本文件,不创建平行计划;更新
state.json、in-progress.md、backlog.md、导航和归档清单时只改真实状态。 - 恢复四个无状态工作流的仓库变量门禁,禁止再提交
if: ${{ false }}永久跳过。 - 把 Release bundle 下载移到 GitHub Runner,使用当次 Run 的短期令牌;RR 控制器只通过 stdin 接收 bundle 和临时 GHCR 登录令牌。
- 生产部署
docs-site后,从公网和控制台计划模块回读 P10 当前、P9 已关闭和正文可访问。
| 边界 | 文件或接口 | 责任节点 |
|---|---|---|
| 计划机器状态 | docs/plans/state.json、agentmeshos-plan-state-check.py |
101 |
| 计划正文与导航 | docs/plans/**、docs/architecture/** |
101 |
| 无状态发布门禁 | 四个 *-docker.yml、reusable-rr-deploy.yml |
101 Runner 与 RR |
| 生产可见性 | docs-site、控制台实施计划嵌入页 |
RR 与公网 |
| 检查 | 当前结果 | 关闭要求 |
|---|---|---|
| 计划状态检查 | 通过,P10 为唯一当前阶段 | 每次文档提交继续通过 |
| 部署门禁契约 | 通过,硬编码禁用会被拒绝 | 四个工作流不再被永久跳过 |
| Release 传输 | 提交 c0f47e7 的 Docs/Console/Status/API 四个 deploy-production / deploy 均成功,下载 bundle、构建 transport、RR 部署验证和清理步骤全部通过 |
后续发布继续使用短期令牌和 stdin transport,不恢复 RR 长期 PAT |
| Actions 结果 | 提交 c0f47e7 的六个 Actions 全部成功;DERP 首次 BuildKit graceful_stop 重跑后完整通过 |
后续若出现同类并发失败,应先定位 Runner/BuildKit 资源竞争,不反复盲目重跑 |
| 公网回读 | docs.yohan.fun/healthz、/plans/ 和 P10 详情页均返回 200;P10 页面包含工作包账本和 P10-8,不再包含旧 MM IP |
后续文档发布后继续回读当前阶段和正文版本 |
| 文档清单 | document-inventory.json 唯一登记 111 个 Markdown;90 个进入公开导航,21 个为内部或证据材料;Docs 生产页已回读 |
新增、删除或改公开性后必须更新清单并重新通过门禁 |
63a2f52 Actions |
Repository Guardrails 成功;Docs 构建与 deploy-production / deploy 均成功 |
包含 CloudCLI 交接材料的提交已经完成生产部署 |
d42a2f6 Actions |
Repository Guardrails 成功;Docs 构建与 deploy-production / deploy 均成功 |
文档清单门禁已进入正式 Guardrails,审计报告已发布 |
| DNS 冻结输入 | edge 静态 A/AAAA;13 个 AgentMeshOS 业务名和 www.threedogs.vip 为 CNAME;mail、sz、裸域保持例外 |
P10-1 以域名后台截图和现场 dig 双重核对后冻结 |
| 控制台认证回读 | 2026-09-26 12:47 CST 使用临时管理 API Key 换取 HttpOnly 会话;页面显示“API Key 管理员身份 · 管理员”,#docsPlans iframe 实际加载 https://docs.yohan.fun/plans/,点击“P10 详细计划”后进入 https://docs.yohan.fun/plans/phase-10-mm-public-ip-replaceable-architecture/;正文断言包含 P10-0、P10-8、rev.7、111 个 和 Repository Guardrails |
P10-0 关闭条件已满足;Key 值不写入仓库、文件、日志或回复,由用户随后撤销 |
| 管理凭据 | 新管理 PAT 已保存在 101 的 0600 受保护文件,权限与账户有效性回读通过 |
后续 401 先分离验证失败原因,再向用户索取续期凭证;值不进入仓库、回复、日志或 RR |
负向回归:P9 不得重新进入当前计划;旧 IP 或当前 MM IP 写入活跃配置必须失败;工作流出现 if: ${{ false }} 必须失败;RR 配置出现长期发布 PAT 依赖必须失败;空 bundle、错误服务名、错误 SHA 和错误摘要必须被拒绝。
回退:计划文档按追加修正回退;自动部署可通过仓库变量暂停;文档镜像回退到上一已验证 SHA;本工作包不涉及 DNS 或边缘网络回退。
退出条件:本地全套测试、严格 MkDocs、GitHub Actions、RR 容器健康、公网回读和控制台回读全部通过;RR 不再保存发布所需的长期 GitHub 凭据。
残余风险:Stateful 服务仍保持人工发布;控制台计划模块只证明文档可见,不证明后续网络整改已完成。
P10-1 DNS 与域名清单
状态:已完成。
目标:冻结每个域名的权威模型,区分静态 A/AAAA、业务 CNAME、邮件独立记录、NAS 动态 AAAA 和裸域例外。当前 edge.yohan.fun 使用静态 A/AAAA,不使用 DDNS;业务域名只保存 CNAME。
前置依赖:P10-0 已完成;已收到域名导出表和管理台截图,继续补齐需要冻结的记录视图;确认 yohan.fun 与 threedogs.vip 的权威 DNS 提供商和 TTL。
具体任务:
- 把
dig、权威后台截图、证书 SAN 和服务清单逐项对齐,记录域名、记录类型、目标、TTL、证书、回源和负责人。 - 确认
mesh/cloud/auth/console/docs/status/api/omni/nomad/ai/disk/ota/6844全部只通过 CNAME 获得边缘地址。 - 保留
mail.yohan.fun的独立 A 和邮件记录,不跟随 edge。 - 保留
sz.yohan.fun的动态 AAAA,只读核对,禁止改为 edge CNAME。 - 确认
www.threedogs.vip使用跨厂商 CNAME 到edge.yohan.fun;裸域只保留独立 A 和 301,不使用普通 apex CNAME。
冻结结果如下。TTL 以 2026-09-26 现场 dig 回读为准;权威 DNS 配置 TTL 为约 300 至 600 秒,记录切换前仍须预留旧 TTL 的缓存窗口。
| 名称或区域 | 权威与记录模型 | 现场事实 | 维护边界 |
|---|---|---|---|
yohan.fun |
阿里云 DNS ns1.alidns.com、ns2.alidns.com |
edge 为静态 A/AAAA,配置 TTL 约 600 秒;业务名返回 CNAME edge.yohan.fun |
换边缘只更新 edge A/AAAA,不逐条改业务 CNAME |
| AgentMeshOS 业务名 | 阿里云 DNS 下 13 个 CNAME | mesh/cloud/auth/console/docs/status/api/omni/nomad/ai/disk/ota/6844 均返回 CNAME edge.yohan.fun |
disk 仍为预留,ota/6844 为个人项目;不纳入核心服务健康成功条件 |
mail.yohan.fun |
阿里云 DNS 独立记录 | 独立 A 为主节点邮件地址;SPF 为 v=spf1 mx -all,DMARC 为 p=none |
不跟随 edge;后续邮件安全提升单独评估 |
threedogs.vip |
Dynadot 管理、Dyna NS | 裸域为独立 A,当前 TTL 300 秒 | 只作 301 跳转入口,不承载 WooCommerce 会话 |
www.threedogs.vip |
Dynadot 管理、Dyna NS | CNAME edge.yohan.fun,现场 TTL 约 300 秒;证书 SAN 覆盖裸域和 www |
Three Dogs 正式站点入口;跨厂商 CNAME 合法 |
sz.yohan.fun |
用户导出的旧 AAAA 与现场动态 AAAA 不一致 | 现场返回动态 AAAA,需要 NAS 侧 DDNS 维持 | 只读例外,禁止修改或改成 edge CNAME |
证书冻结结果以 2026-09-26 openssl s_client 回读为依据:mesh/cloud/auth/console/docs/status/api/omni/nomad/ai 每张证书只覆盖各自业务域名;www.threedogs.vip 的 Let’s Encrypt 证书同时覆盖 threedogs.vip 与 www.threedogs.vip。因此切换 edge 地址不会自动改变证书续期策略,各站点仍需保持独立证书签发与到期提醒。
证书、回源与域名模型的边界如下。
| 项目 | 冻结结论 | 依据或影响 |
|---|---|---|
| 证书 SAN | 业务证书按最终 Host 独立签发;Three Dogs 使用双 SAN | 浏览器按业务域名验签,不依赖 edge.yohan.fun 的单独证书 |
| 回源模型 | MM 当前 Nginx 按业务 Host 回源到 RR、101 或 DD 的服务端口 | 换边缘主机后必须在新边缘重建同等的域名路由与证书,而非只改 DNS |
| 静态地址维护 | edge 只保存 A/AAAA,不使用 DDNS |
用户已确认由维护者在权威 DNS 修改 A/AAAA |
| 动态地址维护 | sz 保留 NAS 自己的动态 AAAA |
用户明确要求只读核对,禁止修改 |
| 后台证据边界 | Dynadot 截图属于编辑态,不能替代权威查询 | 本次以 dig 的 NS、CNAME、A、AAAA 和 TTL 现场结果冻结 |
负向核对同时完成:没有发现 CNAME 环、业务名指向私网或 Tailnet 地址、错误业务名、裸域误用普通 CNAME,或把 sz 改成 edge CNAME。edge 当前同时发布 A 与 AAAA;本轮只证明 DNS 记录存在和 TLS 按业务域名可用,不把 AAAA 可达性写成已经完成端到端验收。
| 例外 | 固定边界 | 验收 |
|---|---|---|
mail |
独立邮件记录 | 邮件 DNS 查询与 MX/SPF/DKIM/DMARC 不受 edge 影响 |
sz |
NAS 动态 AAAA | 只读确认,禁止修改和 CNAME 化 |
裸 threedogs.vip |
独立 A 与 301 | 不承载 WooCommerce 会话;www 才承载正式站点 |
disk |
预留 CNAME | 未启用前不改,不纳入健康成功条件 |
ota/6844 |
个人项目 CNAME | 切换时健康检查,不纳入 AgentMeshOS 服务清单 |
负向回归:CNAME 环、错误业务域名、私网地址、Tailnet 地址、127.0.0.1、缺失 AAAA 但宣称 IPv6 通过、裸域错误 CNAME、后台修改未登记和 TTL 变化未记录都必须被拒绝。
回退:切换前保存每条 DNS 记录的原值、TTL、截图和查询结果;失败时逐条恢复,不批量覆盖整个 zone。
退出条件:后台记录与 dig 结果一致,所有业务域名只依赖 edge,TTL 和证书续期策略已记录,用户完成截图复核。
残余风险:跨厂商 CNAME 的状态依赖 Dynadot 与 yohan.fun 权威 DNS 同时可用;裸域和 CNAME 的差异不能由应用层绕过。
P10-2 端点快照与渲染器
状态:已完成。P10-1 已冻结 DNS 与例外;tools/derp-edge/config/derp-mm.yaml 已删除固定 IPv4,agentmeshos-reboot-resilience.sh 已改为读取受控 allow 渲染文件并校验公网 IPv4。端点解析器、快照、原子 last-known-good、渲染器和单测已在 RR 与 MM 完成安装与读取路径切换。
目标:把当前边缘 IPv4、IPv6、网关、探测时间和状态作为 root-only 运行时数据,活跃源、部署脚本和恢复脚本只引用逻辑主机名或受控快照。
前置依赖:P10-1 DNS 清单冻结已完成;确认 Nginx、UFW、Headscale、SSH、Gemini 出口和恢复脚本的实际读取路径。
首轮实现与现场核对结果:
| 对象 | 当前实现 | 尚未关闭的生产差异 |
|---|---|---|
| 端点快照 | scripts/maintenance/agentmeshos-edge-endpoint.py 解析 edge,拒绝私网、回环、链路本地、保留地址和多 IPv4 冲突 |
RR、MM 的 timer active,快照与 last-known-good 均为当前公网地址 |
| last-known-good | 快照采用原子写入和 0600;校验失败不覆盖上一份可用快照 |
RR、MM 临时路径注入私网 IPv4/IPv6 后均被拒绝,last-known-good 字节未变化 |
| 渲染器 | 生成环境文件、Nginx allow、SSH 公网别名、UFW 刷新脚本、SOCKS 包装脚本和 Gemini unit | RR、MM 重复渲染一致;RR 临时制造 allow 漂移后 render --check 返回失败 |
| 仓库 DERP Map | 只保存 mesh.yohan.fun,没有固定边缘 IP |
RR /etc/headscale/derp-mm.yaml 已删除 ipv4,headscale configtest 通过 |
| Gemini 出口 | wrapper 从受控快照读取当前地址 | RR unit 指向 wrapper,SOCKS 实测出口为当前边缘 IPv4;活跃 drop-in 注释也已改为逻辑身份 |
| SSH 双通道 | 101、RR、Home、DD、MM 的节点矩阵已读取 | 公网别名使用 edge.yohan.fun,Tailnet 别名保留明确节点地址;P10-3 继续收口权限矩阵 |
| CI 门禁 | 端点单测与硬编码检查已进入 Repository Guardrails |
提交后继续监管 Actions,不能只以本地测试代替远端成功 |
具体任务:
- 设计
/etc/agentmeshos/edge-endpoint.json或等价快照,保存当前地址、网关、来源、生成时间、解析 TTL、证据和 last-known-good。 - 实现单一只读解析器,解析
edge.yohan.fun后校验地址类型、私网/回环/链路本地/保留地址、记录数量和失败模式。 - 用幂等渲染器生成 Nginx
allow、UFW 规则、DERP Map、SSH Host、Gemini egress unit 和恢复脚本输入;生成器失败时不覆盖 last-known-good。 - 扫描代码、配置、脚本、部署目录、恢复材料和文档示例,区分活跃值与历史值。
- 把
agentmeshos-edge-hardcode-check.py接入Repository Guardrails,持续阻止旧 IPv4/IPv6 和当前 MM 地址被提交到活跃源。
| 对象 | 只保存 | 禁止保存 |
|---|---|---|
| Nginx 模板 | edge.yohan.fun 与渲染变量 |
MM 公网 IP |
| UFW 渲染器 | 快照引用与地址集合 | 手写固定 IP |
| DERP Map | mesh.yohan.fun |
ipv4 固定值 |
| SSH 配置 | 逻辑别名、Tailnet IP、公网快照引用 | 唯一固定公网 IP |
| 恢复脚本 | 解析器和 last-known-good 路径 | 旧 IP 回退默认值 |
负向回归:解析到私网、回环、链路本地、保留地址、空结果、多个冲突值、过期快照、写入中途失败和旧值重新注入都必须失败或被隔离。
回退:保留变更前文件和 root-only last-known-good;渲染器失败时保持现有 Nginx/UFW 不回写;回退后重新执行网络、TLS、SSH、Tailscale、DERP 和业务入口验收。
退出条件:活跃配置零固定 MM IP;同一边缘地址重复渲染结果一致;错误解析不会覆盖健康配置;恢复脚本在本机通过正向和负向测试,并在目标节点完成一次非破坏演练。RR、MM 的 timer、快照、last-known-good、渲染幂等、渲染漂移检测和恢复脚本检查均已完成,生产 Nginx、DERP、Gemini 与公网健康回读通过。
残余风险:DNS 本身成为权威入口;必须保留 last-known-good 和独立 SSH 入口,不能用解析器成功代替端到端网络验证。
P10-3 SSH 双通道与权限矩阵
状态:已完成。P10-2 已完成;RR、101、Home、DD、MM 的公网与 Tailnet SSH 路径、身份指纹和负向权限测试均已收口。
目标:明确 RR、101、Home 的管理员关系;RR、101、Home、DD、MM 的 SSH 路径按角色分离,不依赖 SSH 自动猜测地址。
前置依赖:P10-2 完成;docs/node-aliases.md 与实际身份、公钥指纹和端口回读一致。
固定权限矩阵:
| 来源 | RR | 101 | Home | DD | MM | 规则 |
|---|---|---|---|---|---|---|
| RR | 自身不回连 | 节点通道 | 节点或公网入口 | 节点与公网 | 节点与公网 | 管理员节点 |
| 101 | 节点与公网 | 自身不回连 | 节点或 LAN | 节点与公网 | 节点与公网 | 管理员节点 |
| Home | 节点与公网 | 节点或 LAN | 自身不回连 | 节点与公网 | 节点与公网 | 管理员节点 |
| DD | 仅保留原有权 | 仅节点 | 仅节点 | 自身不回连 | 不新增 | 存储节点,不扩大管理面 |
| MM | 不新增反向权限 | 仅节点 | 仅节点 | 不新增 | 自身不回连 | 单向边缘,不成为管理员 |
具体任务:
- 每台管理员节点使用明确 Host 别名、明确 IP、端口、用户和
IdentityFile,禁止默认密钥搜索。 - 101 和 Home 到 RR、DD、MM 同时保留节点和公网路径;RR、101、Home 到 101、Home 使用节点或同 LAN 路径。
- DD 到其他节点的路径保持原有最小权限;MM 不新增反向管理权限。
- Mac mini 现有授权暂缓保留,不列为当前管理员,也不在无用户确认时删除。
- 记录每把管理公钥的名称、指纹、目标节点、允许路径和最近验证时间。
负向回归:别名直接交给 SSH、默认密钥命中、错误用户、from= Tailnet 限制、DD 或 MM 越权主动连接、未登记公钥、known_hosts 身份变化和主机密钥静默接受都必须失败。
回退:变更前备份 ~/.ssh/config、authorized_keys 和指纹清单;失败时恢复原入口,但不得恢复 Tailnet-only 限制或删除物理/公网恢复入口。
退出条件:权限矩阵所有正路径和负路径真实验证;RR、101、Home 可在 MM 公网故障期间通过另一条已登记路径完成管理;DD、MM 没有新增反向权限。101、Home、RR 到 RR/DD/MM 的公网与 Tailnet 路径均返回真实主机名,DD/MM 无 SSH 私钥且主动连接被拒绝;节点登记已包含公钥指纹和 Home PowerShell 默认 shell 证据。
残余风险:公网 SSH 入口仍依赖 MM 地址和端口映射;因此必须同时保留 Tailnet 与 RR/Home 等独立管理路径。
P10-4 直连、DERP 与 101 路由
状态:已完成。P10-3 已关闭;360T7 FullCone 生效后,101、Home、RR、DD、MM 的直连和降级分类已通过现场路径复核。
目标:直连优先、DERP 兜底。MM 承载 region 900,DD 作为 region 901 候选;MM 自身故障时不能依赖 MM DERP 自恢复。
前置依赖:P10-2 和 P10-3 完成;360T7 C 固件当前状态、FullCone 是否生效和 101 双层 NAT 已按现场证据分类。
具体任务:
- 对 101、Home、RR、DD、MM 采集
tailscale status、tailscale ping、tailscale debug、derp连接、NAT 类型和 SSH 应用层结果,分别标记公网 SSH、Tailnet 直连、DERP 和失败。 - 重新验证 101 与 RR、DD、MM 的路径;不能把“应用层可连”写成“底层直连”。
- 验证 DERP Map 只使用逻辑主机名,region 900 不可用时不会错误宣称恢复成功。
- 评估并实现 DD region 901 的备份入口、健康检查和回退;不使用 MM 自身作为唯一兜底。
- 保留 101 冷连接金丝雀、NIC Link 抖动和无效 DHCP 租约监控,区分 09-25 长中断和 09-26 瞬时中断。
负向回归:停用 MM 公网入口、阻断一个 region、模拟 UDP 打洞失败、模拟 101 链路抖动、注入错误 DHCP 租约和关闭直连路径时,拓扑和告警必须显示真实降级,不得显示绿色直连。
回退:保留原 DERP Map、Tailscale 状态、路由和 SSH 配置备份;切换失败时先恢复可用控制路径,再恢复配置,不删除客户端身份和 DERP 私钥。
退出条件:直连、DERP、公网 SSH、Tailnet SSH 和使用 LAN 路径分别有证据;MM 不可达时 RR、101、Home 仍可通过独立通道管理;DD 901 有可实现和可回退结论。
残余风险:运营商 CGNAT、对称 NAT、UDP 质量、360T7 固件实现和 Windows 网络栈都可能让直连概率波动;DERP 必须保留但不能成为唯一恢复路径。
P10-5 拓扑接口、金丝雀与告警
状态:已完成。只读拓扑接口、网络控制路径金丝雀、脱敏 ClawBot 状态和告警恢复契约均已收口。
目标:由现有只读 API Gateway 聚合真实节点、链路、路径类型、延迟、新鲜度和错误码,为 Console 提供脱敏拓扑数据;用冷连接金丝雀发现新建连接故障。
前置依赖:P10-4 路径分类完成;现有 101 金丝雀和告警事件协议已验收。
具体任务:
- 定义只读拓扑响应契约,节点只返回身份、角色、状态、最后更新,链路只返回来源、目标、协议、路径类型、状态、延迟和错误码。
- 金丝雀覆盖 DNS、TCP、TLS、固定业务端点、DERP、MM 出口和本地 DHCP 租约;连续达到阈值才告警,恢复后关闭同一上下文告警。
- 把
key-pool.mjs的静默catch {}改为结构化错误日志,记录类别和重试结果,不记录任何 Key 值。 - 把 RR 微信 ClawBot 的可观测状态接入 Gateway;邮件仍是主动告警主路径,ClawBot 只做交互。
- 在 API Gateway 测试中断言私网 IP、Token、Cookie、完整 Prompt、主机路径和内部 URL 不出现在响应中。
负向回归:过期数据、单次失败、连续失败、恢复、未知路径类型、错误延迟、敏感字段、超大响应和上游超时必须按契约表现,不能把未知显示为绿色。
回退:新增接口和前端区域独立开关;失败时隐藏拓扑区域但保留原有状态页、告警和 SSH 管理路径。
退出条件:故障可重复触发,恢复可关闭同一告警;前端只消费 Gateway 事实;桌面和移动端轮询不产生重复告警或敏感字段泄露。
残余风险:探测频率、超时和阈值只能反映采样窗口,不能证明所有路径永久可用;必须保留人工 SSH 和公网回退路径。
P10-6 Console 网络态势与通道
状态:已完成。Console 首页网络态势、Provider 页 ClawBot 状态、桌面与移动端浏览器回归均已交付。
目标:在 Console 首页提供交互式网络拓扑,按真实路径显示节点、连线、状态颜色、数据流和详情;在平台运行页展示 RR 微信 ClawBot 通道状态。
前置依赖:P10-5 拓扑接口可用;Console 现有 Vanilla JavaScript、浏览器契约和认证回源链路不变。
具体任务:
- 节点分层显示公网 edge、管理节点、计算节点、存储节点和其他节点,不使用装饰性图形替代真实状态。
- 连线区分公网 HTTPS、Tailnet 直连、DERP、SSH 管理和公网数据面。
- 状态颜色固定为绿色直连健康、黄色 DERP/降级、红色离线/断链、灰色未知/过期。
- 数据流动只在状态变化或新探测到达时播放;支持悬停、点击详情、缩放、平移、路径筛选和键盘可访问操作。
- 移动端回落为单栏;支持
prefers-reduced-motion,不得出现文字遮挡、横向溢出或按钮尺寸漂移。 #providers增加 ClawBot 版本、绑定状态、最近收发、最近错误和 24 小时回复窗口;不显示 Token、二维码、登录凭据或原始消息。
负向回归:过期链路显示灰色、DERP 不显示绿色直连、数据流动画不在静态状态中持续伪造、移动端无溢出、降低动态偏好下无动画、ClawBot 无敏感字段。
回退:Console 功能开关可回到原节点/Provider 列表;接口不可用时显示原因并保留原有页面,不用假数据填充拓扑。
退出条件:Playwright 桌面 1440x900 和移动 390x844 通过;颜色、路径、交互和 ClawBot 状态均有截图或断言证据;生产公网回读成功。
残余风险:拓扑质量取决于 Gateway 探测真实性和新鲜度;前端不能自行推断链路类型或把未知状态美化。
P10-7 边缘切换与回退演练
状态:已完成可执行范围。已在 RR 隔离目录完成端点候选、非法输入、last-known-good 和回滚演练;真实第二边缘生产切换保留为后续运维外部前置。
目标:在稳定身份不变的前提下,演练边缘地址或边缘主机切换,验证所有业务域名只依赖 edge.yohan.fun,并证明可安全回退。
前置依赖:P10-1 至 P10-6 全部关闭;新边缘节点网络、证书、回源、SSH、DNS TTL 和监控准备完成。
具体任务:
- 切换前保存所有 DNS 记录、端点快照、Nginx allow、UFW、DERP Map、SSH、Gemini egress unit、证书和业务探测结果。
- 先将 TTL 降低到可回退窗口,再把
edge.yohan.funA/AAAA 指向目标边缘;业务域名的 CNAME 不改。 - 验证 DNS、TLS、SSH 公网与 Tailnet、Headscale、DERP、Cloudreve、Console、Docs、Status、API、Auth、Threedogs、个人项目和 NAS 例外。
- 验证 MM 不可达时,RR、101、Home 仍能管理;MM DERP 不参与自身故障兜底。
- 恢复原记录或原边缘后重复全链路,确认回退不是只恢复文件。
负向回归:新边缘证书错误、回源错误、IPv6 不可用、单个 CNAME 未跟随、SSH 身份变更、DERP 未重连、Cloudreve 数据面失败和回退后旧缓存残留都必须阻止关闭。
回退:逐条恢复 A/AAAA、TTL、端点快照、Nginx/UFW、DERP、SSH 和出口服务;先恢复管理路径,再恢复业务入口;任何网络层不可用时不得宣称回退完成。
退出条件:切换、业务验收、故障注入、管理降级、回退和再验收全部有命令、日志、时间和结果;所有业务域名的浏览器地址栏保持原域名。
残余风险:切换窗口内的 DNS 缓存和证书签发时间存在外部不确定性;演练后必须保留旧边缘一段可回退观察期。
P10-8 文档、归档与残余风险收口
状态:已完成。P10 原始计划已原地校正并归档,架构、节点、历史、遗留风险和重新验证条件已同步。
目标:把架构、部署、端口、DNS、SSH、DERP、服务映射、计划和归档同步到真实现场,关闭或明确移交所有残余项。
前置依赖:P10-0 至 P10-7 完成;GitHub Actions、生产镜像和公网状态可回读。
具体任务:
- 更新
docs/architecture/**、运行文档、节点登记、端口映射、DNS 清单、SSH 权限矩阵和恢复步骤。 - P9 保持关闭;P10 完成后追加
history.md,创建独立完成归档,并更新archive-manifest.json、completed.md和导航。 - 把 IPv6
/118与现场/64、AAAA 可达性、auth/console/nomad/omni200/302、Threedogs 延迟、RR 根分区与 Swap、MMcloud-final.service、101 失败单元和离线节点逐项登记为关闭、移交或持续监控。 - Mac mini 授权保持保留但不列为当前管理员;如果后续上线,重新走权限矩阵和公网/Tailnet 双通道验收。
- 更新重新验证触发条件:边缘地址、Headscale/Tailscale/Nginx 版本、证书、DNS 提供方、路由器固件、恢复脚本和云厂商网络变化后必须重新执行完整验收。
负向回归:文档引用不存在文件、导航孤儿页、计划状态不一致、旧 IP 未标历史、已完成项缺证据、未完成项被写成完成、P9 被重新打开和 GitHub 与线上不一致都必须失败。
回退:文档变更按 Git 反向提交;完成归档只追加更正记录,不覆盖旧事实;线上回退继续引用 P10-7 的版本化端点快照。
退出条件:权威文档、仓库、GitHub、CI、生产镜像和公网页面一致;所有残余项有责任人、验证条件和下一步,不再以“无关”名义跳过。
残余风险:外部 DNS、运营商、证书签发、路由器固件和云厂商控制台属于外部依赖,只能在变更时重新验证,不能承诺永久免故障。
🧩 分布式底座接入声明
接入结论:P10-1 仍不接入 Nomad 或 Runtime 任务执行;后续控制台拓扑接口只接入 Network、Observability 和现有只读 API Gateway。
使用层:Network 接入;Observability 接入;Storage 只读用于历史恢复材料;Nomad 与 Compute 本阶段不接入。
Adapter 归属:不新增 Runtime Adapter。拓扑数据由现有 Gateway 聚合,恢复脚本和配置渲染器只属于基础设施维护边界。
执行映射:101 负责计划、文档、GitHub 和 CI/CD;RR 负责生产部署与运行;MM 只承担当前边缘入口;DD 作为存储和第二 DERP 候选。任何凭据不进入模型、文档或普通回复。
数据路径:地址事实写入 root-only 运行时快照;拓扑 API 只返回脱敏状态;大流量业务继续走公网 HTTPS,不通过 Tailnet 中转。
生命周期:端点快照保留 last-known-good;历史旧值和备份只用于回退与审计,不自动清理;一次性凭据按原规则撤销。
验收证据:计划状态检查、MkDocs strict、链接检查、自托管 Runner 日志、DNS 解析、SSH 双路径、直连/DERP 分类、切换演练和回退结果。
🗂️ 文档库治理
文档库纳入 P10 前置工作。docs/** 全量 review 完成前,不修改现网网络配置。文档、网络、端口、DNS、SSH、DERP、服务映射和节点角色变化必须在同一变更集中更新。
执行顺序固定为:部署、更新、GitHub 同步、再次更新并确认。GitHub Actions 必须使用 101 的自托管 Runner 标签 agentmeshos-ci,日志要记录真实 Runner 名称。
P10-0 的“完成”不能只以仓库提交、CI 构建成功或 MkDocs 本地 strict 构建通过为准。现已把通过验证的文档镜像部署到生产 docs-site,并从 https://docs.yohan.fun/plans/ 和控制台“实施计划”嵌入页回读,确认 P10 为当前阶段、P9 明确显示为已关闭、P10 正文可访问。该生产与认证回读已完成,因此 P10-0 关闭并进入 P10-1。
原计划、本修订版、P9 关闭记录和历史证据分别保存,但计划身份只有一个。旧 MM 公网入口迁移文档保留为历史,必须加“历史值,不得用于恢复”的标识;当前权威入口、端口和恢复路径写入 P10 正文及对应运行文档。
🚀 CI/CD 自动部署恢复
本轮重新核对了“更新已推送但生产文档仍为旧版”的原因。GitHub Actions 已正常触发,101 的两个自托管 Runner 均在线;真正的问题是四个无状态工作流的 deploy-production 被提交 5559987 硬编码为跳过。该提交属于 P6 的临时验证边界,但 P6 完成后没有恢复原变量门禁,形成了长期规则漂移。
| 对象 | 当前事实 | 依据 | 处理 |
|---|---|---|---|
| Action 激活 | 文档推送已产生 Run 36212485144,构建 Job 成功 |
GitHub Actions Run 与 Job 回读 | 不是调度故障 |
| 101 Runner | pcdell-101-agentmeshos、pcdell-101-agentmeshos-2 均 online、空闲 |
GitHub Organization Runner API | 保留自托管执行链 |
| 部署门禁 | docs-site、console-site、status-site、api-gateway 均曾为 if: ${{ false }} |
提交 5559987 的四个工作流差异 |
恢复仓库变量门禁 |
| 原禁用原因 | P6 只允许 Home 和 101 验证,禁止 RR 生产部署 | 提交 5559987 注释与 P6 记录 |
保留为历史,不重写 |
| 防复发 | CI 必须校验四个工作流继续使用统一变量门禁,并拒绝硬编码禁用 | scripts/ci/agentmeshos-production-deploy-gate-check.py 与负向契约测试 |
后续提交纳入四个构建 Job |
修复后,临时停部署的操作方式是设置 AGENTMESHOS_ENABLE_RR_PRODUCTION_DEPLOY=false,而不是修改工作流源码。true 时,四个无状态服务沿用完整 40 位 SHA 镜像、RR 发布锁、健康检查、失败回滚和发布日志;Runtime、Auth 与 CLI Gateway 仍保持人工发布边界。
🧪 验证与放行
每次变更前先执行只读基线:计划状态检查、文档站 strict 构建、链接与导航检查、git diff --check、端点清单解析、DNS 查询、SSH 双路径探测和 Tailscale 路径分类。
负向测试至少包括:旧 MM IP 注入必须失败;无效或私网解析结果必须拒绝;过期端点快照不得覆盖 last-known-good;P9 不得重新进入当前实施计划;计划正文不得被平行文件替代;四个无状态工作流出现硬编码禁用必须失败;重复导航项和孤儿页必须失败。
切换演练只允许修改 edge.yohan.fun 的目标地址,随后验证所有 CNAME 业务域名、TLS、SSH 双路径、DERP、Cloudreve、Console、Docs 和 Three Dogs 入口。任一关键验证失败即停止后续步骤并进入回退。
🔁 回退方案
回退以原计划保留的备份和本次端点快照为边界。旧 IP、旧网关、旧 DERP Map、旧 SSH 配置、旧 Nginx allow、旧 UFW、旧 Gemini egress unit 和 last-known-good 必须可逐层恢复。
回退不是只恢复文件。恢复 DNS 或端点后必须重新验证公网解析、TLS、SSH 双路径、Tailscale、DERP、SOCKS 出口和业务入口;网络层不可用时不得宣称回退完成。
计划文档本身使用追加式回退:新增修订记录和更正记录,不删除旧结论、不覆盖历史证据、不重写已经验证的事实。
⚠️ 未决项 / 需要用户决策
| 未决项 | 当前事实 | 下一步 |
|---|---|---|
| P10 后续外部前置 | 真实生产边缘主机切换需要第二台完整边缘、独立证书、回源、DNS 变更窗口和运营商配合;当前只完成隔离演练 | 作为运维触发条件保留;条件满足后再按 P10-7 切换与回退流程执行,不需要重建本计划 |
| IPv6 | DNS 当前发布 AAAA,完整公网路径仍需独立验证 | 从具备 IPv6 的节点验证 443、DERP 和回源 |
| IPv6 掩码 | 用户书面值与现场 /64 曾存在差异 |
用户确认正式网段后再改配置 |
auth/console/nomad/omni |
console、nomad、omni 根路径先返回 302 到 A-Auth,跟随跳转后为 200;auth 登录页直接为 200 |
已核对跳转语义;业务访问仍需合法登录态,不能把跟随后的 200 当作未认证可访问 |
| Threedogs 性能 | 2026-09-26 复核中 www.threedogs.vip 与裸域均在 20 秒内无响应;此前记录曾为 200 但约 11.86 秒;拓扑继续显示真实红链,但不触发整网冷连接告警 |
独立排查后端、代理和资源瓶颈;恢复 200 前不写成健康 |
| RR 资源 | 根分区和 Swap 曾处于高水位 | 单独排期清理并验证 |
MM cloud-final.service |
Debian bullseye 包源失败 | 单独处理软件包源和 cloud-init 路径 |
| 101 失败单元 | 网络等待与构建内存失败已记录 | 作为独立任务排查,不混入 MM IP 变更 |
| 离线节点 | jj、summer、mac-mini、benson-nb、officesummer |
不作为本阶段恢复成功依据 |
| 路由器 FullCone | C 固件界面缺少明确入口,现网是否已生效需复核 | 只在确认路径和回退后调整,不改成 AP 或桥接 |