Files
pangolin/todo/todo.json
T
wangjia 912a495e91 feat(deploy): 单节点全套部署脚本 deploy/single-node(档 3 真机准备)
一台全新 Ubuntu/Debian VPS 上一条命令起整套 pangolin:MySQL + Redis(docker)
+ 控制面(HTTP + gRPC agent 服务)+ 节点 agent + sing-box 数据面,客户端连该
VPS 公网 IP 真实出网。

- deploy.sh:幂等编排——构建二进制 → docker MySQL/Redis → 生成 JWT/webhook/
  derive 密钥 + Node CA + CA 签发的 gRPC server 证书(SAN localhost,匹配 agent
  enroll 后的 mTLS 校验)+ REALITY 密钥对(持久化跨重部署)→ migrate + seed 节点
  → 起控制面(走完整 gRPC 分支)→ nodectl bootstrap-token → 起 agent + sing-box。
- systemd/{pangolin-server,pangolin-agent,sing-box}.service、docker-compose.yml
  (MySQL/Redis 仅 loopback)、seed-node.sql.tmpl。
- README.md:架构图 + 部署/验证步骤 + 客户端接线(API URL / PANGOLIN_SINGBOX_BIN
  / sudoers / 真节点 uuid,客户端代码无改动)+ 排查指引。

本机验证:shellcheck + bash -n 通过;openssl CA ↔ mtls.NewCA + gRPC 证书链互通
已单测实测通过。VPS 端到端(出口 IP == VPS IP)待真机到位后执行。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 00:32:47 +08:00

