diff --git a/client/.gitignore b/client/.gitignore index fd6e84f..3461274 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -44,6 +44,7 @@ app.*.map.json /android/app/debug /android/app/profile /android/app/release +/android/.gradle/ # iOS generated ios/Flutter/Generated.xcconfig diff --git a/todo/todo.html b/todo/todo.html index 1e620e6..7360431 100644 --- a/todo/todo.html +++ b/todo/todo.html @@ -77,6 +77,7 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; } .todo-card.s-accepted { border-left-color: #22c55e; background: #f0fdf4; opacity: .8; } .card-header { display: flex; align-items: flex-start; gap: 10px; flex-wrap: wrap; } +.item-id { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-weight: 700; font-size: 13px; color: #2563AC; background: #eef4fb; border: 1px solid #d3e2f3; border-radius: 6px; padding: 1px 7px; flex: 0 0 auto; } .item-title { font-weight: 600; font-size: 15px; flex: 1; } .todo-card.s-accepted .item-title { text-decoration: line-through; color: #52606d; } .card-badges { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; } @@ -252,13 +253,13 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }

feature+windows — 项目 TODO

-
生成于 2026-06-29 · 真相源 todo/todo.json
+
生成于 2026-06-30 · 真相源 todo/todo.json
-
12全部
-
7待开始
+
16全部
+
8待开始
0开发中
-
3待验收
-
2已验收
+
0待验收
+
8已验收
@@ -292,7 +293,7 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
平台 / 标签 - +
@@ -301,7 +302,7 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
- 📋 待开始 7 + 📋 待开始 8 ▴ 收起
@@ -314,6 +315,7 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; } data-tier="2" data-tags="mac">
+ #1 macOS 原生 KillSwitch 补齐 L0→L3
待开始 @@ -343,6 +345,7 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; } data-tier="2" data-tags="Android">
+ #2 Android KillSwitch L1 + 引导系统 Always-on
待开始 @@ -372,6 +375,7 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; } data-tier="3" data-tags="后端,运维">
+ #4 线上启用 TOTP 两步验证并验 2FA
待开始 @@ -401,6 +405,7 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; } data-tier="2" data-tags="后端">
+ #8 agent 掉线告警 + 静默吞错全量审计
待开始 @@ -430,6 +435,7 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; } data-tier="1" data-tags="前端,后端">
+ #12 协议选择(REALITY/Hysteria2/自动)端到端
待开始 @@ -452,6 +458,66 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
+
  • +
    + #14 + 移动端真·常连:Android Always-on + iOS/iPad On-Demand(无UI自连) +
    + 待开始 + 重要 + 一级 + + +
    +
    + +
    系统在 app 未开时拉起隧道:Android Always-on VPN(系统设置开启+VpnService 支持 onStartCommand 无UI拉起+配置缓存)、iOS/iPad On-Demand(NEOnDemandRule + PacketTunnelProvider 用缓存 lastConfigJson 自连)。难点:paid 凭证 TTL 仅24h,长期常连需原生侧刷新配置/凭证。桌面自启+全平台自动连接已在另一轮做(plan crystalline-exploring-lerdorf)。
    + + + +
  • + +
  • +
    + #16 + 启用设备数量限制 + 超限 UX(踢旧/选择移除,非硬拒登) +
    + 待开始 + 重要 + 一级 + + +
    +
    + +
    现状: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:涉及登录接口 + 跨后端/前端 + 策略设计。
    + + + +
  • +
  • + #3 Windows KillSwitch L1→L2 (WFP 防火墙强制)
    待开始 @@ -477,35 +544,6 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
    🕐 2026-06-22 -
    -
    -
  • - -
  • -
    - 清理旧命名 tablet golden 孤儿文件 -
    - 待开始 - 一般 / 优化 - 三级 - - -
    -
    - -
    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 合并而来)
    - - -
  • @@ -525,26 +563,68 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
    - 🔍 待验收 3 + 🔍 待验收 0 ▴ 收起
      +

      暂无条目

      +
    +
    +
    +
    +
    + ✅ 已验收 8 + ▾ 展开 +
    + -
  • -
    - 打通每设备归因(设备注册 + per-device dp_uuid) -
    - 待验收 - 重要 - 二级 - - -
    -
    - -
    现状:多设备共用账户级 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 缺行时自动建设备行。打通后每设备统计 + 统计页设备下拉才有真数据。是统计重设计「设备下拉」的前置依赖。
    - - - -
  • - -
  • + #10 统计页设备下拉接真实设备数据(依赖#上条)
    - 待验收 + 已验收 一般 / 优化 二级 - +
    @@ -613,21 +665,101 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
    前端
    🕐 2026-06-28 - + ✅ 验收 2026-06-30
  • - + +
  • +
    + #15 + iOS/iPad 实时统计+urltest 延迟与 macOS 对齐 +
    + 已验收 + 重要 + 二级 + + +
    +
    + +
    移植 macOS 已验证的统计架构:扩展注入 clash_api + StatsCollector(clash 取 urltest),app StatsClient 改 sendProviderMessage 轮询;前置生成 iOS Libbox.xcframework。Dart 侧已对齐(共用 VpnNativeBridge)。
    + + + -
    -
    - ✅ 已验收 2 - ▾ 展开 +
    +
  • + +
  • +
    + #9 + 打通每设备归因(设备注册 + per-device dp_uuid) +
    + 已验收 + 重要 + 二级 + + +
    +
    + +
    现状:多设备共用账户级 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 缺行时自动建设备行。打通后每设备统计 + 统计页设备下拉才有真数据。是统计重设计「设备下拉」的前置依赖。
    + + +
  • + +
  • +
    + #13 + 数据面故障韧性:节点健康上报+客户端连通看门狗 +
    + 已验收 + 高优 · 紧急 + 一级 + + +
    +
    + +
    agent 心跳带 sing-box 健康(clash_api /version)→控制面 effectiveNodeStatus 标 down(列表置灰+connect拦截);客户端连上后 HTTP 204 看门狗,连续失败:智能选择自动切节点/手动只提示断开。plan: crystalline-exploring-lerdorf.md
    + + + +
  • +
  • + #6 节点列表:正式名(地区·国家) + 国旗图标
    已验收 @@ -664,6 +797,7 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; } data-tier="3" data-tags="后端">
    + #5 SendCode 发信失败记日志 + 测试
    已验收 diff --git a/todo/todo.json b/todo/todo.json index eca0a3b..c5550f1 100644 --- a/todo/todo.json +++ b/todo/todo.json @@ -1,9 +1,9 @@ { "meta": { "title": "feature+windows — 项目 TODO", - "updated_at": "2026-06-29T00:04:33.913Z" + "updated_at": "2026-06-30T14:47:39.344Z" }, - "seq": 12, + "seq": 17, "items": [ { "id": 1, @@ -106,10 +106,10 @@ "tags": [ "后端" ], - "status": "done", + "status": "accepted", "created_at": "2026-06-28T00:26:44.498Z", - "done": false, - "completed_at": null, + "done": true, + "completed_at": "2026-06-30T14:44:35.082Z", "version": null }, { @@ -137,10 +137,10 @@ "前端", "后端" ], - "status": "done", + "status": "accepted", "created_at": "2026-06-28T09:32:26.008Z", - "done": false, - "completed_at": null, + "done": true, + "completed_at": "2026-06-30T14:44:34.810Z", "version": null }, { @@ -152,10 +152,10 @@ "tags": [ "前端" ], - "status": "done", + "status": "accepted", "created_at": "2026-06-28T09:32:26.080Z", - "done": false, - "completed_at": null, + "done": true, + "completed_at": "2026-06-30T14:44:34.991Z", "version": null }, { @@ -167,10 +167,10 @@ "tags": [ "前端" ], - "status": "open", + "status": "accepted", "created_at": "2026-06-28T11:27:56.637Z", - "done": false, - "completed_at": null, + "done": true, + "completed_at": "2026-06-30T14:47:39.343Z", "version": null }, { @@ -188,6 +188,72 @@ "done": false, "completed_at": null, "version": null + }, + { + "id": 13, + "title": "数据面故障韧性:节点健康上报+客户端连通看门狗", + "desc": "agent 心跳带 sing-box 健康(clash_api /version)→控制面 effectiveNodeStatus 标 down(列表置灰+connect拦截);客户端连上后 HTTP 204 看门狗,连续失败:智能选择自动切节点/手动只提示断开。plan: crystalline-exploring-lerdorf.md", + "level": "high", + "tier": 1, + "tags": [ + "后端", + "前端", + "gRPC" + ], + "status": "accepted", + "created_at": "2026-06-29T04:55:46.733Z", + "done": true, + "completed_at": "2026-06-29T16:59:39.926Z", + "version": null + }, + { + "id": 14, + "title": "移动端真·常连:Android Always-on + iOS/iPad On-Demand(无UI自连)", + "desc": "系统在 app 未开时拉起隧道:Android Always-on VPN(系统设置开启+VpnService 支持 onStartCommand 无UI拉起+配置缓存)、iOS/iPad On-Demand(NEOnDemandRule + PacketTunnelProvider 用缓存 lastConfigJson 自连)。难点:paid 凭证 TTL 仅24h,长期常连需原生侧刷新配置/凭证。桌面自启+全平台自动连接已在另一轮做(plan crystalline-exploring-lerdorf)。", + "level": "mid", + "tier": 1, + "tags": [ + "Android", + "iOS", + "后端" + ], + "status": "open", + "created_at": "2026-06-29T09:36:14.004Z", + "done": false, + "completed_at": null, + "version": null + }, + { + "id": 15, + "title": "iOS/iPad 实时统计+urltest 延迟与 macOS 对齐", + "desc": "移植 macOS 已验证的统计架构:扩展注入 clash_api + StatsCollector(clash 取 urltest),app StatsClient 改 sendProviderMessage 轮询;前置生成 iOS Libbox.xcframework。Dart 侧已对齐(共用 VpnNativeBridge)。", + "level": "mid", + "tier": 2, + "tags": [ + "iOS", + "前端" + ], + "status": "accepted", + "created_at": "2026-06-30T10:56:48.894Z", + "done": true, + "completed_at": "2026-06-30T14:44:34.900Z", + "version": null + }, + { + "id": 16, + "title": "启用设备数量限制 + 超限 UX(踢旧/选择移除,非硬拒登)", + "desc": "现状: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:涉及登录接口 + 跨后端/前端 + 策略设计。", + "level": "mid", + "tier": 1, + "tags": [ + "后端", + "前端" + ], + "status": "open", + "created_at": "2026-06-30T14:33:48.996Z", + "done": false, + "completed_at": null, + "version": null } ] }