wucm667
0875143d98
fix: show optional affiliate code on registration
2026-07-26 02:47:35 +08:00
github-actions[bot]
2730c1c43b
chore: sync VERSION to 0.1.165 [skip ci]
2026-07-25 13:59:09 +00:00
Wesley Liddick
e9a58c1cb8
Merge pull request #4814 from yiancode/fix/email-alias-registration-dedup
...
fix(auth): 注册查重归一化邮箱别名,防止单收件箱批量注册
v0.1.165
2026-07-25 20:54:37 +08:00
shaw
ef0ca5bdf5
style: 修正 dotStrippedEmailExpr 注释以满足 gofmt 文档注释规则
2026-07-25 19:51:19 +08:00
shaw
bc3acd6e28
fix(auth): 收紧注册别名查重(根点绕过 / 误拒 / 无界扫描 / 并发竞态)
...
对 #4814 的审计跟进修复:
- 域名尾随点绕过:user@gmail.com . 的域名不在 gmail 家族名单内,点号折叠与
googlemail 归一被整体跳过,别名刷号原样可复现。归一化入口统一去掉 FQDN 根点。
- 误拒合法用户:剥 "+后缀" 缺空串守卫,+alice@ 与 +bob@ 都折叠成 @domain,
该域后续 "+x@" 注册会永久 EMAIL_EXISTS 且无自助恢复。改为仅当 "+" 不在首位时剥离。
- 无界不可索引全表扫描:原实现按 LOWER(email) LIKE '%@domain' 把整域邮箱读进内存,
且挂在公开未鉴权的 send-verify-code 上。改为按去点邮箱
REPLACE(LOWER(TRIM(email)), '.', '') 做等值 + "local+%@domain" 前缀探针并带 LIMIT,
新增同表达式的部分索引(migrations/190)。TRIM 口径与既有精确匹配一致,
历史带首尾空白的行同样命中;LIKE 元字符转义,% 与 _ 不会扩大匹配面。
- 并发竞态:注册改走 CreateWithEmailAliasGuard,在邮箱唯一性锁上追加收件箱身份锁并在
锁内复查,避免同一收件箱的多个别名变体同时通过服务层前置查重。管理员建号仍走
Create,不受别名限制。
- 能力断言静默 fail-open:别名查重方法上提到 UserRepository 端口(编译期强制),
移除可选接口类型断言与静默降级分支。
- OAuth 邮箱注册的两条建号路径(同样发放注册赠额)纳入同一查重口径;邮箱换绑/绑定
不纳入,否则用户把邮箱改成自己收件箱的别名会被误拒。
2026-07-25 19:40:53 +08:00
yian and Claude Fable 5
b6f9277515
fix(auth): normalize email aliases in registration dedup
...
Registration duplicate checks compared the email verbatim (lowercase +
trim only), so a single inbox could spawn unlimited accounts via provider
alias features: plus addressing (user+tag@gmail.com ) and the Gmail dot
trick (u.s.e.r@gmail.com ) both deliver to the same mailbox but were seen
as distinct, verifiable addresses. This lets abusers bulk-register to farm
signup grants while the domain whitelist and email verification pass.
Add NormalizeEmailForAliasDedup to collapse these variants to a single
"inbox identity" and use it (via existsByEmailOrAlias) on the three local
email-registration paths: register, send-verify-code, and its async
variant. The exact ExistsByEmail check runs first; only on a miss do we
scan the candidate domains (gmail.com/googlemail.com are mutual aliases)
and compare normalized forms. Lookup errors fail closed, matching the
existing check, so the path cannot be bypassed by inducing errors.
Scoped to registration only — email storage, display, login, and delivery
are unchanged. OAuth-bound emails (already provider-verified) are out of
scope.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-25 19:19:15 +08:00
Wesley Liddick
2e2638c01d
Merge pull request #4864 from Wei-Shaw/fix/ollama-usage-pg-compat-and-fetch-floor
...
fix(ollama): 修复 PG<=16 上 due 判定失效并恢复抓取下限
2026-07-25 18:58:06 +08:00
shaw
1763db3a2d
fix(ollama): 修复 PG<=16 上 due 判定失效并恢复抓取下限
...
#4850 的用量刷新调度有三个问题,本次一并修复。
jsonpath .datetime() 直到 PostgreSQL 17 才接受 ISO-8601 的 Z 标识符,
而服务写入的快照时间戳全部是 UTC(即 Z 形式)。在 PG 14/15/16 上
ollamaCloudUsageParseRFC3339SQL 因此把 fetched_at / last_attempt_at /
next_refresh_at 全部解析成 NULL,due 判定整条退化为 fail-open 分支:
每轮 20 个刷新额度被 id 最小的非 due 组占满,id 更大的组永远不会刷新——
正是该 PR 声称修复的饥饿场景。项目文档声明支持 PG 14/15/16,而集成测试
harness 固定使用 postgres:18.1,因此现有测试无法发现。
修法是在送入 jsonpath 前把结尾的 Z 改写为 +00:00。仍保留 jsonpath 而不
直接 ::timestamptz,因为通过形状正则但日历非法的值(如 2026-02-30)需要
fail-open 成 NULL 而非中断整条查询。已在真实 PG 14/15/16/17/18 上验证
五个版本行为一致,且非法日历与垃圾输入仍正确 fail-open。
成功路径不再查阅 next_refresh_at,而 nextOllamaCloudUsageDelay 的
15 分钟下限正作用于该字段,导致同组对 ollama.com 的抓取下限从 15 分钟
降到一个 runner 周期。请求间隔略大于 debounce 的交互式流量(典型 Claude
Code 用法)会把单组 24 小时抓取次数从 24-96 抬高到数百次。改为对成功路径
显式施加 fetched_at + OllamaCloudUsageMinFetchInterval 的下限,Go 与 SQL
两侧同步;空闲账号不再轮询这一主要收益不受影响。
debounce_minutes 与 interval_minutes 此前各自独立校验,因此
debounce >= interval 是合法组合;此时 min(lastUsed+debounce,
fetchedAt+maxWait) 中的 debounce 项恒为死项,管理员配置被静默忽略。
改为在写入时拒绝该组合。
另修复 refreshAccount 中 ListOllamaCloudUsageGroupAccounts 的错误被
静默吞掉(违反 CLAUDE.md 禁止忽略错误):失败时回退到更窄的活动信号会
改变 due 语义,现在记录日志。
测试:
- 恢复被删除的 7/8/9 位小数秒解析覆盖,并改写为可判别形式(断言"不应
返回",解析失败会落入 fail-open 而被捕获)。已验证该测试在 PG 15 上
无此修复时失败、有修复时通过。
- 新增 min fetch interval 下限与 debounce/interval 交叉校验的单元测试。
- integration harness 新增 SUB2API_TEST_POSTGRES_IMAGE 覆盖,使套件可
针对最低受支持版本运行。
2026-07-25 18:34:37 +08:00
Wesley Liddick
bb0c38306f
Merge pull request #4850 from alfadb/feat/ollama-usage-request-debounce
...
feat(ollama): 按模型请求刷新云端用量
2026-07-25 18:09:21 +08:00
alfadb
b403f88f51
fix(ollama): 避免刷新候选饥饿
...
ListDue 在 LIMIT 前用与 service 纯函数一致的 debounce/max-wait/backoff
规则筛真正 due 组,防止有活动但未到期的组占满每轮 20 名额。
2026-07-25 15:37:06 +08:00
alfadb
f1eaed31ed
fix(ollama): 写入设置时缺省 debounce 补 1
...
兼容旧客户端省略 debounce_minutes 的 PUT 请求。
2026-07-25 15:37:06 +08:00
alfadb
0f72b7dca7
feat(ollama): 按模型请求刷新云端用量
...
将 Ollama Cloud settings HTML 自动抓取从固定间隔轮询改为请求驱动的
trailing debounce + max-wait:无新请求不再抓取,连续请求最晚在
max-wait 强制刷新;失败退避仍优先于活动 due。新增 debounce_minutes
(默认 1),interval_minutes 保留为最长等待兼容字段。
2026-07-25 15:37:05 +08:00
Wesley Liddick
43d4bae246
Merge pull request #4843 from slovx2/feature/openai-live-gateway
...
feat(openai): 支持 ChatGPT Live / Frameless 网关
2026-07-25 15:27:10 +08:00
shaw
5374ce2a0f
Merge remote-tracking branch 'origin/main' into feature/openai-live-gateway
2026-07-25 15:16:05 +08:00
shaw
7acc13a29b
fix(live): 租约丢失终止会话并补齐过期时的 usage log
...
三处功能修复(审计发现):
1. 租约续租失败按会话终结处理。RefreshLiveLease 的 Lua 在 leaseID 被 GC 后不会
重新 ZADD,重连拿不回并发槽;原先把 ErrLiveUnavailable 当临时错误交给 observer
重连,会让会话以约 1 秒一轮的节奏空转到 ExpiresAt(最长 60 分钟),期间持着
上游 WS 连接却不计入账号/用户/API Key 的任何并发限制。
2. observer 因过期放弃时补写 usage log。waitForLiveObserverRetry 原先把过期判定
混在重试条件里并返回 false,直接 return 绕过了 observeLiveCall 循环顶部的过期
分支,导致该路径既不写 usage log 也不释放租约(静默结束)。改为只判控制权归属,
过期交回循环顶部 finalize。
3. 把两处重复的三项终止判据抽成 liveSessionEnded,消除 ProxyLiveSideband 与
observeLiveCall 之间的判据漂移风险。
迁移改名 186/187 -> 188/189:原编号会成为第三个 186,且 187 与已合入 main 的
#4801 的 187_add_usage_log_session_id.sql 撞号。文件名即迁移主键,功能无害但易误读。
新增两个测试均经变异验证(去掉修复后会失败)。
2026-07-25 15:15:59 +08:00
Wesley Liddick
b99ea955d9
Merge pull request #4818 from weiness/fix/announcement-display-and-preview
...
fix(frontend): 修复home页公告弹窗样式错乱问题,增加后台公告预览功能
2026-07-25 14:44:04 +08:00
Wesley Liddick
e6a3030beb
Merge pull request #4803 from wucm667/fix/issue-4798-gemini-image-chat-content
...
fix(gemini): preserve image output in chat completions
2026-07-25 14:43:30 +08:00
Wesley Liddick
3176cdee17
Merge pull request #4823 from wucm667/fix/issue-4819-drop-orphan-tool-choice
...
Supersedes the earlier attempt #4439 by @KnWsdHunter, which its own author closed on 2026-07-20 and which was never merged. This PR discloses that prior work in its description and contributes a broader 6-case test table. Courtesy credit to @KnWsdHunter for the original diagnosis.
2026-07-25 14:43:01 +08:00
shaw
6b267e4f40
Merge branch 'main' into fix/announcement-display-and-preview
...
解决 frontend/pnpm-lock.yaml 冲突:采用 main 的 frontend/package.json 与
frontend/pnpm-lock.yaml。本 PR 附带的 postcss ^8.4.32 -> ^8.5.22 并非安全降级
(高于 main 的 pnpm.overrides 下限 >=8.5.18),但与本 PR 的公告弹窗主题无关,
回退后 PR 范围回归其本职改动。
本 PR 的功能改动(AnnouncementBell/Popup、announcement-markdown.css、
AnnouncementsView、i18n)未受影响。
2026-07-25 14:33:58 +08:00
shaw
f06c8c5698
Merge branch 'main' into fix/issue-4798-gemini-image-chat-content
...
解决 frontend/pnpm-lock.yaml 冲突:采用 main 的 frontend/package.json 与
frontend/pnpm-lock.yaml,回退本 PR 附带的 postcss ^8.4.32 -> ^8.5.12 改动。
main 已通过 pnpm.overrides ("postcss@<8.5.18": ">=8.5.18") 强制安全下限,
本 PR 的直接依赖下限低于该值,保留会与 overrides 冲突且无安全收益。
本 PR 的功能改动(gemini_* compat service 及其测试)未受影响。
2026-07-25 14:33:06 +08:00
shaw
8bed40c67b
Merge branch 'main' into fix/issue-4819-drop-orphan-tool-choice
...
解决 frontend/pnpm-lock.yaml 冲突:采用 main 的 frontend/package.json 与
frontend/pnpm-lock.yaml,回退本 PR 附带的 postcss ^8.4.32 -> ^8.5.12 改动。
main 已通过 pnpm.overrides ("postcss@<8.5.18": ">=8.5.18") 强制安全下限,
本 PR 的直接依赖下限低于该值,保留会与 overrides 冲突且无安全收益。
本 PR 的功能改动(openai_gateway_grok.go 及其测试)未受影响。
2026-07-25 14:32:18 +08:00
Wesley Liddick
a29a62112b
Merge pull request #4842 from Cynicismcart/fix/openai-pool-retry-transient-cooldown
...
fix(openai): preserve pool-mode same-account retries
2026-07-25 14:30:04 +08:00
Wesley Liddick
eb03be0dbf
Merge pull request #4788 from wucm667/fix/issue-4782-pool-5xx-cooldown
...
fix(grok): avoid pool cooldown on 5xx
2026-07-25 14:29:36 +08:00
Wesley Liddick
6d956bdc20
Merge pull request #4801 from SemonCat/feat/persist-session-id
...
feat(usage): persist client session identifiers
2026-07-25 14:03:32 +08:00
Wesley Liddick
333acde7d1
Merge pull request #4832 from ListenCodes/fix/openai-apikey-responses-item-id-v2
...
fix(openai): sanitize API-key responses item IDs
2026-07-25 13:42:35 +08:00
Wesley Liddick
9994eaa70f
Merge pull request #4804 from scp-planet/fix/openai-strip-input-namespace
...
fix(openai): strip input item namespaces before HTTP forwarding / HTTP 转发前移除 input 项 namespace
2026-07-25 13:42:17 +08:00
Wesley Liddick
a9866f03db
Merge pull request #4841 from wucm667/fix/issue-4838-affiliate-mobile-copy
...
fix(frontend): adapt affiliate copy controls for mobile
2026-07-25 13:42:03 +08:00
Wesley Liddick
0e39e21fa2
Merge pull request #4796 from 404QAQ/codex/fix-image-request-diagnostics
...
fix(images): log requested quality and size
2026-07-25 13:41:52 +08:00
Wesley Liddick
95cc6ee2c0
Merge pull request #4793 from 404QAQ/codex/fix-pricing-empty-remote-url
...
fix(pricing): skip remote scheduler without URL
2026-07-25 13:41:40 +08:00
song
db6fbdbf29
fix(openai): satisfy Live CI checks
2026-07-25 12:51:20 +08:00
song
988d4b577e
feat(openai): add macOS Live attestation
2026-07-25 12:50:46 +08:00
song
ec23716ee4
fix(openai): align Live request metadata
2026-07-25 12:50:46 +08:00
song
e6eb23eaac
feat(openai): add Live gateway support
2026-07-25 12:50:46 +08:00
Wesley Liddick
37ed639d1e
Merge pull request #4852 from Wei-Shaw/fix/bump-postcss-audit
...
fix(security): 升 postcss 到 >=8.5.18 修复 frontend-security 红灯
2026-07-25 12:01:42 +08:00
shaw
a5aae5db9a
fix(security): 升 postcss 到 >=8.5.18 修复 frontend-security 红灯
...
新披露两条 high 级公告命中锁文件里的 postcss@8.5.6,frontend-security 的
audit exception 检查失败:
- GHSA-6g55-p6wh-862q(2026-07-23 披露,修复版 8.5.12)
CSS 注释中攻击者可控的 sourceMappingURL 导致任意文件读取与信息泄露
- GHSA-r28c-9q8g-f849(2026-07-24 披露,修复版 8.5.18)
Previous Source Map 自动加载存在路径穿越,导致任意 .map 文件泄露
postcss 不只是 devDependency —— 它经 vue → @vue/compiler-sfc 进入生产依赖树,
因此 `pnpm audit --prod` 会命中。用 pnpm.overrides 而非只升直接依赖,可保证
所有引入路径的实例都被抬到修复版(沿用本仓 form-data@<4.0.6 的既有写法)。
锁文件用 pnpm 10 重新解析以匹配现有锁文件的生成工具,避免 pnpm 9 误删
11 处 libc: [glibc|musl] 平台门控字段;lockfileVersion 保持 9.0。
实际解析到 postcss 8.5.23,nanoid 3.3.11→3.3.16 是 postcss 自身依赖的
补丁级跟随,diff 无其他无关变动。
验证:复现 CI 失败步骤(pnpm audit --prod --audit-level=high +
tools/check_pnpm_audit_exceptions.py)已通过;CI 所用 pnpm 9 的
--frozen-lockfile 接受该锁文件;vue-tsc --noEmit、pnpm build、vitest 均通过。
2026-07-25 11:45:42 +08:00
shaw
6c9b84cc7a
feat: 适配 Anthropic 新模型 claude-opus-5
...
模型登记:/v1/models 清单、Bedrock 默认映射(us.anthropic.claude-opus-5-v1)、
定价条目($5/$25 per MTok、1M 上下文、128K 输出)、前端模型清单与
Anthropic/Bedrock 预设映射、限流 scope 简称。
同时修复两个会静默出错的问题:
- 定价家族兜底 3 倍超收:定价数据缺 claude-opus-5 时,matchByModelFamily
的 Phase 2 关键字兜底会落到 opus-4 系列、getFallbackPricing 会落到
claude-3-opus,两条路都按 $15/$75 计费(官方 $5/$25),输入输出双双
3 倍超收且无任何报错。两处补 opus-5 家族并回退到同价的 4.8;判断用
opus-5/opus5 子串而非裸 "5",避免误伤 claude-opus-4-5。顺带补齐兜底表
缺失的 claude-opus-4.8(此前同样会掉到 claude-3-opus)。
- Bedrock 版本闸门降级:claudeVersionRe 强制要求 major-minor 两段版本号,
只有主版本号的 claude-opus-5 / claude-sonnet-5 完全不匹配,被当成旧模型:
isBedrockOpus47OrNewer 假导致 thinking.enabled 不转 adaptive(Opus 5 上游
已移除 budget_tokens,透传直接 400)、isBedrockClaude45OrNewer 假导致
cache_control.ttl 被剥离、bedrockModelSupportsToolSearch 假导致 tool search
被过滤。改为 minor 可选(缺省 minor=0),claude-sonnet-5 的同一问题一并修复。
Vertex 无需改动:normalizeVertexAnthropicModelID 只处理 -YYYYMMDD→@YYYYMMDD,
无日期后缀的裸 ID 原样透传即正确。context-1m-2025-08-07 白名单不动:Opus 系
上游不接受该 beta,且 Opus 5 的 1M 上下文是默认能力。
Antigravity 暂不接入:无上游支持证据,mapAntigravityModel 对未映射模型返回
空字符串即"该账号不支持",fails closed 安全。
回归测试 internal/service/claude_opus5_test.go 覆盖定价两层兜底、Bedrock
三个闸门、thinking 转换与模型清单;逐个回退上述修复已确认测试会红。
2026-07-25 11:22:42 +08:00
Cynicismcart
521db6869e
fix(openai): preserve pool-mode same-account retries
...
Avoid recording the generic account-model transient cooldown for pool-mode statuses explicitly configured for same-account retry. This lets the bounded request-local retry budget complete while preserving cooldowns for other statuses and non-pool accounts.
2026-07-25 05:31:31 +08:00
wucm667
30d146e8b5
fix(frontend): adapt affiliate copy controls for mobile
2026-07-25 04:27:19 +08:00
LIULIXING
1891faa68d
fix(openai): keep item ID sanitization linear
2026-07-25 01:40:26 +08:00
wucm667
41456b69dd
fix(frontend): upgrade postcss for security audit
2026-07-24 22:37:42 +08:00
ListenCodes
c5d9d57940
fix(openai): sanitize API-key responses item IDs
2026-07-24 20:15:58 +08:00
wucm667
41f12e874d
fix(grok): drop orphaned Responses tool choice
2026-07-24 16:25:53 +08:00
weiness
67bb446b5c
fix(deps): upgrade postcss for GHSA-6g55-p6wh-862q
2026-07-24 16:12:34 +08:00
weiness
972a4a471e
feat(admin): add announcement preview action
2026-07-24 15:44:34 +08:00
weiness
7b387e479d
fix(frontend): share announcement rich text styles
2026-07-24 15:44:27 +08:00
wucm667
b5979050f3
fix(frontend): upgrade postcss for security audit
2026-07-24 08:33:58 +08:00
wucm667
8276fdf605
fix: resolve Gemini compat test lint
2026-07-24 03:00:26 +08:00
scp-planet
d2d4fb9221
fix(openai): satisfy buffer write lint checks
2026-07-24 02:59:32 +08:00
scp-planet
1bdf99109b
fix(openai): strip input namespaces for api key accounts
2026-07-24 02:59:32 +08:00
scp-planet
e70fbf3204
fix(openai): strip residual input namespaces before HTTP forwarding
2026-07-24 02:59:32 +08:00