审查 F4:ConnectNode 发每设备 devDp,DisconnectNode 却吊销账户级 ent.DpUUID 且无 device_id 入参——断开从未真正吊销,凭证活到 TTL。修:disconnect 收 device_id,吊销该设备 dp_uuid(账户级作遗留兜底);客户端带上 device_id。
审查 F3:device_id 跨账号复用 + devices.uuid 全局 UNIQUE → 第二账号注册永远 403 → 连接被 DEVICE_NOT_REGISTERED 卡死。落地 migration16 注释里推迟的 UNIQUE(user_id,uuid) 表重建,注册查找改按 (user,uuid)。见 docs/code-review-2026-07.html
agent 每 dp_uuid 每窗口计 SessionMinutes=1,控制面 ReportUsage 逐条累加进 usage_daily.minutes_used → N 台并发=N×墙上时钟(chenxin 2903/天)。免费卡控下会错误判耗尽。改:账户维度按 user 分组去重(minutes=max,bytes=sum),每设备维度不变。
连接期倒计时+到点切断;耗尽按钮灰化;点击弹广告(占位流程)看完+10分钟(累加,每日封顶120);桌面硬10分钟不可延+升级提示。额度全账户共享。服务端ConnectNode按remaining卡控+TTL硬切;ad_bonus_minutes累加模型;DevVerifier占位。
✓ 已确认
一级方案规划
2026-07-01
已进 plan 模式出方案并经用户 ExitPlanMode 批准
📄 详见 /Users/wangjia/.claude/plans/crystalline-exploring-lerdorf.md
windowManager.hide() 走 orderOut: 后窗口不可见,点 Dock 图标只发 applicationShouldHandleReopen(hasVisibleWindows=false),AppDelegate 未接管 → 点了没反应。修:AppDelegate 实现 applicationShouldHandleReopen 唤回 mainFlutterWindow。
后台/挂起期 urltest 被限流停更但 speed 在流→path A 误判上游死断连。修:statsLive 闸 + 切后台(paused/hidden)停看门狗、resumed 重启并重置基准。另修连接时长墙上时钟(切后台不漏计)。已合 main 07861ea/37c1724/58211d2,含回归测试。
现状:plans.max_devices(free1/pro5/team10)+ devices/service.go:216 强制逻辑 + DEVICE_LIMIT_EXCEEDED 错误码 + 账户API DevicesMax 都在,但 main.go:534 登录注册传 MaxDevices:0(不启用)。原因:free 用户重装会换 device UUID,登录硬卡会把人锁外面。需:① 登录/注册从套餐读 max_devices 传入 RegisterIfAbsent;② 超限不直接拒登,改为'踢最旧设备/让用户选哪台下线'的 UX(客户端弹窗 + 设备管理页操作);③ 处理 free 重装 churn(同机复用而非每次新增)。tier-1:涉及登录接口 + 跨后端/前端 + 策略设计。
⏸ 待确认
一级方案规划 · 确认后方可继续开发
登录卡超限(非硬拒登:token照发+返回device_limit信号,客户端挡在移除设备页)+连接backstop兜底;选择移除+一键踢最旧;服务端按last_seen自动清理久不活跃(staleWindow=30d,活跃count排除+登录best-effort删僵尸)。复用现成 DeleteDevice/ResolvePlan/CheckDeviceQuota/ConnectNode。后端:auth service/handler(recordLogin回传+LoginOutcome.DeviceLimit)、devices(DeviceLimitStatus+活跃count+prune)、main wiring、nodes ConnectNode backstop。前端:auth_api解析、auth_provider路由、DeviceLimitScreen、l10n。无DB schema变更。
📄 详见 ~/.claude/plans/crystalline-exploring-lerdorf.md
确认执行 ✓
在终端运行:
/todo approve 16
复制命令
client/test/golden/goldens/ 下未被引用的 tablet_connect.png/tablet_connect_dark.png/tablet_servers.png/tablet_stats.png/tablet_account.png(旧命名,已被 _light_/_dark_zh 矩阵取代),git rm 清掉。(从本地 main todo 合并而来)
本次 google 打不开暴露的架构漏洞:① 节点 status 是静态 DB 列(种子 up),只有 SCHED 健康循环会改、而单节点没开 → Hub 已知 agent 离线却不反映到节点状态/列表,客户端永远显示健康。应把 Hub 的 agent 在线状态接进 ListNodes/节点 status。② ConnectNode 把 hub.Push 错误吞了(_ = pushErr)且不校验 agent 在线 → 凭证没下发也返回 200,客户端误以为连上。应在 agent 离线/push 失败时降级或明确报错,并把推送结果纳入响应。③ agent 掉线无告警(本次停 6 天没发现),应在 Hub 检测到 agent stream 断开时告警。④ 通病:错误被 _ = 静默吞掉(今天邮件/连接500/此处共三处),需排查同类静默吞错。
统计重设计的设备下拉,先只挂「全部」上线;每设备归因打通后,把下拉填上「全部 + 近30天用过的设备名」,选设备走 /v1/usage/devices 过滤。依赖每设备归因 TODO。
移植 macOS 已验证的统计架构:扩展注入 clash_api + StatsCollector(clash 取 urltest),app StatsClient 改 sendProviderMessage 轮询;前置生成 iOS Libbox.xcframework。Dart 侧已对齐(共用 VpnNativeBridge)。
现状:多设备共用账户级 dp_uuid,统计无法区分设备;usage_device_daily 永远空,统计页设备下拉只有「全部」。基础设施已具备(devices.dp_uuid / EnsureDeviceDpUUID / usage_device_daily / UserDeviceByDpUUID)但未激活——客户端没 POST /v1/me/devices 注册本机,连接时 EnsureDeviceDpUUID 查不到设备行→回退账户 uuid。需:① 客户端启动/登录时注册本机设备(稳定 uuid + name + platform);② 连接时带该 device_id;③ 或让 EnsureDeviceDpUUID 缺行时自动建设备行。打通后每设备统计 + 统计页设备下拉才有真数据。是统计重设计「设备下拉」的前置依赖。
agent 心跳带 sing-box 健康(clash_api /version)→控制面 effectiveNodeStatus 标 down(列表置灰+connect拦截);客户端连上后 HTTP 204 看门狗,连续失败:智能选择自动切节点/手动只提示断开。plan: crystalline-exploring-lerdorf.md
客户端节点列表项展示改造:① 节点名改正式格式「地区 · 国家」(如 香港 · 中国),去掉测试名(当前 prod 节点 name_zh=单节点·测试);② 节点图标用国旗(按 region/国家码渲染 emoji 或 SVG 旗)。涉及:服务端 nodes 行的 name/region/国家码数据(可能需补国家码字段),客户端节点卡片渲染国旗+名格式。HK 节点国旗/国家标签需产品确认(🇭🇰香港 vs 🇨🇳中国)。
auth/service.go 异步发信把错误静默吞了(:157 SendCode 的 _=s.mailer.SendCode(...),:133 SendAlreadyRegistered 同样),导致 SMTP 故障日志无痕、本次 587 被封难排查。改为发信失败时记日志(slog.Error,脱敏:只记 send failed:<err>,绝不记验证码,邮箱可打码,守 no-secret-in-logs)。并加测试:注入会失败的 mock Mailer,断言发送失败时确实记了一条错误日志(可用 LogMailer 思路/捕获 slog handler 验证)。