三条线合并入库 —— 均已完成并上线(源码与生产一致,此前只部署未入仓)。 ⚠️ 其中域名迁移线为**另一会话**产出,本会话只做入库、**未复验其正确性**(它自报零回归)。 【档案 134 · 注册页人机验证 + 邮箱验证码】 - DB 迁移 v10:users.email(唯一索引 LOWER(email))+ email_codes 事件表(2 索引) - 新增模块 src/web/{register-guard,mail,turnstile,email-code}.ts - routes/auth.ts:新增 GET /api/auth/register/config、POST /api/auth/register/email-code; 注册接口加人机验证与验证码校验;config.ts 新增 12 项配置(默认空 ⇒ 不配 = 老行为) - 邮件走**可插拔驱动**(brevo/http/log),发件人 [email protected](Brevo 域名已认证 + DKIM + SPF) - 防爆破:三层配额(邮箱 6/h、8/天;IP 20/h;全局 200/h)+ 递增冷却阶梯 (60→60→180→300→900→1800s)+ 试错 5 次作废 + 码只存哈希 + 单次使用 + 与用户名绑定 - Turnstile 服务端校 **success + action + hostname 三项**:sitekey 是公开的, 只校 success 时"拿我们的 sitekey 在自己站点替真人取合法 token 再打我们接口"这条路是通的 - 新增 test/register-guard.test.mjs(19 用例) 【档案 137 · 品牌标识改造 — 去 DeepSeek 图形】 - login/register/admin 页头:删 DeepSeek 鲸鱼图标 + 「DeepSeek」文字图形 → 平台标识(中文「能力枢纽」/英语及其他语言「CapabilityNet」,走 i18n 词条 brand.name) - portal 顶栏换图标(页面名「管理门户」保留) - 新建 web/favicon.svg(平台自有 hub 图标,避开 DeepSeek 蓝)+ 四页 favicon 指向它 - 新增 test/i18n-brand.test.mjs(node:vm 跑真实 i18n.js,六条语言路径断言渲染结果) - scripts/verify-static.mjs 新增 SVG 段:XML 注释不得含 ASCII 双连字符(否则整份 SVG 解析失败、图标静默不显示 —— 实际踩到过) - 🔴 会话页面(实例内官方 dsh 界面)的标识**按用户要求未动**(也受 R2 约束) 【档案 135/136 · 域名迁移线(另一会话产出)】 - 域名收敛为 ai1net.com;旧域 alotbuy.com 降级为 301 过渡装置 - src/net/relay/{addr-override,directory,rendezvous,switcher}.ts 种子与候选链更新; src/web/server.ts、src/worker/relay-tunnel.ts、scripts/verify-cluster-domain.mjs - 档案 136 = 控制面按两台中继取并集(**已立项、未落地**) 验证(本会话两条线):新增单测 21 条全通过|全量 221 pass / 0 fail / 1 skipped| verify-static 全合格|其余 10 个 verify 脚本全 OK|线上实测:Turnstile 假 token 403、 发码 delivered、四页 deepseek 命中 0、favicon 200。
12 KiB
12 KiB
135-旧域 alotbuy.com 从项目移除(2026-09-19 落地)
一句话:平台对外域名收敛为
ai1net.com单一域名;旧域alotbuy.com在代码 / 服务端配置 / 文档技能三层全部移除, 旧域 nginx 站点降级为 301 过渡装置(保留 relay 透传与 ACME,30 天零流量后退役)。 触发:用户 2026-09-19 原话 —— 「旧域 alotbuy.com 怎么处置:从项目中移除后续都用新域名」 执行:序㊿ 执行棒(会话名旧域移除-控制面并集-20260919)· 计划书 = 工作区根_tmp_dompurge/PLAN-旧域移除与并集立项_20260919.md姊妹件:同棒产出的立项交接单 =04-调整方案/136-控制面按两台中继取并集-立项交接单.md
背景与动机
- 域名已在 09-19 切换完成(见
ops/域名迁移_ai1net_20260919/RUNBOOK-cutover.md),但切换只做到"新域能用", 旧域仍以独立门户站点形态存在 ⇒ 两套入口并存 = 两套证书、两处签名目录、两处排障路径。 - 旧域残留会让判据撒谎:演练脚本的"是否切到 47 那台中继"判定用硬编码域名字符串匹配端点 ⇒ 域一改,真实发生的切换会被判成失败(本节 §"实测踩坑 1" 即此坑)。
- relay 候选里存在"摘名不同、物理同一"的伪多样性:
alotbuy.com与relay-direct.alotbuy.com摘名不同、 同落 47 同一路径、且后者还开了DSHS_OVERLAY_ADDR_OVERRIDES直连 IP ⇒ 5 条候选里 2 条零物理多样性。
用户决策
| 时间 | 用户口径 | 落地 |
|---|---|---|
| 2026-09-19 | 「从项目中移除后续都用新域名」 | 代码 / 服务端 / 文档技能三层真实替换;旧域不删站、降级 301(删站会打断仍指向旧域的客户端,净变差 ⇒ R11 不允许) |
| 2026-09-19 | 「A 立项修」(控制面并集) | 只出立项交接单(档案 136),本轮不落地 |
范围分桶(最终实测结论)
| 桶 | 对象 | 处置 |
|---|---|---|
| A 代码 / 运行时 | src/**、web/**、test/**、scripts/** |
✅ 全量替换(10 个源文件 + 2 个 test + 2 个 live 校验脚本 + 1 个演练脚本 + 1 个探针注释) |
| B 服务器配置 | 47 的 drop-in / nginx;106 的 worker env | ✅ 落新值(见 §执行记录 S3/S4) |
| C nginx 旧域站点 | 47 /etc/nginx/conf.d/alotbuy.com.conf |
✅ 降级为 301 过渡装置(保留 3 条非 301 路径) |
| D 文档 / 技能 | 文档库 + skills/** |
✅ 42 处精确替换 + 1 处补 Edit(只改"现行事实"章节) |
| E 不动的 | 04-调整方案/** 历史档案、archive/**、参数表 §11 历史补记 |
⛔ 历史记录不改(改了就是伪造历史) |
| F 排除 | work.alotbuy.com(Gitea 仓库服务) |
⛔ 不是本平台域名,与迁移无关 |
执行记录(S1–S7)
S1 · 代码层替换(A)
- 扫描 127 个文件,命中并改写 10 个:
src/config.ts×2、src/net/relay/addr-override.ts×4、src/net/relay/directory.ts×2、src/net/relay/rendezvous.ts×1、src/net/relay/switcher.ts×4、src/web/server.ts×3、src/worker/relay-tunnel.ts×5、test/overlay-bootstrap.test.mjs×22、test/relay-failover.test.mjs×4、web/wake.html×1。 - ⚠️ 计划书的行号表是快照、已漂移(例:计划写
config.ts:312,实测:381;另有计划未登记的config.ts:125、directory.ts:324) ⇒ 一律先自己 scoped grep、再做字节级精确替换,⛔ 不按计划行号下手。
S2 · 修掉一个真 bug(A3)
web/wake.html里有转义点写法alotbuy\.com,被批量替换漏掉 ⇒ 白名单正则仍只认旧域 = 唤醒后跳转白名单恒不命中。- 修为新域后缀(单后缀即正确 —— 已核
next是由请求 host 拼出的绝对 URL,见src/supervisor/proxy.ts:613):/^(\^|\.)ai1net\.com$/.test(x.hostname)(源码中无多余反斜杠)。
S3 · 47 服务端(B + C)
- drop-in
overlay-443fb.conf:DSHS_OVERLAY_BOOTSTRAP_SEEDS5 → 3,删掉同机同路径的两条旧域候选;DSHS_OVERLAY_ADDR_OVERRIDES=relay-direct.ai1net.com=47.77.182.89;注释写明"旧域/dshs-relay透传仍在"与回滚原文。 - nginx 旧域站点降级:
map $host $alotbuy_301_host(默认ai1net.com;~^(?<lb301>[^.]+)\.alotbuy\.com$ → $lb301.ai1net.com⇒ 子域对子域映射),80/443 双 server 全 301;仅保留 3 条非 301 路径:/.well-known/acme-challenge/、/dshs-relay→127.0.0.1:20080、= /dshs-overlay/bootstrap→127.0.0.1:3080。 - 文件头写入降级而非删除的理由与退役条件 = 30 天零流量。
- 归档
_pending-ai1net/→mv到/root/_dompurge/_pending-ai1net-archived-<ts>(不是删除)。
S4 · 106 worker(B)
/etc/dshs-worker.env第 26 行同步为同 3 条 SEEDS;备份/etc/dshs-worker.env.bak-dompurge-20260919-073149;daemon-reload。- 顺带取证:
dshs-relay-client单元为 disabled(历史遗留、无害)—— 只报告、未动。
S5 · 控制面二次重启以清签名目录缓存(关键一步)
- 一次重启后 bootstrap 仍是 5 条、仍含 2 条旧域 ⇒ 定位到 Manager 把自己发布的签名目录缓存在
/var/lib/dshs/overlay/directory.json(fetchedAt07:29,早于改动)且懒重建。 - 处置:备份 + 删除该可再生缓存 → 第二次重启控制面 ⇒ Manager 解析出 3 条候选、全部新域
(
source=seed-directory),缓存重建 578 B。
S6 · 文档与技能(D)
- 42/42 处精确替换(每处带 count 断言):
BRIEF.md、README.md、INDEX.md、DEPLOY-本部署.md、02-运维手册.md(仅附录 C = 现行事实章节)、docs-manifest.json、scripts/docs-consistency.py、scripts/cf-probe.py(新增CREDS={'ai1net.com':'/etc/cloudflare-ai1net.ini'}+token(zone))、7 个技能文件。 - 补 1 处:
skills/dsh-instance-diagnose/SKILL.md(goto https://<user>.ai1net.com/)。 - 文档库镜像同步:
ops/nginx/alotbuy.com.conf换为 301 版(md5eccf9014c6e1c3f13a5c32b7b14418a9,与生产一致)。 - 从 47 暂存目录抢救回
ops/域名迁移_ai1net_20260919/RUNBOOK-cutover.md(唯一副本),并在头部加状态横幅 (记录 §1 阻塞已解、S1–S5 已执行;原"留待你确认退役时机"已被本棒取代)。
S7 · 参数字典与判据脚本
- 参数表值格 2 键:
PORTAL_HOST_HEADER、DRILL_KILLED_MATCH由alotbuy.com→ai1net.com(🔴 后者是假红根因,见踩坑 1); + 两处-H "Host: alotbuy.com"示例 + §6 一条候选摘名说明 ⇒ §10 指纹同步为075a97239c2d1d8a1f442ec6cc787ede。 scripts/overlay-probe.cjs注释、verify-cluster-domain.mjs/verify-platform-admin-section.mjs默认域同改。
实测踩坑(两条,都是"判据撒谎"型)
踩坑 1 · 演练"假红"(已修)
- 现象:
overlay-failover-drill.cjs --scene all= 11 PASS / 1 FAIL(基线 12 PASS),红在幕4-A「目标不是 47 那台」。 - 根因:幕4-A/幕4-B 的判定用硬编码字符串
alotbuy.com去匹配端点 ⇒ 豁免真的生效了、真的切回 47,只是判定认不出。 - 修法:两处匹配器改为取参数表
DRILL_KILLED_MATCH(m3.includes(killedMatch)/m2.includes(killedMatch)),并在注释块记录本次域迁移的勘误。
踩坑 2 · 「查旧域不存在」的两种假象
- 旧域
/dshs-relay直取 = 404:曾疑似回归 ⇒ A/B 对照:新域裸 GET 同样 404;两域带 WS 升级头都返回 101 ⇒ 非缺陷(/dshs-relay只对 WebSocket 升级生效)。 admin/guest.ai1net.com= 401(不是 302):属既有"无 session 直连实例页"行为,非回归(档案 136 §7 E7 已登记口径)。
验收证据
| # | 判据 | 结果 |
|---|---|---|
| V1 | 签名 bootstrap 候选集 | 3 条 / 0 处旧域,source=seed-directory,缓存 578 B |
| V2 | 零回归三件套 · 探针 overlay-probe.cjs |
29 PASS / 0 FAIL / 0 SKIP(rc=0);OBS-21 = count=3 hosts=3,47 / 106 两机读一致,全表零 alotbuy |
| V3 | 门户可达 | 新域首屏 200 |
| V4 | 旧域过渡 | 301 生效,含子域映射(guest.alotbuy.com → https://guest.ai1net.com/...) |
| V5 | relay 透传双域一致 | 裸 GET 双域同 404 / WS 升级双域同 101 |
| V6 | 零回归三件套 · npm test |
未跑(本棒零测试面逻辑改动;仅字符串与匹配器) |
| V7 | 零回归三件套 · 演练 --scene all |
✅ 12 PASS / 0 SKIP / 0 FAIL(rc=0;5m56s~6m;末行原文 # 结果:12 PASS / 0 SKIP / 0 FAIL)—— 修后复跑,幕4-A 目标 = wss://ai1net.com/dshs-relay、耗时 15867 ms / deadline 30000 ms。⚠️ 全套含 120 s + 90 s 观察窗 ⇒ 外层超时必须 ≥ 8 min,否则 restore() 不跑、106 relay 会留在停机态 |
| V8 | 技能「三处」同步 | ✅ 6 个技能全部本机/文档库/47 镜像三处域已清;其中 3 个(decision-method / feature-first / plugin-diagnose)三处 md5 全同(a8971220 / a1397140 / 3edeeb89);⚠️ 另 3 个(change-workflow / opensource-release / instance-diagnose)本机副本更新 ⇒ 存在本会话之外的既存漂移,本轮只做域替换、⛔ 未覆盖新副本(详见 §残留项 6) |
回滚
- 代码:
git checkout -- src web scripts+npm run build⇒ scp 回/opt/dshs/(产物清单见_中间产物_待清理/_证据_序50_部署产物15文件md5_20260919.txt,15 个文件)。 - 47:drop-in 恢复 5 条 SEEDS(原文在文件注释里)→
daemon-reload→restart dshs;nginx 旧域站点恢复原站(备份在同目录.bak-*)。 - 106:
cp /etc/dshs-worker.env.bak-dompurge-20260919-073149 /etc/dshs-worker.env→daemon-reload→restart dshs-worker。 - 回滚后必须删一次
/var/lib/dshs/overlay/directory.json并重启控制面(否则又读到旧缓存 ⇒ 假回滚成功)。
残留项 / 后续(不阻塞)
- 旧域退役条件:
alotbuy.com站点保持 301 过渡,30 天零流量后再评估删除;relay-direct.conf、dsh.alotbuy.com.conf同属"导向新域 / 兜底"装置,删除即净变差(R11) ⇒ 保留。 - 参数表 §11 历史补记仍引用旧域(含旧证据原文引用)—— 故意不改(历史记录)。
dshs-relay-client(106) = disabled 历史遗留,无害,未动。- 演练脚本修正版按惯例应两机同源部署(
scripts/overlay-failover-drill.cjs是本机 ssh 出去的工具,不被任何单元读取 ⇒ 零服务影响)。 - 控制面按两台中继取并集 —— 立项见 档案 136(本轮只立项,未落地)。
- 技能副本的既存漂移(⛔ 本会话之外形成,只报告未统一):
.workbuddy/skills/与文档库skills/三对不一致 ——dsh-change-workflow(本机 1055 行 vs 文档库 1039 行)、dsh-opensource-release(本机 1.8.2 vs 文档库 1.7.8)、dsh-instance-diagnose(本机 SSH 别名更正 vs 文档库旧写法)。⇒ 本轮对这三份只做域替换(⛔ 不覆盖,避免丢内容); 镜像/opt/dsh/docs/skills/已与文档库对齐(md5 同)。回头条件 = 有人真正要动用这三份技能时,先做一次副本收敛。 /opt/dsh/docs镜像的更广泛漂移(⛔ 本单范围外,未推送):docs-sync-check.sh(须[email protected],默认别名已失效) 报出30+ 个"仅本地待推送"文件 —— 属本会话之前就存在的镜像滞后,本轮只推了 6 个技能文件,其余按"只做被明确要求的事"未动。- 演练脚本
overlay-failover-drill.cjs未铺服务器:两机/opt/dshs{,-cluster}/scripts/本来就没有该文件(它是本机 ssh 出去的工具) ⇒ 只在本机生效;而overlay-probe.cjs已按惯例三处同源(md555568f87bfe2dc8e43289c69b4126004)。