From e49345acd93fdb4920e159750fdd47a7d2e0c905 Mon Sep 17 00:00:00 2001 From: C3H3-AI Date: Wed, 16 Sep 2026 06:14:09 +0800 Subject: [PATCH] chore(release): 1.1.0b14 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 版本号 1.1.0b13 -> 1.1.0b14,并补齐 CHANGELOG(顶部此前停在 b12)。 本轮内容分三类: 1. 独立审计发现的缺陷修复(H1 凭证写入竞态 / H2 管理接口默认开放 / H3 流式错误未识别 / M1 会话 token 可预测 / M2 流式错误被丢弃) 2. 早期修复(TZ 缺失致签到偏移 / TraeWork 预热窗口过窄 / 流式 120s 截断 / is_custom_model 未过滤) 3. CI/CD 基建(预构建镜像 / 门禁 / 发版流程 / 上游同步保护) CHANGELOG 说明: - 只新增 v1.1.0b14 条目,**未补写 v1.1.0b13**。 b13 是 9/13 的提交("恢复 b3-b12 全部改动"),缺少第一手信息, 臆测补写不如留空。 - 条目格式沿用既有风格(### 修复 / 安全 / 构建与发布 / 内部)。 - 两处**用户可感知的行为变化**已在条目中显式标注: · TZ 修复后签到时刻从 17:00 变回配置值 · H2 修复后非 ingress 直连 7870 的管理访问会被拒绝 发版链路(合并后自动执行): release.yml 读 config.yaml 版本 → 与最新 tag 做 semver 比较 (1.1.0b14 > 1.1.0b13 ✅)→ 建 tag → 建**草稿** release (含 b14 故自动标 prerelease) build-image 构建 amd64/aarch64 镜像并推 ghcr.io/c3h3-ai/ai-proxy:1.1.0b14 发布由维护者人工确认(草稿不会自动发布) 验证: go build ./... / go vet ./... / go test ./... 全 PASS scripts/test_mgmt_auth.py / test_session_token.py 全 PASS --- CHANGELOG.md | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++ config.yaml | 2 +- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5bd0be..d7be201 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,72 @@ # Changelog +## v1.1.0b14 (2026-09-15) 测试版 + +本轮包含三类改动:独立审计发现的缺陷修复、CI/CD 基建、以及若干安全加固。 + +### 修复 +- **签到/保活时刻偏移 8 小时**:容器缺 `ENV TZ`,`time.Now()` 取到 UTC, + options 里配置的 `09:00` 实际在 **17:00**(北京时间)触发。Dockerfile 补 + `ENV TZ=Asia/Shanghai`(`tzdata` 原本已装)。**升级后触发时刻会变回配置值, + 属预期行为变化。** +- **TraeWork 账号被误永久禁用**:token 预刷新窗口仅 10 分钟,请求途中 token + 失效时上游返回 401 → 判定 session dead → 账号被永久禁用、需人工重登。 + 现按平台区分窗口(TraeWork 24h / WorkBuddy 保持 10min)。 +- **长回答被中途截断**:流式请求使用了带 `Timeout` 的 HTTP client,而 + `http.Client.Timeout` 包含**读取响应体**的时间,单次输出超 120s 即被切断。 + 现流式改用无总时长上限的 client,首字节由 `ResponseHeaderTimeout` 约束。 +- **面板列出不可用的模型**:未过滤 `is_custom_model`(第三方代理模型需额外 + 授权),用户选中后必然失败。现过滤该类型(对齐上游 `abb9b0b`)。 +- **凭证文件写入竞态(可能丢失 refreshToken)**:凭证用**固定**临时文件名 + (`path.tmp`),而 `serverd` 与 `ctl` 是**两个独立进程**、都会写同一份文件。 + 并发下会出现 rename 竞争(实测并发 800 次失败 292 次);更严重的是上游 + refresh **会轮换 refreshToken**,后落盘者覆盖先落盘者,若落盘的是已失效的 + 那个,账号下次刷新即失败。现改用新增的 `internal/atomicfile`:唯一临时 + 文件名 + 跨进程 `flock` + fsync。state 文件同样处理。 +- **流式响应中途的上游错误未被识别**:上游并非只在 `status>=400` 时报错 + (同包三处代码都显式处理 `code != 0` 的 200 响应)。流式路径此前只做逐行 + 透传,会把 `{"code":1,"msg":"余额不足"}` 这类非 SSE 内容原样写给客户端, + 且**不触发账号冷却**,后续请求继续选中它。现透传前嗅探首行,非 SSE 帧按 + 上游错误信封解析并走既有错误分类。 +- **流式错误被完全丢弃**:`_ = Upstream.Stream(...)` 忽略返回值,且 + `NoteSuccess` 在流式开始**之前**调用 —— 即使流失败,账号也被标记为健康。 + 现改为先透传、成功后才记成功,失败时记录日志并按类别冷却/禁用账号。 + +### 安全 +- **管理接口默认对局域网开放**:`config.yaml` 默认 `webui_user/pass` 为空, + 面板登录未启用时,鉴权回退为「来源在内网即放行」,而 add-on 的 `7870/tcp` + 映射到宿主机 —— 同网段任意设备可**无认证**调用管理接口(账号列表、刷新 + 令牌、修改配置)。根因是 ingress 转发(`172.30.x`)与 LAN 直连 + (`192.168.x`)**源 IP 同属内网,无法仅凭 IP 区分**。现未启用登录时 + **只信任 ingress 转发与本机回环**。 + **注意:若此前通过非 ingress 方式(如直接访问 `http://:7870`)使用 + 管理界面,升级后会被拒绝 —— 请在设置页配置面板登录账号/密码,或改走 + ingress 入口。** +- **面板会话 token 可预测**:原用 `sha256(time.time())` 生成,熵几乎全部 + 来自时间戳,可被枚举。现改用 `secrets.token_urlsafe(32)`(约 258 bit 熵), + 落盘权限收紧为 `0600`,比较改用 `hmac.compare_digest`(原先的 `==` 会短路, + 可据响应时间逐字节推断 token)。 + +### 构建与发布 +- **预构建镜像**:改用 HA 官方 builder actions 在 CI 构建 amd64/aarch64 + 镜像并推送 `ghcr.io/c3h3-ai/ai-proxy`,`config.yaml` 增加 `image` 字段。 + Supervisor 直接拉取镜像,**不再在用户设备上编译**(此前需拉 Go 镜像并编译 + 5 个二进制,在树莓派上可能十余分钟且易受网络影响失败)。 +- **CI/CD 门禁**:新增 `go-ci`(build/vet/test)、`pr-validate`(分支/标题/ + 描述/单一变更类型)、`pr-label`(自动打标)、`release`(tag + 草稿 release)、 + `stale`、`sync-labels`。此前仓库无任何 CI。 +- **移除 `build.yaml`**:legacy builder 配置,自 Supervisor 2026.04.0 起 + **不再被读取**,其 `build_from` / `args.BUILD_VERSION` 均为死配置。 + +### 内部 +- **上游同步保护**:`sync_vendor.sh` 此前会静默覆盖 addon 对上游文件的改动, + 实测跑一次即导致**编译失败**(`svc.go` 引用了被覆盖掉的 `pool`/`config` + 扩展)。现将 `pool` / `config` / `server` / `upstream` 四个文件纳入 + `PROTECT_FILES`,并在结束时对其做**上游差异检查**——上游若改动过会显式 + 告警提示人工 merge,而不再静默跳过。 +- 修正 `TestModelsDynamic` 的过期断言(v1.1.0b11 起 `/v1/models` 会追加虚拟 + `cheapest` 条目,测试仍按 3 个断言,已失败多时)。 + ## v1.1.0b12 (2026-09-07) 测试版 ### 变更 diff --git a/config.yaml b/config.yaml index b313fd7..089dce0 100644 --- a/config.yaml +++ b/config.yaml @@ -1,5 +1,5 @@ name: "AI Proxy" -version: "1.1.0b13" +version: "1.1.0b14" slug: "ai-proxy" description: "多平台 AI 账号(WorkBuddy/CodeBuddy + TraeWork)聚合为 OpenAI 兼容 API,模型带来源前缀自动路由;自动签到、多账号轮转。" url: "https://github.com/C3H3-AI/ai-proxy"