wangjia
95fad37989
test(client): L2 登陆/重启续登/登出 流程(真 AuthNotifier)
...
驱动真实 AuthNotifier(非桩),仅在可注入接缝 TokenStore 处换内存实现,覆盖最初诉求:
- 登陆:saveTokens → isLoggedIn + 令牌持久化
- 重启续登:新 AuthNotifier 从同一 store 恢复登录态(无需重输密码)
- 登出:logout → 未登录 + store 清空,再重启仍未登录
- 3 用例全过
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 12:10:52 +08:00
wangjia
cb6fc25bc9
test(client): L1 数值格式化纯函数单测 + 从 widget 抽出(支柱3)
...
- lib/util/format.dart:抽出 formatSpeed/formatDuration(原私有于 connect_page
_speed / connect_button _fmt,混在 widget 里没法单测)
- connect_page/connect_button 改用公共纯函数(渲染输出不变)
- test/unit/format_test.dart:10 用例覆盖速率 B/s→GB/s 各单位边界 +
时长 HH:MM:SS 补零/小时不封顶/取模 60
- 验证:format 10 + widget 8 全过、analyze 无 error/warning
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 12:06:34 +08:00
wangjia
64f96fe018
refactor(api): /v1/me 收敛 expire_at → 只发 expires_at(无 web 用户中心)
...
之前后端同时发 expire_at + expires_at(分别给 app + web 用户中心)。现已无 web 端,
双发是纯冗余,统一只用 expires_at:
- account.go:meResponse 删 ExpireAt 字段 + GetMe handler 不再赋值
- client me.dart:fromJson 删 (expires_at ?? expire_at) 别名回退
- 两端契约快照同步:Go meResponse 冻结集去 expire_at(12→11 key)、删 Dart 别名测试
- 验证:go test httpapi 绿、flutter test contract(14)绿、analyze EXIT 0、e2e 全链路绿
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 10:08:50 +08:00
wangjia
dbd183ee00
fix(ci): 修 flutter analyze 闸长期 exit 1(形同虚设)
...
发现:CI flutter analyze 退出码 1(1204 个 info,0 error/warning),其中 1191 来自
第三方 vendored 包 lucide_icons_patched —— 这道闸一直红/无效。
- analysis_options.yaml:exclude packages/lucide_icons_patched/**(去 1191 噪音)
- ci.yml:flutter analyze --no-fatal-infos(info 是建议级不该硬挡 merge;
error/warning 仍致命)→ analyze EXIT 0、闸真正可用
- 顺手清 11 个 clean 文件 info:auth_api 删 >>>AUTHLOG 调试 print 残留(+unused sw)、
account_page/plan_card withOpacity→withValues、vpn_bridge where(is Map)→whereType、
测试文件删多余 import + final→const
- 剩 2 个 info 在 stats-overhaul dirty 文件(stats_page/device_stat_row),留其合并清
- 验证:flutter analyze --no-fatal-infos EXIT 0(1204→2)、flutter test 48 全过
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 07:39:14 +08:00
wangjia
6bd5c04cba
test(ci): 第5刀c e2e-smoke CI job + 文档 L4 状态更新
...
- ci.yml 新增 e2e-smoke job(golang:1.25 + apt openssl/curl/python3);容器内无
docker daemon → 脚本走内嵌 miniredis 兜底,无需 docker-in-docker——CI 走的
正是本机已验证绿的同款路径
- docs/test-architecture.html:L4 从「完全缺·最大缺口」更新为已落地
scripts/e2e-smoke.sh + server/test/e2e/
- 注:本机无 docker,e2e job 未在真 nas runner 实跑;逻辑等同本机已绿的
miniredis 路径,首次 CI 运行需观察 apt 包/go module 下载
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 07:06:35 +08:00
wangjia
fd82d82fe3
test(e2e): 第5刀b L4 gRPC 全链路(enroll→ReportUsage→统计真入库真读出)
...
在 HTTP 段基础上接 gRPC mTLS 全链路,真验证「统计准不准」:
- 脚本:生成 Node CA + gRPC server 证书(镜像 deploy.sh)、起 server 带 gRPC、
nodectl 签 bootstrap token,传 E2E_GRPC_ADDR/CA/token/node 给 driver
- driver:复用 agentd.EnsureEnrolled 真 TCP enroll → enroll 到的 client cert
建 mTLS → ReportUsage 注入 1GiB/100MiB(dp_uuid=用户) → 轮询 /v1/usage
断言 bytes_up=1GiB·bytes_down=100MiB 真入库真读回
- 本地全链路绿;go build ./... 不受影响(tag e2e)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 07:04:26 +08:00
wangjia
b3cbeef7cf
test(e2e): 第5刀a L4 进程级冒烟编排 + HTTP 段
...
真起 server 二进制(sqlite + Redis)跑 HTTP 用户旅程,验证 in-process 测试给不了的
信心(二进制起/迁移/路由/鉴权/DB 端到端):
- scripts/e2e-smoke.sh:起栈编排(Redis 三选一:已有 addr / docker / 内嵌 miniredis
兜底)+ 随机端口 + trap 清理;调 Go driver
- server/test/e2e/smoke_test.go (tag e2e):造用户(复用 argon2 HashPassword)
→ 登录 → /v1/me(dp_uuid/plan/email) → /v1/usage 鉴权 + 无 token 401
- server/test/e2e/miniredis (tag e2e):无 docker 时 Redis 兜底 launcher
- 本地绿;go build/test ./...(无 tag)仍 25 包绿,tag e2e 文件被静默跳过
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 06:59:39 +08:00
wangjia
6df453f057
test(ci): 第4刀a pre-commit hook(闸3 提交前本地把关)
...
复用 CI 同款检查的快子集,提交前本地拦截:
- .githooks/pre-commit:红线词 + 可移植SQL + codegen 漂移(成功静默/失败打详情)
- ci/install-hooks.sh:一键启用(core.hooksPath=.githooks)
- 不放 flutter/go test(慢,留 CI 闸4);可 --no-verify 临时跳过
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-24 23:49:41 +08:00
wangjia
747ceb06f0
test(contract): 第2刀c Go 契约快照(/v1/me·usage·UsageEntry)+ Go CI job
...
支柱 2(契约单源)后端守门 + 两端对账:
- httpapi/contract_test.go:冻结 /v1/me 字段面(12 key,与 Dart _frozenMeKeys 对账,
注明后端多发 uuid/dp_uuid + expire_at 别名)
- usage/contract_test.go:冻结 /v1/usage(UsagePoint)、/v1/usage/devices
(DeviceUsagePoint + envelope)字段面
- pb/agentv1/contract_test.go:冻结 agent↔控制面 UsageEntry 字段面
- ci.yml:新增 go-server job(golang:1.25 build+test)——此前 server 测试未进 CI
- 本地:5 契约用例 + 全量 go test ./...(25 包)绿
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-24 23:35:23 +08:00
wangjia
149aa90cfa
test(contract): 第2刀b Dart 契约快照(stats + /v1 API 字段面冻结)
...
支柱 2(契约单源)守门 — 堵 mac-stats-0 一类跨进程契约悄悄分叉:
- test/contract/stats_contract_test.dart:冻结 pangolin/vpn/stats payload
字段面 + status 四值,改契约即测试红、逼同步原生产出端 + 文档
- test/contract/api_contract_test.dart:冻结 /v1/me、/v1/usage、
/v1/usage/devices 的 snake_case 字段面
- ci.yml:flutter job 测试纳入 test/contract;本地 15 用例全过
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-24 23:32:00 +08:00
wangjia
c34d8d8fb5
test(ci): 第2刀a codegen 漂移检查(token 单源不漂移)
...
支柱 2(契约单源)守门:
- ci/check-codegen-drift.sh:重生成 pangolin_tokens.gen.dart,与已提交版本
不一致即失败(改了 CSS 真相源没重生成,或手改了生成物 *.gen.dart)
- ci.yml:新增 codegen-drift job(node:20 镜像,含 git/bash)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-24 23:28:41 +08:00
wangjia
2bf6701def
test(ci): 第1刀 可移植 SQL 扫描硬闸 + 五支柱 PR 自检模板
...
执行机制四道闸 → 闸4(CI 硬闸) + 评审兜底落地:
- ci/scan-portable-sql.sh:扫 server Go 运行时查询禁用 MySQL 专属构造
(UTC_TIMESTAMP/UTC_DATE/NOW()/FIELD(/ON DUPLICATE KEY/IFNULL),
豁免方言层 dialect*.go / _test.go / 注释行;当前 152 文件 0 违规
- ci.yml:新增 portable-sql-scan job;push 触发路径补 server/**
- .gitea/PULL_REQUEST_TEMPLATE.md:可测试性五支柱 + 测试 + 红线自检清单
- 守支柱 3(纯逻辑/IO 分离·双库可移植),见 docs/dev-conventions.html
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-24 23:25:26 +08:00
wangjia
29ddd5b453
docs(test): 测试框架架构 + 开发规范五支柱文档
...
- docs/test-architecture.html:分层测试金字塔(L0契约→L4 E2E) + 契约接缝
数据流 + 四类诉求映射 + CI 流水线 + E2E 拓扑,5 张内联 SVG/表格图
- docs/dev-conventions.html:可测试性五支柱(接缝即接口/契约单源/纯逻辑分离/
错误是值/可观测) + 支柱↔测试层咬合矩阵 + 反例对照表 + 执行机制四道闸
- docs/index.html:登记两份文档到知识库/调研,双向互链
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-24 23:25:14 +08:00
wangjia
2a1208a41c
Merge worktree-monitor-debounce: server #5 国内分流 DNS 面 + #12 链路诊断端点 + VPN 测试工具
...
ci-pangolin / Lint — shellcheck (push) Has been cancelled
ci-pangolin / OpenAPI Sync Check (push) Has been cancelled
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Has been cancelled
ci-pangolin / Flutter — analyze + test (push) Has been cancelled
- clientconfig.go(#5 ):开分流时 geosite-cn 域名走 local(223.5.5.5)直连解析,
避免国内 DNS 绕道出海多一个 RTT(splitActive 门控,不动既有 hijack-dns)
- diag.go(#12 ):新增公开诊断端点 /v1/diag/egress,白名单限定(anti-SSRF)、
只返回节点→目标出海段 TCP-443 耗时,供白盒拆接入段/出海段
- main.go:PANGOLIN_PUBLIC_URL 未设时告警(否则 split_cn 静默失效)
- scripts/vpn_test.py + vpn_whitebox.py + tests/vpn:黑/白盒测试工具
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-23 10:55:47 +08:00
wangjia
62925a6886
Merge worktree-windows-icon-tray-fix: Windows 桌面/托盘/任务栏图标 + 关窗不断连接
...
- 关窗(X/Alt+F4)隐藏到托盘并保持隧道,真退出只走托盘菜单(Platform.isWindows 隔离)
- 窗口标题设「穿山甲」(无 VPN 字眼)
- Windows 托盘改用 .ico(Win32 只认 ico,PNG 空白),mac/Linux 仍 PNG
- 更新 app_icon.ico / tray_icon.ico / Runner.rc / installer
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-23 10:54:23 +08:00
wangjia
e4db3beba6
Merge branch 'main' into feature/pangolin-ios
...
ci-pangolin / Lint — shellcheck (push) Has been cancelled
ci-pangolin / OpenAPI Sync Check (push) Has been cancelled
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Has been cancelled
ci-pangolin / Flutter — analyze + test (push) Has been cancelled
# Conflicts:
# client/lib/bridge/vpn_bridge_provider.dart
# docs/index.html
2026-06-23 10:05:20 +08:00
wangjia
e25649cd27
feat(client/ios): iPad tablet 正式适配——断点≥900 对齐设计源 + tablet golden 回归闸
...
- form_factor 触屏 tablet 阈值 600→900,对齐 design/ui_kits/tablet(1180×820 横屏
侧栏):iPad 横屏/12.9″竖屏走侧栏,标准/11″竖屏回落 mobile 底 Tab,避免双栏挤压
- form_factor_test 补全断点边界(900/899)与各 iPad 尺寸用例
- 新增 tablet_pages_golden_test:四视图×明暗×中英 12 张 golden,注入演示数据
(6 节点/周流量/30 天用量)让 2 列网格与周柱满渲染,作回归闸
- design/CONTRACT.md:tablet 像素契约(取自 tabapp.jsx)+ 逐屏验收清单
- 真机 iPad mini 6 视觉签核通过;141 测试全绿
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-23 10:00:14 +08:00
wangjia
11ee3342bf
feat(client/ios): 补齐 App 图标(iPhone+iPad 全尺寸,去 alpha)
...
iOS AppIcon.appiconset 只有 Contents.json、无任何 PNG → 桌面图标空白。
以 design 单源 assets/app-icon.svg(去圆角 rx=0 全幅方形)经 qlmanage 渲染 1024,
flutter_launcher_icons 铺开 21 张全尺寸(含 iPad 76/83.5)并去 alpha(App Store 合规)。
新增 dev_dep flutter_launcher_icons + 配置块,改图标重渲源图后 dart run 即可。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-23 00:39:37 +08:00
wangjia
bd984feff9
fix(client/ios): iOS 接通原生隧道——切真桥 + save-before-start + DNS matchDomains
...
根因:iOS 端 vpn_bridge_provider 把 iOS 归入'其他平台 → VpnBridgeMock',
整个 App 用假桥,伪造已连接状态与写死的 URLTest 延迟(18/32/54ms),从不调用
B1/C1 打通的原生 NEPacketTunnelProvider。表现为 UI 显示已连接但流量全直连
(apple 通/google 被墙、RTT 20ms),设备日志无任何隧道/sing-box/节点痕迹。
三处修复:
1. vpn_bridge_provider.dart: iOS → VpnNativeBridge(真原生 MethodChannel)。
2. VpnManager.start(): 先 saveToPreferences+重载(首启触发系统授权、持久化配置)
再 startVPNTunnel,否则对未持久化 manager 调用抛 NEVPNError。对齐 macOS。
3. PacketTunnelProvider.openTun: DNS 补 matchDomains=[""],强制所有 DNS 走隧道,
iOS 不设会把隧道 DNS 当补充解析器、查询仍走系统直连 DNS 致污染打不开站点。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-23 00:28:53 +08:00
wangjia
9b365c7e1c
fix(client/ios): PacketTunnel 引入 Generated.xcconfig 注入版本号
...
扩展 Info.plist 的 CFBundleVersion=$(FLUTTER_BUILD_NUMBER) 因 target 未引
Flutter 的 Generated.xcconfig 而展开为空串,iOS 装机校验 MissingBundleVersion
(code 33) 拒绝安装。给 PacketTunnel 三个 build config 加 baseConfiguration
Reference 指向 Generated.xcconfig(纯 Flutter 变量,无 Pods,不破坏 OTHER_LDFLAGS=""),
使扩展版本号 = 主 App = 1.0.0(1),满足 App Extension 版本须与 host app 一致的上架要求。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 23:59:05 +08:00
wangjia
d4d211124c
Merge: Android 官方穿山甲启动图标(自适应)
...
ci-pangolin / Lint — shellcheck (push) Has been cancelled
ci-pangolin / OpenAPI Sync Check (push) Has been cancelled
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Has been cancelled
ci-pangolin / Flutter — analyze + test (push) Has been cancelled
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 23:42:57 +08:00
wangjia
f3f91cc0ff
feat(android): 启动图标改用官方穿山甲(自适应图标)
...
前景 path 取自官方 client/assets/logo-mark-white.svg(原样,非重绘),仅加 Android 安全区居中;
背景为 app-icon.svg 的橙色渐变(#C8794A→#9E5630);删除占位三角 drawable/ic_launcher.xml。
Vivo X200/华为 DCO-AL00 真机验证图标显示正常。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 23:42:18 +08:00
wangjia
76d8e57a44
build(client/ios): B1 完成——PacketTunnel 链接 libbox+系统框架,iOS 构建打通
...
- PacketTunnel 链 Libbox.xcframework(静态,只Link不Embed)+ NetworkExtension
+ SystemConfiguration + libresolv.tbd + UIKit(libbox iOS 引用 UIApplication);
OTHER_LDFLAGS="" 切 CocoaPods 继承,FRAMEWORK_SEARCH_PATHS 指 Frameworks/
- 桥接头手动声明 sockaddr_ctl/ctl_info(iOS SDK 无 kern_control.h,稳定内核 ABI)
- 部署目标 iOS 12→14(os.Logger 需 14;低版老机不再兼容,用户拍板)
- 修预存脚手架坑: Podfile 删悬空 RunnerTests; Info.plist 移出 Resources(双产出);
Runner 构建阶段重排(Embed App Extensions 前置, Thin Binary 殿后) 解依赖环
- 验证: flutter build ios 通过, C1 Provider 编译通过, otool -L 扩展零外部 @rpath
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 22:20:49 +08:00
wangjia
381a621d77
feat(client/ios): Provider 对齐 macOS libbox 集成(CommandServer+utun fd)+ 内存监控
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-22 20:58:03 +08:00
wangjia
33a3508489
build(client/ios): 引入 iOS libbox 框架 + gitignore 排除产物
2026-06-22 20:52:28 +08:00
wangjia
99695e8861
test(client): 锁定 form_factor 断点(iPad→tablet, iPhone→mobile)
2026-06-22 20:51:34 +08:00
wangjia
867107515d
Merge: Android 客户端端到端连通 MVP(Task 1-7)
...
ci-pangolin / Lint — shellcheck (push) Has been cancelled
ci-pangolin / OpenAPI Sync Check (push) Has been cancelled
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Has been cancelled
ci-pangolin / Flutter — analyze + test (push) Has been cancelled
Flutter Android 接入内嵌 sing-box(libbox)隧道,Vivo X200/Android16 真机验证科学上网通过。
切节点(Task9)/KillSwitch(Task10)为后续。
2026-06-22 20:48:08 +08:00
wangjia
d0919943f5
fix(android): 真机连通修复——补 ACCESS_NETWORK_STATE + 砍 IPv6 zone(Task 7)
...
Vivo X200(Android 16)真机实测两处运行期崩溃并修复:
- DefaultNetworkMonitor 用 ConnectivityManager 需 ACCESS_NETWORK_STATE 权限(缺则 SecurityException)
- getInterfaces 返回的 IPv6 link-local 含 zone(%rmnet_data0),sing-box netip.ParsePrefix panic;substringBefore('%') 砍掉
真机端到端连通已由用户验证通过。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 20:43:49 +08:00
wangjia
c1fddcdf99
docs(android): 修正工具链记录(降Go保pin→SagerNet gomobile fork+5层环境修复)
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 20:05:50 +08:00
wangjia
126c06833d
feat(android): libbox 隧道重写对接真实 1.13.12 API,APK 编译通过(Task 5)
...
原生层照 PoC 旧/想象 API 写,与真实 sing-box 1.13.12 libbox 差距是架构级:
- 包名 libbox(非 go.libbox);无 BoxService,改 Libbox.setup + CommandServer 模型
- PangolinVpnService 重写:实现完整 PlatformInterface(15法)+CommandServerHandler
- 新增 DefaultNetworkMonitor(上报默认接口,缺则报 no available network)
- openTun 适配真实 TunOptions(RoutePrefixIterator/getMTU/StringBox DNS)
- 统计/切节点经 CommandClient(uplinkTotal/selectOutbound);MainActivity 接线
构建环境矩阵打通:Gradle 8.7(Java21)+声明式插件迁移+AGP 8.6+Kotlin 2.2.0+占位图标
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 19:28:24 +08:00
wangjia
53a2ee0b74
docs(client/ios): plan 增 HTML 阅读版 + 登记索引(双产物:.md 执行/.html 阅读)
2026-06-22 19:27:45 +08:00
wangjia
e11c06225d
plan(client/ios): iOS+iPad 支持实施计划(6 阶段/12 任务,TestFlight 里程碑)
...
A 补 libbox / B Xcode 接线 / C Provider 重写对齐 macOS / D 真机连通+内存双闸 /
E iPad 横竖屏适配 / F TestFlight 分发。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 19:22:05 +08:00
wangjia
84912f4dea
docs(client/ios): iOS+iPad 支持设计方案(TestFlight 里程碑)+ 新建 docs 索引
...
五条工作线:libbox iOS 框架 / Provider 对齐 macOS 修复 / App Group IPC /
iPad 布局横屏适配 / TestFlight 分发;头号风险 NE ~50MB 内存红线设双闸。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 19:06:20 +08:00
wangjia
2a8426c357
fix(android/kernel): 补 -checklinkname=0 ldflags + JDK 自动探测,构建出 40MB libbox.aar
...
对齐 sing-box build_libbox sharedFlags 的 -ldflags(含 -checklinkname=0 放行
badlinkname 的 //go:linkname;-trimpath/-buildvcs=false/版本戳);
JDK 自动选 Android Studio JBR(macOS /usr/bin/javac 仅桩)。Task 2 完成:
三 ABI(arm64/armeabi-v7a/x86_64) libgojni.so 齐。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 18:59:14 +08:00
wangjia
f298b207fe
fix(android/kernel): gomobile 改用 SagerNet fork v0.1.12 + 补 linkname tags
...
原 pin golang.org/x/mobile@v0.0.0-20240604...70c4c5da7d30 是失效 revision;
对照 sing-box v1.13.12 go.mod 与 cmd/internal/build_libbox,官方用
github.com/sagernet/gomobile@v0.1.12;补 badlinkname,tfogo_checklinkname0
以适配 Go 1.24 的 //go:linkname 限制。Task 2 blocker 修复。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 18:48:58 +08:00
wangjia
82741ce0c4
feat(android): Dart provider 接 Android→VpnNativeBridge(Task 4)
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 18:48:58 +08:00
wangjia
64c427cf11
docs(android): Android 设计方案+KillSwitch 知识库(HTML)+文档索引+实现计划
...
- docs/android-client-design.html / killswitch-design.html / index.html
- docs/superpowers/plans/2026-06-22-android-client.md
- todo/ KillSwitch 三端待办(#1 mac/#2 Android/#3 Windows)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 18:44:50 +08:00
wangjia
5ea4e1ae03
fix(client/windows): 任务栏图标 + 关闭窗口不再断连接
...
- 关闭窗口断连接:onExitRequested 原先无条件 _teardownVpn 再退出;Windows 点 X
会触发该回调拆隧道,而 window_manager 的 preventClose 又把窗口仅隐藏到托盘
→ 出现「一关就断网、进程还在」。改为 Windows 下点 X/Alt+F4 取消退出+隐藏,
保持隧道;真正退出只走托盘「退出」(onBeforeQuit 标记 _isQuitting 再拆隧道)。
macOS Cmd+Q 仍正常拆隧道退出。
- 任务栏图标没换:仅靠 WNDCLASS.hIcon(LoadIcon 单尺寸)任务栏可能拿不到正确
尺寸。窗口创建后用 LoadImage 按系统 SM_CXICON/SM_CXSMICON 各取一份,
WM_SETICON 显式设 ICON_BIG(任务栏/Alt-Tab)+ ICON_SMALL(标题栏)。
- 版本 1.0.1 → 1.0.2。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 17:53:34 +08:00
wangjia
94993b21b4
fix(client/windows): 修桌面/标题栏图标 + 标题文案 + 系统托盘空白
...
- app_icon.ico 重新由 assets/app-icon.svg 生成(穿山甲品牌图标,多尺寸),
替换残留的默认 Flutter logo —— 同时修好桌面图标与标题栏小图标。
- 窗口标题去掉 "VPN" 字眼:main.cpp 原生标题 pangolin_vpn → Pangolin;
main.dart 用 windowManager.setTitle('穿山甲') 显示中文品牌名;
Runner.rc 的 FileDescription/InternalName/ProductName → Pangolin。
- 系统托盘空白:Windows 走 Win32 Shell_NotifyIcon 只认 .ico(传 PNG 显示空白),
新增 BMP 编码的 assets/tray_icon.ico,system_tray.dart 按平台选 ico/png。
- 安装包版本 1.0.0 → 1.0.1(pubspec 1.0.1+2)便于区分测试构建。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 17:06:05 +08:00
wangjia
306d8e5247
Merge branch 'main' into worktree-monitor-debounce
...
# Conflicts:
# scripts/vpn_test.py
2026-06-22 15:08:11 +08:00
wangjia
7a4d0cf7cd
fix(diag): host 参数走 base64 避免 GFW 拦明文敏感词诊断请求
...
控制面跑明文 HTTP 在国外 IP 上,白盒诊断请求 URL 里出现 google/youtube 等 GFW
敏感词时被墙重置(返回空)→ 出海段拿不到、报告显示「—」。改:host 用 base64url
传(host_b64),响应也回 b64、不回明文,明文里无敏感词(不影响真实加密隧道流量)。
- diag.go: EgressTiming 支持 ?host_b64=,解码后查白名单,响应 echo b64
- vpn_whitebox.py: node_egress 用 base64url 编码 host
验证:cara(墙内)google/youtube 出海段从 None → 8-9ms,与 github/cloudflare 一致。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 14:34:05 +08:00
wangjia
eea851737f
docs(client/windows): 合并后校正 README API 默认值说明(已随 main 改为测试节点)
...
ci-pangolin / Lint — shellcheck (push) Has been cancelled
ci-pangolin / OpenAPI Sync Check (push) Has been cancelled
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Has been cancelled
ci-pangolin / Flutter — analyze + test (push) Has been cancelled
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 14:17:48 +08:00
wangjia
ac0fc774cb
Merge branch 'main' into feature/windows
2026-06-22 14:17:19 +08:00
wangjia
322d806876
fix+build(client/windows): 复查修缮——一键构建脚本 + 修 README dart-define 漏项 + 清 lint
...
- 新增 client/windows/build.ps1:拉内核→带 --dart-define 构建→出安装包一键串联,
规避 Release 漏 --dart-define 导致默认连 localhost、登录「网络请求失败」的坑。
- README:Release 命令补回 --dart-define 并加显式警告,指向一键脚本。
- 清 4 个 lint warning:desktop_vpn_bridge 多余 cast→pattern match、去多余非空断言;
nav_sidebar 删未用 import;vpn_bridge_mock 加 killSwitchEnabled getter。
- 同步 window_manager/tray_manager/screen_retriever 插件注册生成文件(win+macos)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 14:17:13 +08:00
wangjia
a19406d041
feat(test): VPN 黑盒/白盒测试工具 + 索引页 + 链路时序图与阶段拆解
...
- vpn_test.py(黑盒):站点矩阵连通/延迟(TLS 握手口径)/吞吐,落 tests/vpn/runs/
并重建 index.html 索引(内嵌 meta、file:// 直开);索引含 cara→LA→Google 时序图
+ 步骤表
- vpn_whitebox.py(白盒):双 IP-echo 判国内是否被隧道 + 五段拆解;经控制面
/v1/diag/egress 取出海段,自动算「接入段=整轮−出海段」,报告出「阶段拆解」表
(对应时序图 橙=接入 / 绿=出海)
- tests/vpn/: runs 与生成的 index.html 为本地工件(.gitignore),README 说明用法
- docs/: vpn-testing-research.md(调研)+ vpn-test-plan.md(黑盒/白盒方案)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 14:12:46 +08:00
wangjia
bc890974c0
fix(server): 补 #5 国内分流的 DNS 面 + 链路诊断端点( #12 )
...
#5 只分了数据面(geoip/geosite-cn 路由 direct),DNS 仍 final:remote 全量经隧道
解析 → 国内域名解析到非 CN IP、漏过 geoip-cn 又走隧道(白盒实测国内 TLS
1000-1660ms;修后 ~50ms)。
- clientconfig.go: 开分流时 dns.rules 加 {rule_set:[geosite-cn]→local},国内域名
用 local(223.5.5.5)直连解析 → 拿到真 CN IP → geoip-cn 命中直连
- main.go: PANGOLIN_PUBLIC_URL 缺失时启动告警(空则分流静默跳过,是隐蔽坑)
- nodes.go: connect 渲染加可观测日志(split_cn/rules_base/split_active/bytes)
- diag.go: 新增只读端点 GET /v1/diag/egress?host=X,节点侧量出海段耗时(白名单
防 SSRF、只回耗时数字),供白盒拆「接入段 vs 出海段」
验证:go test(splitCN 开渲染 dns.rules→local、关无 dns.rules)+ go vet;cara
实测国内 TLS 1000ms+→~50ms、接入段占 TLS 握手 ~98%。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 14:12:31 +08:00
wangjia
98ba2b411e
test: VPN 黑盒测试工具改用 Python(零依赖)+ HTML 报告 + 国内外站点矩阵
...
- scripts/vpn_test.py:替换 vpn_test.sh。纯标准库(socket/ssl/urllib),覆盖国内外
常见站点矩阵(google/youtube/github/x/fb/ig/wiki/cloudflare/openai/reddit;
百度/腾讯/淘宝/京东/B站/微博/网易/知乎/阿里云),测连通+延迟+TTFB+DNS+出口IP+吞吐,
本机连通性(tun/系统扩展),生成自包含 HTML 报告(-o)。
- 延迟标准 = TLS 握手耗时(ssl 握手,纯链路往返),报告里标注 "TTL=按 TLS 计算、非 IP TTL";
TTFB 作参考。禁用 ping/tcp_connect(经 TUN 本地应答失真)。
- 删除 scripts/vpn_test.sh;文档引用同步更新为 .py。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
Claude-Session: https://claude.ai/code/session_01JEHzjEcFzvGwgbxT6Wbt6c
2026-06-22 09:43:46 +08:00
wangjia
98e39629a6
docs: 固定延迟口径——延迟=TLS握手(time_appconnect),TTFB 作参考
...
明确含义与区别:TLS 握手=纯网络链路往返(不含目标后端),跨站可比,作统一延迟基准;
TTFB=TLS握手+服务器处理,含站点因素,仅作体感参考。禁用 ping/tcp_connect 当延迟
(经 TUN 被本地应答)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
Claude-Session: https://claude.ai/code/session_01JEHzjEcFzvGwgbxT6Wbt6c
2026-06-22 09:21:35 +08:00
wangjia
d7c2e22e6f
docs: Windows 客户端实现计划(plan)
...
8 任务分解 + 完成定义,配套 spec(5c9731f )。subagent-driven 执行依据。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 09:18:04 +08:00
wangjia
4025ce341c
build(client/windows): installer AppId 改为合法 GUID
...
原 AppId 段含非 hex 占位(PANGOLIN0001);Inno 虽接受任意串,改为规范 GUID 更清晰。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 09:17:31 +08:00