682 lines
21 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"meta": {
"title": "doc — 项目 TODO",
"updated_at": "2026-06-16T15:22:21.051Z"
},
"seq": 23,
"items": [
{
"id": 1,
"title": "OpenAPI 契约 + MySQL migration 基线",
"desc": "依据 doc/02、doc/03openapi.yaml 展开全部 /v1 契约(connect 返回 sing-box 凭证而非 WG peer);MySQL 8 全量 DDLusers/devices/plans/subscriptions/codes/usage_daily/audit_log + providers/node_events/directory_version)。后端各模块的共同前置。",
"level": "high",
"tier": 1,
"tags": [
"后端",
"数据库"
],
"status": "doing",
"created_at": "2026-06-11T15:48:05.656Z",
"done": false,
"completed_at": null,
"version": null,
"subtasks": [
{
"sid": "1A",
"title": "Go 模块骨架 + 工具链(go.mod/tools.go/Makefile)",
"tier": 1,
"deps": [],
"status": "open",
"created_at": "2026-06-11T16:14:18.892Z"
},
{
"sid": "1B",
"title": "MySQL migration 7 文件 + plans seed",
"tier": 1,
"deps": [],
"status": "open",
"created_at": "2026-06-11T16:14:18.952Z"
},
{
"sid": "1C",
"title": "openapi.yaml 契约(13 操作 + 全量 schema)",
"tier": 1,
"deps": [],
"status": "open",
"created_at": "2026-06-11T16:14:19.013Z"
},
{
"sid": "1D",
"title": "oapi-codegen 接线 + 生成代码入库",
"tier": 1,
"deps": [
"1A",
"1C"
],
"status": "open",
"created_at": "2026-06-11T16:14:19.070Z"
},
{
"sid": "1E",
"title": "config + store(UTC DSN) + 自动迁移",
"tier": 1,
"deps": [
"1A",
"1B"
],
"status": "open",
"created_at": "2026-06-11T16:14:19.125Z"
},
{
"sid": "1F",
"title": "apierr + idgen + CONVENTIONS.md",
"tier": 2,
"deps": [
"1A"
],
"status": "open",
"created_at": "2026-06-11T16:14:19.182Z"
}
],
"gate": {
"kind": "plan",
"note": "openapi.yaml 13 端点 + MySQL 12 表 migration + plans seedgolang-migrate/oapi-codegen/chiconnect 返回 sing-box 凭证",
"ref": "doc/plans/01-openapi-mysql.md",
"approval": "pending",
"proposed_at": "2026-06-11T16:33:26.856Z",
"approved_at": null
}
},
{
"id": 2,
"title": "auth 模块(验证码/注册/登录/JWT",
"desc": "邮箱验证码限频、注册自动 7 天 PRO 试用、argon2id、JWT RS256access 15min + refresh 30d)、Redis 滑窗限流。依赖 #1。",
"level": "mid",
"tier": 2,
"tags": [
"后端"
],
"status": "open",
"created_at": "2026-06-11T15:48:05.707Z",
"done": false,
"completed_at": null,
"version": null
},
{
"id": 3,
"title": "codes 激活码模块",
"desc": "批量生成(Crockford Base32 + 校验位,库存 hash)、发卡店 webhook(HMAC)、兑换幂等 + 订阅顺延叠加、失败锁定、audit_log。依赖 #1。",
"level": "mid",
"tier": 2,
"tags": [
"后端"
],
"status": "open",
"created_at": "2026-06-11T15:48:05.764Z",
"done": false,
"completed_at": null,
"version": null
},
{
"id": 4,
"title": "devices + 订阅校验中间件",
"desc": "设备登记/移除(同步回收节点侧凭证)、套餐/到期/设备数校验中间件。依赖 #1、#2。",
"level": "mid",
"tier": 2,
"tags": [
"后端"
],
"status": "open",
"created_at": "2026-06-11T15:48:05.818Z",
"done": false,
"completed_at": null,
"version": null
},
{
"id": 5,
"title": "nodes 模块 + agent gRPC 协议设计",
"desc": "proto 定义(注册/心跳/凭证下发与回收/用量上报,mTLS 双向)、节点目录 version 灰度(if_version 304)、connect/disconnect 下发 REALITY/Hy2 参数、free 凭证 TTL。依赖 #1。",
"level": "high",
"tier": 1,
"tags": [
"后端"
],
"status": "doing",
"created_at": "2026-06-11T15:48:05.872Z",
"done": false,
"completed_at": null,
"version": null,
"subtasks": [
{
"sid": "5A",
"title": "proto 契约 + buf 工具链(最先冻结)",
"tier": 1,
"deps": [],
"status": "open",
"created_at": "2026-06-11T16:14:19.245Z"
},
{
"sid": "5B",
"title": "mTLS/CA + 引导 token 框架",
"tier": 1,
"deps": [],
"status": "open",
"created_at": "2026-06-11T16:14:19.299Z"
},
{
"sid": "5C",
"title": "gRPC server + hub + 跨实例 pub/sub",
"tier": 1,
"deps": [
"5A",
"5B"
],
"status": "open",
"created_at": "2026-06-11T16:14:19.356Z"
},
{
"sid": "5D",
"title": "目录灰度 + connect/disconnect + 凭证编排",
"tier": 1,
"deps": [
"5C"
],
"status": "open",
"created_at": "2026-06-11T16:14:19.415Z"
},
{
"sid": "5E",
"title": "生命周期状态机接口(供 #15)",
"tier": 1,
"deps": [
"5C"
],
"status": "open",
"created_at": "2026-06-11T16:14:19.471Z"
}
],
"gate": {
"kind": "plan",
"note": "agent gRPC proto(buf) + 控制面 nodes 模块;agent 主动拨号、下发服务端流、mTLS 内部CA、目录 version 灰度",
"ref": "doc/plans/05-nodes-grpc.md",
"approval": "pending",
"proposed_at": "2026-06-11T16:33:26.908Z",
"approved_at": null
}
},
{
"id": 6,
"title": "节点 agent 实现",
"desc": "轻量 agentmTLS 自注册、心跳、sing-box 用户表增删(凭证下发/回收/TTL)、负载上报 Rediscloud-init 一段式安装。依赖 #5 的 proto。",
"level": "mid",
"tier": 2,
"tags": [
"后端"
],
"status": "open",
"created_at": "2026-06-11T15:48:25.479Z",
"done": false,
"completed_at": null,
"version": null
},
{
"id": 7,
"title": "usage 用量 + 广告解锁",
"desc": "usage_daily 聚合(仅字节/分钟,无日志口径)、/v1/ads/unlock 验广告 SDK 回执、free 用户 connect 额度校验。依赖 #1。",
"level": "mid",
"tier": 2,
"tags": [
"后端"
],
"status": "open",
"created_at": "2026-06-11T15:48:25.532Z",
"done": false,
"completed_at": null,
"version": null
},
{
"id": 8,
"title": "管理端最小后台",
"desc": "码批次生成导出、节点操作(replace/draining)、audit_log 查看;独立监听 + 内网白名单 + 2FA。依赖 #1。",
"level": "low",
"tier": 2,
"tags": [
"后端",
"Web"
],
"status": "open",
"created_at": "2026-06-11T15:48:25.585Z",
"done": false,
"completed_at": null,
"version": null
},
{
"id": 9,
"title": "Flutter 客户端工程搭建(演示态跑通)",
"desc": "用 design/flutter/ 起步包建工程:pubspec 覆盖、theme/widgets/main 拷入、字体配置,flutter run 出登录→引导→主框架演示态。前端线起点,可与后端完全并行。",
"level": "high",
"tier": 2,
"tags": [
"前端",
"iOS",
"Android"
],
"status": "open",
"created_at": "2026-06-11T15:48:25.638Z",
"done": false,
"completed_at": null,
"version": null
},
{
"id": 10,
"title": "Flutter 逐屏还原 + iPad 断点",
"desc": "对照 ui_kits/mobile + tablet 逐屏补齐:智能选择推荐卡、免费额度卡+看广告解锁、Tab 滑动切换、宽度 ≥900 切侧栏分栏(连接页双栏/节点双列网格);四态验证(明暗×中英)。依赖 #9。",
"level": "mid",
"tier": 2,
"tags": [
"前端",
"iOS",
"Android"
],
"status": "open",
"created_at": "2026-06-11T15:48:25.690Z",
"done": false,
"completed_at": null,
"version": null
},
{
"id": 11,
"title": "sing-box libbox 桥接 PoC(三端隧道)",
"desc": "gomobile AAR/XCFramework + iOS NetworkExtension / Android VpnService / 桌面 TUN 子进程;URLTest 智能选线、Kill-switch。全项目最大技术风险,应尽早并行启动。",
"level": "high",
"tier": 1,
"tags": [
"前端",
"iOS",
"Android",
"mac",
"Windows"
],
"status": "doing",
"created_at": "2026-06-11T15:48:25.745Z",
"done": false,
"completed_at": null,
"version": null,
"subtasks": [
{
"sid": "11A",
"title": "数据面定稿 + 修订 ARCHITECTURE.md connect 契约",
"tier": 1,
"deps": [],
"status": "open",
"created_at": "2026-06-11T16:14:37.334Z"
},
{
"sid": "11B",
"title": "app/kernel 构建管线(AAR/XCFramework/桌面二进制)",
"tier": 1,
"deps": [],
"status": "open",
"created_at": "2026-06-11T16:14:37.389Z"
},
{
"sid": "11C",
"title": "桥接 API 面(Channel 契约 + 三端原生骨架)",
"tier": 1,
"deps": [],
"status": "open",
"created_at": "2026-06-11T16:14:37.447Z"
},
{
"sid": "11D",
"title": "桌面端 PoC M1(首发打通)",
"tier": 1,
"deps": [
"11A",
"11B",
"11C"
],
"status": "open",
"created_at": "2026-06-11T16:14:37.504Z"
},
{
"sid": "11E",
"title": "Android 端 PoC M2",
"tier": 1,
"deps": [
"11B",
"11C"
],
"status": "open",
"created_at": "2026-06-11T16:14:37.561Z"
},
{
"sid": "11F",
"title": "iOS 端 PoC M3 + entitlement 申请",
"tier": 1,
"deps": [
"11B",
"11C"
],
"status": "open",
"created_at": "2026-06-11T16:14:37.616Z"
},
{
"sid": "11G",
"title": "URLTest + Kill-switch + 弹性重连 M4/M5",
"tier": 2,
"deps": [
"11D"
],
"status": "open",
"created_at": "2026-06-11T16:14:37.672Z"
},
{
"sid": "11H",
"title": "控制面联调 M6",
"tier": 2,
"deps": [
"11A"
],
"status": "open",
"created_at": "2026-06-11T16:14:37.731Z"
}
],
"gate": {
"kind": "plan",
"note": "gomobile libbox + Platform Channel + 三端壳;首发桌面→Android→iOS;含数据面定稿 11A",
"ref": "doc/plans/11-libbox-bridge.md",
"approval": "pending",
"proposed_at": "2026-06-11T16:33:26.957Z",
"approved_at": null
}
},
{
"id": 12,
"title": "官网 Astro 迁移",
"desc": "ui_kits/website → Astro SSG + Cloudflare Pages 多镜像;保留 i18n 单显、响应式断点、全部脱敏文案。完全独立可并行。",
"level": "mid",
"tier": 2,
"tags": [
"Web",
"前端"
],
"status": "open",
"created_at": "2026-06-11T15:48:45.836Z",
"done": false,
"completed_at": null,
"version": null
},
{
"id": 13,
"title": "Web 用户中心(Next.js",
"desc": "ui_kits/usercenter React 组件直接复用;先 mock 数据,后接 me/redeem/devicesTOTP 2FA。UI 部分独立并行,接口联调依赖 #2。",
"level": "mid",
"tier": 2,
"tags": [
"Web",
"前端"
],
"status": "open",
"created_at": "2026-06-11T15:48:45.886Z",
"done": false,
"completed_at": null,
"version": null
},
{
"id": 14,
"title": "弹性节点基建:Terraform + 一键更换",
"desc": "多厂商 API 适配层(providers 池)、cloud-init 模板、replace 一键更换(make-before-break)与全量滚动轮换、换 IP 不换机。依赖 #6 的 agent。",
"level": "mid",
"tier": 2,
"tags": [
"CI/CD",
"后端"
],
"status": "open",
"created_at": "2026-06-11T15:48:45.936Z",
"done": false,
"completed_at": null,
"version": null
},
{
"id": 15,
"title": "探针判封 + 自动更换 scheduler",
"desc": "境内多 ISP 拨测 + 境外对照 + 流量骤降三路互证;blocked_suspect/confirmed 状态机、阈值与熔断、池水位告警、自动补新。依赖 #5、#14。",
"level": "high",
"tier": 1,
"tags": [
"后端"
],
"status": "doing",
"created_at": "2026-06-11T15:48:45.987Z",
"done": false,
"completed_at": null,
"version": null,
"subtasks": [
{
"sid": "15A",
"title": "探针汇聚入口 + Redis 探针存储",
"tier": 1,
"deps": [],
"status": "open",
"created_at": "2026-06-11T16:14:37.789Z"
},
{
"sid": "15B",
"title": "轻量探针客户端 L1/L2/L3",
"tier": 1,
"deps": [
"15A"
],
"status": "open",
"created_at": "2026-06-11T16:14:37.845Z"
},
{
"sid": "15C",
"title": "第三方拨测 API 适配",
"tier": 2,
"deps": [
"15A"
],
"status": "open",
"created_at": "2026-06-11T16:14:37.900Z"
},
{
"sid": "15D",
"title": "判定引擎 signals+rules+streak",
"tier": 1,
"deps": [
"15A"
],
"status": "open",
"created_at": "2026-06-11T16:14:37.959Z"
},
{
"sid": "15E",
"title": "自动更换编排 + 养机灰度",
"tier": 1,
"deps": [
"15D"
],
"status": "open",
"created_at": "2026-06-11T16:14:38.015Z"
},
{
"sid": "15F",
"title": "容量水位 + 熔断器",
"tier": 2,
"deps": [
"15E"
],
"status": "open",
"created_at": "2026-06-11T16:14:38.072Z"
},
{
"sid": "15G",
"title": "告警出口 TG bot + runbook",
"tier": 2,
"deps": [
"15D"
],
"status": "open",
"created_at": "2026-06-11T16:14:38.130Z"
},
{
"sid": "15H",
"title": "scheduler 装配 + 选主 + 优雅退出",
"tier": 1,
"deps": [
"15D",
"15E"
],
"status": "open",
"created_at": "2026-06-11T16:14:38.187Z"
}
],
"gate": {
"kind": "plan",
"note": "探针汇聚入口 + 三路互证判定引擎 + make-before-break 自动更换 + 熔断;Go 单体 goroutine + Redis 选主",
"ref": "doc/plans/15-probe-scheduler.md",
"approval": "pending",
"proposed_at": "2026-06-11T16:33:27.007Z",
"approved_at": null
}
},
{
"id": 16,
"title": "域名池 + CDN 前置 + 签名端点分发",
"desc": "四组域名隔离与冷备池、源站隐藏(回源鉴权)、Ed25519 签名端点更新与公告 JSON 多镜像、客户端 DoH/IP 直连兜底联动。可独立并行。",
"level": "mid",
"tier": 2,
"tags": [
"Web"
],
"status": "open",
"created_at": "2026-06-11T15:48:46.039Z",
"done": false,
"completed_at": null,
"version": null
},
{
"id": 17,
"title": "备份与灾备演练",
"desc": "xtrabackup 每日全量 + binlog 15min 增量、age 加密异地(独立身份账号)、月度恢复演练脚本、RPO≤15min/RTO≤4h 验证。",
"level": "mid",
"tier": 3,
"tags": [
"数据库",
"CI/CD"
],
"status": "open",
"created_at": "2026-06-11T15:48:46.090Z",
"done": false,
"completed_at": null,
"version": null
},
{
"id": 18,
"title": "CI 流水线",
"desc": "lint + 单测 + OpenAPI 同步校验 + 脱敏红线词扫描(UI 文案资源)+ 容器镜像构建。",
"level": "low",
"tier": 3,
"tags": [
"CI/CD"
],
"status": "open",
"created_at": "2026-06-11T15:48:46.141Z",
"done": false,
"completed_at": null,
"version": null
},
{
"id": 19,
"title": "Flutter 逐屏还原+iPad断点: l10n/Riverpod/三态连接/推荐卡/额度卡/Tab滑动/≥900分栏/golden/CI红线",
"desc": null,
"level": "mid",
"tier": null,
"tags": [],
"status": "done",
"created_at": "2026-06-13T06:08:14.230Z",
"done": false,
"completed_at": null,
"version": null
},
{
"id": 20,
"title": "修复 macOS keychain entitlement (-34018) 导致登录写 token 失败",
"desc": "flutter_secure_storage 在未签名 macOS app 上 write keychain 抛 PlatformException -34018 'A required entitlement isnot present'。真实登录成功后调 saveTokens 写 keychain 会卡住/抛异常。需给 macos entitlements 加 keychain-access-groups,或 TokenStore.saveTokens 加错误兜底。当前 debug 用 devLogin 内存旁路绕过。栈: token_store.dart:17 / auth_provider.dart:44 / auth_screen.dart",
"level": "mid",
"tier": 2,
"tags": [
"前端",
"mac"
],
"status": "done",
"created_at": "2026-06-15T23:36:58.366Z",
"done": false,
"completed_at": null,
"version": null
},
{
"id": 21,
"title": "客户端三端布局架构(mobile/tablet/desktop) + desktop 对齐设计稿",
"desc": "用 design-distill skill 重做:form_factor 三端判定 + shell/ 三端外壳(desktop_shell 对照 ui_kits/desktop/dapp.jsx:侧栏204·6项+套餐卡+顶栏主题切换+居中单列连接页) + navigation_provider(6视图) + contact_page/settings_page 一级页 + 截图diff验收。根因:MainFlutterWindow nib默认<900走窄屏;现宽屏分支是tablet双栏非desktop单列。plan: ~/.claude/plans/majestic-kindling-boole.md",
"level": "high",
"tier": 1,
"tags": [
"前端",
"mac"
],
"status": "done",
"created_at": "2026-06-16T00:49:45.404Z",
"done": false,
"completed_at": null,
"version": null
},
{
"id": 22,
"title": "档2: 接真后端(本机置备 + 客户端去旁路/修keychain)",
"desc": "后端/客户端已就绪,只差: dev/ 本机置备(docker MySQL+Redis + JWT密钥 + migrate + seed节点 + run-local.sh) + 客户端修keychain(MacOsOptions useDataProtectionKeyChain:false) + 删dev旁路。验收: mac app 真注册→登录→拉真节点。plan: ~/.claude/plans/majestic-kindling-boole.md",
"level": "high",
"tier": 1,
"tags": [
"后端",
"前端",
"mac",
"CI/CD"
],
"status": "done",
"created_at": "2026-06-16T05:06:43.335Z",
"done": false,
"completed_at": null,
"version": null
},
{
"id": 23,
"title": "档3 真实连接出网:新 VPS 全套部署(代码+部署脚本)",
"desc": "nodectl bootstrap-token 子命令 + deploy/single-node 一键部署脚本 + systemd unit;本机编译验证,机器到位端到端测试",
"level": "high",
"tier": 1,
"tags": [
"后端",
"部署",
"CI/CD"
],
"status": "doing",
"created_at": "2026-06-16T15:22:03.653Z",
"done": false,
"completed_at": null,
"version": null,
"gate": {
"kind": "plan",
"note": "nodectl bootstrap-token 子命令 + deploy/single-node 部署脚本",
"ref": "/Users/wangjia/.claude/plans/majestic-kindling-boole.md",
"approval": "pending",
"proposed_at": "2026-06-16T15:22:20.983Z",
"approved_at": null
}
}
]
}