wangjia
|
4d67a90659
|
fix(ci): deploy-server 隧道 healthcheck 改非致命(本地 healthz 才是权威闸)
Deploy Server / deploy-server (push) Failing after 22s
隧道 /healthz 依赖 cloudflared/CF 边缘,与本次二进制是否健康是两回事;
CF 边缘抖动或隧道尚未 provision 不应判整次部署失败。改为失败仅告警。
(最终 whole-branch review 的 Minor A 决议)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
|
2026-07-06 16:59:52 +08:00 |
|
wangjia
|
cccbb7b56b
|
docs: 控制面 CF Tunnel/端口布局说明 + 方案 HTML 登记 index
CLAUDE.md 补充控制面经 Cloudflare Tunnel 对外的端口/URL 布局说明;生成
docs/control-plane-tls-tunnel.html 阅读版并登记 docs/index.html「实现计划」;
顺带修正 deploy/single-node/deploy.sh 摘要 echo 里残留的旧明文口描述(Task 4/5
落地后措辞漂移,实际已是 CF Tunnel + loopback)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
|
2026-07-06 16:53:36 +08:00 |
|
wangjia
|
06ba76e22b
|
feat(deploy): 8080 收 loopback + 关 8080 防火墙 + 健康检查改本地/隧道(退役明文控制口)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
|
2026-07-06 16:47:32 +08:00 |
|
wangjia
|
e2ffce90d3
|
feat(deploy): PANGOLIN_PUBLIC_URL 改 https://api.yanmeiai.com(客户端规则集走隧道)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
|
2026-07-06 16:45:00 +08:00 |
|
wangjia
|
1b091f3be0
|
ci: 守护 Android manifest 禁全局明文(#25 控制面已 https)
新增 ci/scan-cleartext.sh 扫描 client/android AndroidManifest.xml,
防止将来把 usesCleartextTraffic="true" 重新加回(退回明文态)。
CI 新增 cleartext-scan job,并把该脚本纳入 lint job 的 shellcheck 覆盖
(单独挂载 ci/ 目录,不动 scripts/ci 既有挂载)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
|
2026-07-06 16:41:59 +08:00 |
|
wangjia
|
a5aea9438a
|
feat(client): 控制面基址默认 https://api.yanmeiai.com + 移除 Android 明文开关
TDD: 先加守护测试(断言 kApiBaseUrl 走 https 且不含硬编码 IP),确认失败后
再改 api_config.dart 默认值 + 去掉 AndroidManifest 的 usesCleartextTraffic。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
|
2026-07-06 16:37:42 +08:00 |
|
wangjia
|
9b56e2667b
|
feat(deploy): cloudflared 出站隧道前置控制面 API(api.yanmeiai.com→127.0.0.1:8080)
deploy.sh 在 systemd 安装段新增 cloudflared 二进制(apt 源)+ unit 安装;
enable-on-boot 用 /etc/pangolin/cloudflared.env(TUNNEL_TOKEN)存在与否作
门槛,避免全新单机部署在 token 未落地前因 cloudflared 起不来而失败。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
|
2026-07-06 16:32:32 +08:00 |
|
wangjia
|
bac79017ae
|
docs(plan): #25 控制面 CF Tunnel 实现方案
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
|
2026-07-06 16:30:11 +08:00 |
|
wangjia
|
5c647235aa
|
chore(todo): #25 方案 propose/approve + #32 fallback 登记
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
|
2026-07-06 16:28:45 +08:00 |
|
wangjia
|
f8e870fd6a
|
fix(ci): backup 大小 sanity 阈值 50k→1k(小库压缩后 <50k 被误删)
远端 .backup 出的库 gzip 后可能 <50KB,原 >50k 检查把有效备份当'异常小'删了。
空 gzip 仅 ~20 字节,>1k 足以区分空/断流与有效备份。
|
2026-07-06 15:34:18 +08:00 |
|
wangjia
|
84b042394d
|
ci(backup): 备份步骤输出 tee 到 NAS _last-run.log(便于排障)
|
2026-07-06 15:32:10 +08:00 |
|
wangjia
|
e557a94ed0
|
fix(ci): lib-ssh 加 IdentitiesOnly+BatchMode(修 Too many auth failures)
CI ssh 到 pangolin1 报 Too many authentication failures + 回落密码提示:ssh 把
容器默认/agent key 也一并递上,撞 MaxAuthTries。加 IdentitiesOnly=yes 只用 -i key,
BatchMode=yes 纯非交互。影响 deploy-server / backup 等所有走 lib-ssh 的部署。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-06 15:05:44 +08:00 |
|
wangjia
|
e1a17acbe4
|
feat(ci): SQLite 每日备份到 NAS(异地容灾,#26/F2)
backup-db.sh:ssh pangolin1 → sqlite3 online .backup 取 WAL 一致快照 + 远端
integrity_check → gzip 流回 → 存 NAS /volume1/docker/backups/pangolin,保留 30 天。
backup.yml:每日 02:00(北京)cron + 手动,ubuntu-latest,复用 DEPLOY_SSH_KEY,
Telegram 通知。异地=家里 NAS≠VPS 机房。不在 pangolin1 装/常驻任何东西。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-06 14:55:11 +08:00 |
|
wangjia
|
3efd67297e
|
ci(server): 编译/测试直接在 runner 跑,去嵌套 docker(修 DinD;go 工具链自动下载)
compile-backend/test.sh 原在 golang:1.25 容器里跑,job 容器内 $PWD 在宿主不存在
→ DinD 挂载失败。改直接跑;go.mod 要求 1.25.10,靠 Go 工具链经 goproxy.cn 自动拉取。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-06 14:40:09 +08:00 |
|
wangjia
|
f6e565ffdc
|
ci(site): 官网构建/部署直接在 runner 跑,去掉嵌套 docker(修 DinD 挂载)
Deploy Site / deploy-site (push) Successful in 1m23s
job 容器内 $PWD(/workspace/...)在宿主不存在,docker run -v $PWD 挂载失败。
runner 镜像 catthehacker/ubuntu:act-latest 自带 node/npx,直接 bash 跑即可。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
site-v0.0.3
|
2026-07-06 14:34:12 +08:00 |
|
wangjia
|
ba5f71b716
|
ci: runs-on nas → ubuntu-latest(匹配 nas runner 实际 label)
Deploy Site / deploy-site (push) Failing after 1m36s
nas 上的 forgejo-act-runner 注册 label 是 ubuntu-latest(非 nas),导致所有
runs-on: nas 的工作流无匹配 runner。改为 ubuntu-latest 对齐 runner 现状。
(备选:给 runner 加 nas 标签保约定,未采用。)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
site-v0.0.2
|
2026-07-06 13:33:27 +08:00 |
|
wangjia
|
7c26050cdb
|
docs(spec): 官网部署改 Cloudflare Pages(架构变更说明)
Deploy Site / deploy-site (push) Has been cancelled
节点 :443 被 VPN 占用 + CF 免费套餐改回源端口需 Enterprise → 官网改 CF Pages 托管
(纯静态/全程 HTTPS/CSP 生效/无 :443 冲突),已上线 pangolin.yanmeiai.com。
deploy-site.sh 用 wrangler,需 CLOUDFLARE_API_TOKEN + CLOUDFLARE_ACCOUNT_ID。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
site-v0.0.1
|
2026-07-06 10:08:20 +08:00 |
|
wangjia
|
673914783d
|
refactor(ci): 官网部署改用 Cloudflare Pages(替代 rsync 到 pangolin1)
节点 :443 被 sing-box(VPN 数据面)占用,CF 免费套餐回源只能打 :80/:443、改端口需
Enterprise —— 故官网改由 CF Pages 托管(项目 pangolin-site,自定义域 pangolin.yanmeiai.com),
纯静态、全程 HTTPS、_headers/CSP 自动生效、不落 VPS、彻底无 :443 冲突。
deploy-site.sh 改为 wrangler pages deploy(需 CLOUDFLARE_API_TOKEN + CLOUDFLARE_ACCOUNT_ID
Gitea secret);deploy-site.yml deploy 步骤在 node:20 容器内跑 wrangler。lib-ssh 仍供服务端部署用。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-06 09:59:58 +08:00 |
|
wangjia
|
443d4e3a11
|
feat(ci): test.sh(go test / flutter test)
Add scripts/ci/test.sh <server|client>: server runs `go test ./...`
inside golang:1.25 (mirrors ci.yml's go-server job docker invocation +
gomod/gobuild caches + GOPROXY from _env.sh); client runs `flutter test`
inside ghcr.io/cirruslabs/flutter:stable (mirrors ci.yml's flutter-client
job's pub-cache mount + test dirs). Wired into deploy-server.yml's Test
step already added in Task 4. Registers the script in ci.yml's shellcheck
file list.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
|
2026-07-06 00:37:48 +08:00 |
|
wangjia
|
0825170044
|
fix(ci): 服务端流水线注入加固(tag 校验/JSON 转义/workflow env)+ gitignore server/out
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
|
2026-07-06 00:33:47 +08:00 |
|
wangjia
|
4fb3fe3fee
|
feat(ci): 服务端 server-v* 编译+release+部署(备份/迁移/回滚,复用 lib-ssh/lib-forgejo)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-06 00:24:18 +08:00 |
|
wangjia
|
91d1355721
|
fix(ci): 部署脚本 —— 私钥清理 trap 前移 + rsync 空目录守卫 + 主机密钥 accept-new(评审 Critical/Important)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-06 00:17:37 +08:00 |
|
wangjia
|
9bac5c8dcb
|
feat(ci): 官网 site-v* 构建+部署脚本(compile-site/deploy-site/lib-ssh/workflow)
- scripts/ci/compile-site.sh: node:20 容器内构建 web/website(Astro),
SITE_URL 注入 canonical 域名 https://pangolin.yanmeiai.com。
- scripts/ci/lib-ssh.sh: 新增共享 setup_ssh/teardown_ssh(写临时私钥+
known_hosts),供 site 与后续 server 部署复用;目标写死 IP 103.119.13.48
(runner 无法解析用户本机 ~/.ssh/config 的 pangolin1 别名)。
- scripts/ci/deploy-site.sh: rsync dist/ 到 pangolin1
/var/www/pangolin-site/,root 部署。
- .gitea/workflows/deploy-site.yml: site-v* tag + workflow_dispatch 触发,
concurrency 组 deploy-site 防并发。
- .gitea/workflows/ci.yml: shellcheck 列表纳入三个新脚本。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
|
2026-07-06 00:10:53 +08:00 |
|
wangjia
|
f0a8c6dd98
|
ci(checks): 触发路径纳入 scripts/ci(否则 CI 脚本改动不触发 lint)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-06 00:05:26 +08:00 |
|
wangjia
|
0b9f291ff1
|
ci(checks): shellcheck 覆盖 scripts/ci
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-06 00:03:05 +08:00 |
|
wangjia
|
ff8fc36726
|
fix(ci): lib-forgejo TLS 校验默认开启,-k 改显式 opt-in(安全)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-05 23:55:56 +08:00 |
|
wangjia
|
b8343a8788
|
feat(ci): scripts/ci 基座(_env/lib-forgejo/notify)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-05 23:49:59 +08:00 |
|
wangjia
|
6be777dff5
|
docs(plan): CI/CD 实现计划(#30) —— .md 真相源 + HTML 阅读版 + 索引
三期 11 任务:Phase1 基座+官网+服务端(无签名) → Phase2 Android → Phase3 macOS/Windows。
服务端部署固化 F3/F4 备份/迁移/回滚;下载链接接 release 资产;密钥对齐 jiu。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-05 23:40:59 +08:00 |
|
wangjia
|
0ab31b4c58
|
docs(spec): CI/CD 密钥命名对齐 jiu(MACOS_*/APPSTORE_*/ANDROID_*)
Apple 那套账户级与 jiu 共用一份(同名);新增 FORGEJO_URL、macOS 两个描述文件
入表。Android keystore 同命名规范但各 app 独立不共享。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-05 23:19:29 +08:00 |
|
wangjia
|
fe9a3a6cdb
|
docs: CI/CD 方案 HTML 阅读版 + 登记 docs/index.html(#30)
深色家族风 HTML(cicd-design.html),真相源仍是 superpowers/specs 的 .md。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-05 22:06:25 +08:00 |
|
wangjia
|
f30097172a
|
docs(spec): CI/CD 全流程设计方案(#30)
范围 A~F(官网+服务端+Android/macOS/Windows,排除 iOS/#26/#25);runner 混合
(nas/mac/windows);tag 触发;镜像 jiu 的 scripts/ci+workflows 结构;密钥作用域
(Apple/token 账户级、部署key/keystore 仓库级);服务端部署固化 F3/F4 手动次序带回滚。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-05 22:02:40 +08:00 |
|
wangjia
|
70d3293251
|
refactor(website): 域名/邮箱/渠道收口到 src/config/site.ts 单一真相源
新增 SITE 配置(url/email/telegram/line/store),Footer、Pricing、astro.config
(canonical 域名)均改为引用它;改联系方式/域名只动一处。
astro.config.mjs 直接 import 该 TS(Astro 配置加载支持)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-05 19:23:19 +08:00 |
|
wangjia
|
a454c63c4e
|
fix(website): 落定真实域名/邮箱/Telegram
- canonical 域名 → https://pangolin.yanmeiai.com(astro.config SITE_URL 默认值)
- 联系邮箱 support@/buy@pangolin.vpn → pangolin@yanmeiai.com(可点 mailto)
- Telegram @PangolinVPN_bot → @pangolin_app(可点 https://t.me/pangolin_app)
邮件转发已在 CF 配好:pangolin@yanmeiai.com → chenxin880812@gmail.com(目标已验证)。
未动(待 #24):shop 自助商店 URL、LINE handle(TG 群为私有,不放公开页)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-05 19:19:58 +08:00 |
|
wangjia
|
c1c6b7ccf5
|
fix(website): Docs 卡片暂改不可点(去掉「阅读」死链)
4 张文档卡原为 <a class=doc> 无 href + 「阅读」死链;真实文档页未写。
改为信息卡(<div>),保留标题/描述与导航·页脚入口,不误导。
撰写真实文档(快速开始/FAQ/协议安全/隐私政策)并接回链接 → #31。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-05 18:09:07 +08:00 |
|
wangjia
|
75ed293151
|
fix(website): 移除无效的「登录」按钮(死 span,无链接)
Web 用户中心(web/usercenter)尚未部署、无 URL,登录入口暂无处可去;
产品主流程为 App 内登录。先删死按钮避免公开页点了没反应,待 #30 部署
usercenter 后接上登录地址恢复(已挂 #30 子任务)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-05 17:56:49 +08:00 |
|
wangjia
|
95abb74db2
|
fix(website): 价格按语言分币种 —— 英文版显示美元(P0)
PRICES 原为中英共用一份人民币值 → 英文页显示 ¥ 不专业。改为 Record<Lang,...>:
- zh: ¥0 / ¥25(年¥20) / ¥99(年¥79)
- en: $0 / $3.99(年$3.19) / $13.99(年$11.19) 年付沿用 8 折
Pricing.astro 接收 lang 按语言取价;Site.astro 传入 lang。
构建产物核实:EN 页 0 处 ¥、ZH 页 0 处 $;红线扫描 0 命中。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-05 17:43:44 +08:00 |
|
wangjia
|
1c8f6cb56b
|
fix(website): 去除夸大宣传 + 隐藏占位 Blog 区(官宣页上线前 P0)
- 「80+ 全球加速线路」→ 中性「全球加速线路 / Global routes」(hero 徽章/功能卡/Pro 套餐/对比表 4 处);
现实仅 1 个节点(pangolin1),80+ 属夸大宣传(国内 VPN 有法律风险)。
- 功能卡③描述去掉「港日新美欧韩」具体地区罗列 → 「覆盖多地优质线路」。
- 隐藏整个 Blog 区:3 篇均占位假帖,含虚构的「首尔/法兰克福节点」「v2.4 版本」。
移除 <Blog/> + 顶栏导航 Blog 项 + 页脚 Blog 链接;有真实文章后恢复。
未动(待用户输入):英文版价格货币(等美元定价);下载链接归入 #30 CI/CD。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-05 17:35:49 +08:00 |
|
wangjia
|
08fb915b5e
|
test(devices): #27 同机换账号登录注册 E2E(SQLite,服务层)
走 login 完全相同的路径 devices.Service.RegisterIfAbsent{MaxDevices:0}:
同一 device uuid 两账号各得一行、A 重登幂等刷新、共享 uuid 恰 2 行。
补 SQLite(生产同引擎)服务层覆盖,与既有 store 层 TestSQLite_DevicesUserScopedUUID
及 MySQL 集成 TestSameDeviceUUIDTwoAccounts 三层互证 F3 修复。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-05 13:11:25 +08:00 |
|
wangjia
|
eb7c3c1062
|
feat(agent): WARP 域名分流 —— 命中域名走 Cloudflare 干净出口(#29)
节点 sing-box 渲染新增可选 WARP 分流:节点本地 warp.json(默认
<StateDir>/warp.json)配 WARP 凭证 + 域名清单 → 渲染时注入一个 userspace
WireGuard(WARP)endpoint + route(sniff 取 SNI/Host → domain_suffix 命中走
warp,其余 final=direct)。sing-box 1.11+ endpoints 语法,system=false 用户态
不依赖内核 wg 模块。
- 运营改域名只需编辑 warp.json + 重启 agent(sing-box 无热重载),即「配置的方式」。
- warp.json 不存在/enabled=false/域名空/凭证缺/坏 JSON → 一律按未启用,配置与旧
节点逐字节一致,坏配置绝不产出无法启动的 sing-box config(渲染读失败仅记日志)。
- WARP 凭证节点私有(wgcf 注册免费匿名账号),不入 git、不经控制面。
- 测试:注入 endpoint+route/无配置无 route/禁用或残缺不注入/坏 JSON 优雅退化。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-02 13:40:00 +08:00 |
|
wangjia
|
f035552ff5
|
fix: disconnect 吊销每设备凭证 + 客户端断开时真正调用(F4,#28)
审查 F4 两层问题:①DisconnectNode 只撤账户级 ent.DpUUID,而 connect 下发的是
每设备 devDp——吊销从未对准目标;②客户端从未调用过 disconnect 端点(只有
fetchConfig),端点是死代码,凭证一律活到 TTL(付费 24h)。
- server:disconnect 收 optional body {device_id},吊销该设备 dp_uuid(优先)+
账户级遗留兜底;旧客户端无 body 走兜底,行为不回归。nil hub 守卫(测试友好,
与 ListNodes 一致)。
- client:ConnectApi.disconnect(best-effort,5s 超时吞错);_disconnect 加
revokeCredential 参数,仅在「不会紧接重连同节点」的路径置 true(用户主动断开/
额度耗尽/登出)——看门狗断开→重连若也吊销,revoke 可能晚于新 connect 推送、
误杀新会话。
- test:httpapi disconnect 三态(带 device_id 双吊销/无 body 仅兜底/设备已移除
不炸);client 功能套件 182 过(golden 为已知 macOS 本地漂移,不相关)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-02 13:29:01 +08:00 |
|
wangjia
|
63d1baeb01
|
fix(server): devices 唯一键改 (user_id,uuid) —— 同机换账号不再 403 死结(F3,#27)
device_id 按安装持久、跨账号复用;旧全局 UNIQUE(uuid) 使同机第二账号注册永远
403 → ConnectNode 判 DEVICE_NOT_REGISTERED,提示的「重新登录」无法自救。
- migration 21(sqlite/mysql):UNIQUE(uuid)→UNIQUE(user_id,uuid);platform 放行
linux(normalizePlatform 早已接受,旧 CHECK/ENUM 会拒)。SQLite 表重建用
rename→重建→复制→drop 次序,单事务内不触发 sessions 的级联清空(FK ON)。
- 查找全部收口为按 (user,uuid) 作用域(重复 uuid 跨用户后全局查询歧义):
findDeviceByUserUUIDTx / FindByUserUUID;Register 删跨用户 Forbidden 分支;
Delete/ForceLogout/Rename 对他人设备返回 404(不可见);SessionActive 删
「非本人 fail-safe」分支,dev==nil→false 语义不变。
- 测试:SQLite 真迁移库 F3 回归(两账号同 uuid 各自成行/同用户重复拒/linux 入库/
sessions 重建后级联仍成立)+ MySQL 集成测试 schema 同步与双账号用例。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-02 13:16:40 +08:00 |
|
wangjia
|
bbe149fd41
|
docs: 全栈设计审查 2026-07(前端/后端/数据库,13 项发现分级)
P0:控制面明文 HTTP、SQLite 零备份。P1:同机换账号设备注册 403 死结(migration16
注释里推迟的 UNIQUE(user_id,uuid) 未落地)、disconnect 撤账户级凭证而 connect 发
每设备凭证、agent 用量 Reset 后上报失败即丢(at-most-once)、Redis 白名单单点全员
掉线、argon2id 64MiB 并发 OOM。P2:sessions/audit 无留存、免费额度 UTC 日界、
三时钟口径、hub 内存态、单实例端口无握手、ReportUsage 无事务。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-02 12:52:08 +08:00 |
|
wangjia
|
14bcdc2e79
|
docs(contact): 落定渠道二级页设计 —— 统一单表 + LINE 灰置
拍板:不展示成员数;群组=「加入」其余=「打开」;独立 GET /v1/contact;
全渠道(Telegram/LINE/邮箱/发卡)统一一张 contact_link 表,靠 url 协议区分
(mailto:/https:/tg://),邮箱=kind=link+mailto。L1 平台图标/名/强调色由前端
platform 注册表内置(唯一不入库的皮)。LINE 也做二级、同构,但先灰置「即将开放」
(registry comingSoon=[line],配好去灰即用)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-02 12:30:24 +08:00 |
|
wangjia
|
91a890428f
|
docs: 联系我们渠道二级页交互设计(Telegram/LINE 多频道群组,DB 配置)
点渠道进二级页,按 kind 分组(频道/群组/Bot)列多条链接,内容 DB 配置。
含可点原型(App 真实暗色 token)+ 单表 contact_link 数据模型 + GET /v1/contact
接口 + 交互规则(平台 >1 条链接才进二级,否则点击直达)。#24,待统一后开发。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-02 12:23:02 +08:00 |
|
wangjia
|
2c804d4ebf
|
fix(scripts): local_test.sh 对齐当前 macOS 架构(sysext 标识符名 + 静态 libbox)
发版脚本停留在旧「嵌入 Libbox.framework」架构,与现工程漂移两处、导致 sign 失败:
- sysext bundle 名 = 标识符 com.pangolin.pangolin.PacketTunnel.systemextension
(PRODUCT_NAME,见 CLAUDE.md),非短名 PacketTunnel.systemextension。
- libbox 现「只 Link 不 Embed」静态进 sysext 二进制,sysext 内已无独立
Libbox.framework;删掉对不存在 framework 的签名,签 sysext bundle 即覆盖。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-02 11:11:05 +08:00 |
|
wangjia
|
8937044f55
|
fix(client/macos): 最小化托盘后点 Dock 图标唤回窗口(1.0.48+49)
windowManager.hide() 走 orderOut: 后主窗口不可见,点 Dock 图标系统只发
applicationShouldHandleReopen(hasVisibleWindows=false),AppDelegate 未接管 →
点了没反应。AppDelegate 实现该回调,无可见窗口时 makeKeyAndOrderFront +
activate 唤回 mainFlutterWindow。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-02 10:50:40 +08:00 |
|
wangjia
|
76126f7a0c
|
chore: bump 1.0.47+48 (弱网自动重连#18 + 用量去计)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-02 09:58:27 +08:00 |
|
wangjia
|
be27529054
|
feat(client): 弱网抖动先自动重连当前节点,不再动不动报「节点异常」(#18)
弱网下(实测 RTT 2.2s/丢包)urltest 瞬断或内核 off,看门狗此前一判死就断开+要用户手动
重连(nodeUnhealthyError),体验差。改为:无备用节点时先自动重连**当前节点**(不换节点——
弱网是本地网络问题,换节点无益还会来回横跳),连续失败超过 _kMaxAutoReconnect(3) 次才真报
「节点异常」。urltest 成功或用户主动连接即清零计数,只有持续失败才耗尽。
- _tryAutoReconnectCurrent(bounded 重连当前节点)+ _handleUnexpectedOff(kernel off 走同一逻辑)。
- _onNodeUnhealthy 无备用分支改调 _tryAutoReconnectCurrent;智能有备用仍优先切备用(不变)。
- 重连期给「网络波动,正在重连…」瞬态提示(nodeReconnecting,zh/en)。
- 测试:注入时钟 + 内存 SecureKV(避免 deviceId 挂起);kernel-off 连续判死→3 次自动重连后报
节点异常;路径B 无备用→自动重连当前节点不换节点。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-02 09:57:19 +08:00 |
|
wangjia
|
daaed39bac
|
fix(server): 用量分钟数按墙上时钟去重 —— 多设备并发不再 N× 超计(bug)
agent 按每 dp_uuid(每设备)每窗口计 SessionMinutes=1,控制面 ReportUsage 逐条累加进
usage_daily.minutes_used → N 台并发 = N×墙上时钟(线上 chenxin 2903 分钟/天,不可能)。
免费额度是「所有设备共同的时间」,超计会把免费账号错误判「时长耗尽」而断连。
改 ReportUsage:账户维度按 user 分组去重 —— 字节仍求和(可加),分钟按窗口取 max
(=窗口墙上分钟,恒为 1)去重,循环后每 user 各 flush 一次 AccumulateUsage/Hourly。
每设备维度(usage_device_*)保持逐台累加不变。usage_daily.minutes_used ≤ Σ 每设备分钟,
/me 的 quota_today_min 与 ConnectNode 免费门随之正确。历史数据次日归零、不回填。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-02 09:57:19 +08:00 |
|
wangjia
|
837bf55f6a
|
fix(client): 「今日剩余」不再冻结 —— 倒计时兜底启动 + 会话后静默刷新 /me(1.0.46+47)
免费版「今日剩余 xx 分钟」一直不变的两处原因:
1. 倒计时仅在经 _connect 连接时锁定 _freeRemainingSec;Android 常驻隧道/重启后自动
同步到已在跑的隧道时不走 _connect → 倒计时不启,连接页只显示静态「今日剩余」。
现于 _onKernelStatus.on 兜底:免费且未锁定则按当前额度补锁,保证显示会动的倒计时。
2. /me 仅登录时拉一次,会话消耗后不刷新 → 「今日剩余」停在登录值。现于断开/内核掉线
后静默刷新 /me(新增 MeNotifier.silentRefresh,不进 AsyncLoading → 不闪整页 spinner)。
markExhausted / watchAd 也改用 silentRefresh,避免额度变动时连接页闪 spinner。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-02 01:54:53 +08:00 |
|