wangjia
eb1bd11439
fix(test): 契约测试解耦 stats-overhaul WIP(CI 抓到的真问题)
...
ci-pangolin / Lint — shellcheck (pull_request) Failing after 9s
ci-pangolin / OpenAPI Sync Check (pull_request) Successful in 18s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (pull_request) Successful in 6s
ci-pangolin / Flutter — analyze + test (pull_request) Successful in 39s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (pull_request) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (pull_request) Successful in 4s
ci-pangolin / Go — build + test (pull_request) Successful in 2m2s
ci-pangolin / E2E Smoke — L4 进程级端到端 (pull_request) Failing after 2m14s
ci-pangolin / Golden — 视觉回归 (components + auth) (pull_request) Successful in 31s
CI 暴露:我的契约测试引用了未提交的 stats-overhaul 文件,本地能过(文件在工作区)、
CI checkout 已提交代码就崩:
- api_contract_test.dart import device_usage.dart(?? 未提交)→ flutter analyze 报
'Target of URI doesn't exist'
- usage/contract_test.go 引用 DeviceUsagePoint/deviceUsageResponse(HEAD service.go/
handler.go 均无)→ go-server 编译失败
摘掉 /v1/usage/devices(DeviceUsage)契约,保留 /v1/me + /v1/usage(已提交)。
待 stats-overhaul 合并后再补 DeviceUsage 契约。
验证:flutter analyze test/contract 'No issues';go vet usage 无错。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 18:13:27 +08:00
wangjia
9a2d14adbe
fix(ci): 去掉误提交的 .claude/worktrees gitlink
...
ci-pangolin / Lint — shellcheck (pull_request) Failing after 5s
ci-pangolin / OpenAPI Sync Check (pull_request) Successful in 20s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (pull_request) Successful in 7s
ci-pangolin / Flutter — analyze + test (pull_request) Failing after 36s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (pull_request) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (pull_request) Successful in 5s
ci-pangolin / Go — build + test (pull_request) Failing after 2m17s
ci-pangolin / E2E Smoke — L4 进程级端到端 (pull_request) Failing after 2m17s
ci-pangolin / Golden — 视觉回归 (components + auth) (pull_request) Successful in 38s
.claude/worktrees/iridescent-sleeping-lampson 是个 git worktree 目录,被误提交成
gitlink(mode 160000)。.gitignore 已有 .claude/worktrees/ 但它在那之前就提交了。
git rm --cached 去跟踪(不删磁盘 worktree)。修 actions/checkout 的 submodule 警告
(No url found for submodule path)+ 清理仓库。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 18:01:18 +08:00
wangjia
58e06708f4
test(ci): 闸2 Go go vet 进 CI(支柱-adjacent;golangci-lint 暂受 go1.25 阻)
...
ci-pangolin / Lint — shellcheck (pull_request) Failing after 15s
ci-pangolin / OpenAPI Sync Check (pull_request) Successful in 26s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (pull_request) Successful in 5s
ci-pangolin / Flutter — analyze + test (pull_request) Failing after 29s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (pull_request) Successful in 4s
ci-pangolin / Codegen Drift — token 生成物未漂移 (pull_request) Successful in 5m10s
ci-pangolin / Go — build + test (pull_request) Failing after 5m55s
ci-pangolin / E2E Smoke — L4 进程级端到端 (pull_request) Failing after 14m36s
ci-pangolin / Golden — 视觉回归 (components + auth) (pull_request) Successful in 35s
go-server job 加 go vet ./...(项目工具链,零版本摩擦):
- golangci-lint(errcheck/depguard)暂用不了:其 go1.23 构建 < 项目 go1.25.10,
报版本错;待 golangci-lint 跟上 go1.25 再上 errcheck(支柱4)+ depguard(import 方向)
- go vet 当前零违规,接进 go build+vet+test 链
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 13:51:41 +08:00
wangjia
945c2e2f8d
test(ci): 闸2 Dart 支柱4 lint 升 error 级(真守门)
...
analyze 闸修好后(exit 0),把支柱4 两条规则提升为 error 级:
- only_throw_errors / avoid_catching_errors → analyzer.errors: error
- 即使 CI --no-fatal-infos,这俩违规仍致命(挡 merge);当前零违规
- 将来 throw 字符串 / catch Error → CI 红(支柱4:错误是有类型的值)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 13:45:31 +08:00
wangjia
bb2688cede
test(ci): L3 golden 进 CI(components+auth 子集,Linux 权威基线)
...
L3 视觉回归真进 CI(此前卡 docker daemon 未起 + dirty 纠缠;现启 Docker 落地干净子集):
- 在 ghcr.io/cirruslabs/flutter 容器重生成 components+auth 的 14 张 Linux 权威基线
(auth_login/connect 三态/quota/smart_card;mac 渲染与 CI Linux 不一致,故钉死 Linux),
容器内 --update-goldens 后无 flag 复跑幂等通过
- ci.yml 新增 golden job(第9个):flutter test components_golden_test + auth_redesign_golden_test
- 解耦干净:这俩只 import clean widget;stats-overhaul 的 l10n 改动纯新增(现有键未动)
→ 渲染不受影响、不裹挟 dirty;tablet/desktop-stats golden 仍耦合 stats-overhaul,待合并后并入
- docs/test-architecture.html:L3 状态更新为「已进 CI(子集)」
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 13:20:55 +08:00
wangjia
63bb31066f
test(ci): 闸1 接缝脚手架 new-seam.sh(支柱1:让对的写法成默认)
...
预防式闸:一条命令生成「接口 + Impl + Fake + Riverpod provider + flow-test 桩」,
外部依赖从一开始就藏接口后、可注入、自带 Fake、可测——把支柱1 变成阻力最小路径。
- scripts/new-seam.sh <PascalName> [lib子目录]
- 验证:生成样例 SampleProbe → flutter analyze 无 issue + test 过 → 清理
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 12:17:58 +08:00
wangjia
c5223af4a1
test(ci): L3 golden 权威环境脚本(进 CI 前置准备)
...
golden 真进 CI 卡两个硬约束:Linux/mac 渲染不一致(mac 基线在 CI 全红)+ 基线绑定
stats-overhaul dirty 工作区。本提交备好权威环境,不裹挟 dirty、不破坏:
- scripts/update-goldens.sh:在 CI 同款镜像 cirruslabs/flutter 重生成 Linux 权威基线
(开发者改 UI 后用它刷新,而非裸 mac --update-goldens,保持与 CI 一致)
- docs/test-architecture.html:L3 现状更新 + 列明启 CI 硬闸的两个前置条件
- 真启闸需:有 docker 的机器生成并提交 Linux 基线 + dirty 工作区合并(本机无 docker)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 12:16:16 +08:00
wangjia
76dbdcfa83
test(client): L2 点连接能连上 流程 + ConnectApi 注入(支柱1)
...
- connection_provider:加 connectApiFactoryProvider(原内部 new ConnectApi 改成
可注入工厂,支柱1 接缝即接口)——默认行为不变
- test/unit/flow_connect_test.dart:真 toggle → fetchConfig(注入 MockClient 回占位
config)→ bridge.start → statusStream 确认 → on → 再 toggle → off;
验证「非乐观翻转」红线(on 必由 bridge 确认)
- 全量 unit/widget 47 全过(重构不破坏)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 12:13:40 +08:00
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