Wesley Liddick
1702ee1362
Merge pull request #5078 from wucm667/fix/issue-5072-subscription-expiry-label
...
fix(frontend): correct subscription expiry labels
2026-07-31 11:44:07 +08:00
Wesley Liddick
c4b461c68c
Merge pull request #5063 from lucas-ward/codex/issue-4211
...
fix(payment): keep subscription plan titles readable
2026-07-31 11:44:00 +08:00
wucm667
fb40211305
fix(frontend): correct subscription expiry labels
2026-07-30 12:47:05 +08:00
BayinForge
0ee9ea5765
fix(payment): keep subscription plan titles readable
2026-07-29 21:23:16 +08:00
Zhixuan Jiang
711056f5b7
fix: clarify passkey deployment guidance
2026-07-29 08:58:33 -04:00
Wesley Liddick
f2d824836f
Merge pull request #5008 from hansnow/fix/claude-sonnet-5-status-alias
...
fix(frontend): 补充 Claude Sonnet 5 模型状态别名
2026-07-29 09:41:54 +08:00
shaw
acad7f1a09
fix(profile): stop passkey load error toast when feature is disabled
...
The PASSKEY_DISABLED silence guard compared the string error code
against error.code, but the api client puts the numeric envelope code
there and the string code in error.reason, so the guard never matched
and every /profile visit on deployments without WebAuthn configured
showed a spurious "failed to load passkeys" toast.
Read error.reason instead, and skip the credentials request entirely
when the feature is disabled so the card no longer issues a request
that is guaranteed to fail with 403.
2026-07-28 22:51:58 +08:00
hansnow
32618e71e4
fix(frontend): 补充 Claude Sonnet 5 状态别名
2026-07-28 18:17:38 +08:00
feeeei
720c405e35
feat: add model plaza with group-scoped pricing showcase
...
- public /model-plaza page (standalone + admin-embedded) listing groups
with discounted effective prices alongside LiteLLM official reference
- faceted platform/group/rate filters: cross-dimension options gray out
instead of disappearing, platform-tinted chips via accent color-mix
- paid-price columns highlighted with per-platform tint band
- OptionalJWT middleware so anonymous and signed-in users share one route
- admin settings: enable switch, require-auth switch, markdown description
2026-07-28 16:19:41 +08:00
Wesley Liddick
2e432173f7
Merge pull request #4920 from alexj11324/feat/passkey-auth
...
feat: add passkey authentication
2026-07-28 14:58:37 +08:00
shaw
38ef8dc069
feat: require account password for passkey enrollment and revocation
...
A hijacked session must not be able to silently add a passkey as a
persistent backdoor or remove the victim's credentials. Registration
(begin) and deletion now verify the account password server-side,
reusing the existing PASSWORD_REQUIRED / PASSWORD_INCORRECT errors.
The password is used instead of TOTP step-up so the guard also protects
deployments that never configured a TOTP encryption key. The password
key in both request bodies is covered by the audit middleware's
key-substring redaction, so no credential material reaches audit_logs.
Frontend: the add-passkey form gains a current-password field, and the
delete confirmation is now a dialog with a password input (replacing
window.confirm), mirroring the TOTP disable dialog. Backend error
messages (e.g. wrong password) are surfaced instead of the generic
failure toast. Rename remains password-free as it is cosmetic.
2026-07-28 14:12:46 +08:00
Wesley Liddick
f71332ff85
Merge pull request #4980 from yan9651688/feat/model-id-copy
...
feat(accounts): add one-click model ID copy
2026-07-28 11:06:48 +08:00
shaw
bfbe113f5e
fix(security-audit): 解密失败不再吞掉整份配置,修复升级后配置消失且无法保存的死锁 ( #4887 )
...
根因:prompt audit 是共享 TOTP_ENCRYPTION_KEY 加密器的功能中唯一不校验
EncryptionKeyConfigured 的落点。未配置固定密钥的部署每次重启自动生成新
密钥,v162 保存的节点 Token 密文在升级重启后永久无法解密,Reload 中
ActiveFromStorage 整体失败导致快照永远装不上:管理端 GET 回退默认 v1
(v166 起为 503),而保存路径直读数据库做 CAS 版本对比,必然冲突——
配置既看不见也改不掉。PR #4893 仅改变了报错形态,未修复根因。
修复:
- ActiveFromStorage 对单节点解密失败降级容忍:该节点运行时禁用并标记
TokenInvalid,配置整体照常激活;管理端恢复显示真实版本号,重新输入
Token 即可自愈(密文保留,密钥恢复后自动复原)
- blocking 意图下零可用节点时 evaluator 仍返回 unavailable,请求照旧
被拒,fail-closed 语义不回归;async 意图下 enqueue 直接 drop 并告警
- Save 在未配置固定加密密钥时拒绝保存新 Token(与 TOTP/Ollama/备份
一致的门控),错误码 prompt_audit_encryption_key_required
- token_status 新增 invalid 状态,前端凭据列与编辑框提示重新输入
- 新增 config_token_invalid 告警日志(集合变化时记录一次,不随 5s
刷新刷屏)
2026-07-28 09:31:36 +08:00
yan9651688
d8ae153ae9
feat(accounts): make model IDs easy to copy
...
Administrators often need exact model identifiers while editing account whitelists. Add a dedicated copy action without changing model selection or upstream sync behavior.
Constraint: Keep the contribution frontend-only and avoid model routing or persistence changes
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep copy and selection as separate actions
Tested: focused Vitest, account component regression tests, frontend typecheck, lint, and production build
Not-tested: Authenticated browser screenshot
Related: Wei-Shaw/sub2api#2151
2026-07-28 09:23:52 +08:00
shaw
fead4c7ec3
feat(security): add panel API rate limiting to protect DB from high-frequency requests
...
用户可高频刷面板接口(usage/dashboard 等重聚合查询)直接打爆数据库:
现有限流器只覆盖登录/注册等公开认证入口,登录后的全部面板端点无任何限流。
三层防护(阈值均可在后台可视化配置,panel_rate_limit_settings):
1. 认证面板接口按「用户 ID」限流,与来源 IP 无关——反向代理/NAT 共享出口
(所有请求源地址坍缩为 127.0.0.1 等)不会互相误伤:
- Global 档(默认 240 rpm/账号):user/auth/payment/admin 全部登录后路由
- Heavy 档(默认 60 rpm/账号):/usage、/usage/dashboard/*、
/user/api-keys/:id/usage/daily 等重 SQL 聚合端点叠加计数
- 管理员默认豁免(可关闭)
2. 无认证公开接口(/api/v1/settings/*,每次请求都查 DB)按安全客户端 IP
限流(默认 300 rpm/IP);回环/私网/链路本地地址(反代内部转发地址)
一律跳过计数,杜绝把整条反代链路合并进同一个桶造成大面积误拦截。
3. 修复既有隐患:auth 入口限流的 IP 取值从 c.ClientIP() 切换到与审计日志/
会话绑定/API Key ACL 同源的安全客户端 IP 解析(尊重后台「信任反代转发
IP」开关快照)。原实现下默认反代部署(未配置 server.trusted_proxies)
所有用户共享同一个登录限流桶,既会全员误拦也可被单人恶意占满形成登录
DoS;开关关闭时行为与原来完全一致。
工程约束:
- 配置热路径走进程内缓存(atomic.Value + singleflight,60s TTL),
限流中间件零 DB 访问;保存后当前节点立即生效
- 面板限流 Redis 故障 fail-open(auth 入口保持原有 fail-close)
- 429 响应携带 Retry-After;错误码 RATE_LIMITED
- 支付 webhook / 公开支付回调有意不挂限流
- 新增 GET/PUT /api/v1/admin/settings/panel-rate-limit;设置页安全 tab
新增「面板接口限流」卡片(zh/en i18n 全量)
测试:rate_limiter/panel_rate_limit/setting_panel_rate_limit 单测全绿;
routes、handler/admin、-tags unit 契约测试通过;前端 vue-tsc/ESLint/
SettingsView spec(26/26,含新增交互用例)/i18n 守卫全部通过。
2026-07-27 15:12:51 +08:00
Wesley Liddick
ab73bc0c77
Merge pull request #4924 from Cynicismcart/fix/group-description-wrapping
...
修复分组描述换行与下拉框溢出
2026-07-27 13:52:44 +08:00
Wesley Liddick
b72d487b85
Merge pull request #4878 from StarryKira/codex/fix-payment-dashboard-currencies
...
fix(payment): group dashboard stats by currency
2026-07-27 11:46:23 +08:00
Wesley Liddick
131d42d25d
Merge pull request #4839 from visa2/fix/composite-route-prefix-passthrough
...
fix(composite): pass the requested model through when a prefix route leaves upstream_model empty
2026-07-27 11:44:15 +08:00
Wesley Liddick
bc9173be15
Merge pull request #4934 from OG-Wang/fix/monitor-timeline-overflow
...
fix(frontend): 修复渠道监控时间线在窄卡片下溢出
2026-07-27 11:39:34 +08:00
Wesley Liddick
beeb4b84ed
Merge pull request #4900 from wucm667/fix/issue-4889-mobile-available-channels
...
fix(frontend): adapt available channels for mobile
2026-07-27 10:19:44 +08:00
Wesley Liddick
aac44473aa
Merge pull request #4876 from wucm667/fix/issue-4846-show-usage-user
...
fix: show routed user in usage filters
2026-07-27 10:19:31 +08:00
Rick
e94383a4c4
fix(frontend): 修复渠道监控时间线在窄卡片下溢出
...
MonitorTimeline 每根柱子设置了 min-w-[3px],60 根柱子加 2px 间距的
最小总宽度为 298px。当卡片内容区宽度低于该值时(如 100% 缩放下的
部分布局),时间线整体溢出卡片边缘。改为 min-w-0 让柱子随容器等分
压缩,任意宽度下均不再溢出。
2026-07-27 09:08:56 +08:00
Cynicismcart
78f78947f1
fix(frontend): 完善下拉框视口边界处理
2026-07-27 00:41:40 +08:00
Cynicismcart
005a5d2a37
fix(frontend): 修复分组描述换行和下拉框溢出
2026-07-27 00:35:15 +08:00
Zhixuan Jiang
357c5b917b
feat: add passkey sign-in settings control
2026-07-26 11:07:12 -04:00
Zhixuan Jiang
cc62979aa7
feat: add passkey authentication
2026-07-26 09:50:28 -04:00
wucm667
16dd3d8ee6
fix(frontend): adapt available channels for mobile
2026-07-26 16:26:25 +08:00
haruka
6d99e668d2
fix(payment): group dashboard stats by currency
2026-07-26 03:18:30 +08:00
wucm667
0875143d98
fix: show optional affiliate code on registration
2026-07-26 02:47:35 +08:00
wucm667
d11b838702
fix: show routed user in usage filters
2026-07-26 02:25:54 +08:00
visa2
1614ae9c99
Merge remote-tracking branch 'origin/main' into fix/composite-route-prefix-passthrough
2026-07-25 22:20:27 +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
shaw
5374ce2a0f
Merge remote-tracking branch 'origin/main' into feature/openai-live-gateway
2026-07-25 15:16:05 +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
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
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
e6eb23eaac
feat(openai): add Live gateway support
2026-07-25 12:50:46 +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
visa2
386b57bb77
fix(composite): pass the requested model through when a prefix route leaves upstream_model empty
...
Composite model routes support a match_type: prefix mode with an optional
upstream_model. Leaving upstream_model empty is meant to pass the concrete
requested model through to the upstream, but every request matching the prefix
collapsed to the route's public_model instead. A route with
public_model=deepseek-v4, match_type=prefix and an empty upstream_model
forwarded both deepseek-v4-flash and deepseek-v4-pro upstream as deepseek-v4.
Root cause: normalizeCompositeRouteInput backfilled an empty upstream_model with
public_model at save time, so CompositeRouteResolver.Resolve never reached its
"upstreamModel == '' -> concrete requested model" fallback.
- Skip the backfill for prefix routes only; an empty upstream_model stays empty
and Resolve passes the concrete requested model through.
- exact routes keep the backfill (model == public_model, so persisted/display
contract is unchanged).
- Explicit upstream_model still forwards that fixed model in every mode.
- Frontend: add an upstream_model hint (zh/en) documenting empty = passthrough.
2026-07-25 10:20:50 +08:00
wucm667
30d146e8b5
fix(frontend): adapt affiliate copy controls for mobile
2026-07-25 04:27:19 +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
alfadb
5ac4a9fac2
feat(ollama): 支持 Cloud 官方用量自动刷新
2026-07-23 15:50:44 +08:00
Wesley Liddick
2c76506e07
Merge pull request #4734 from wjx2951874/feat/alipay-mobile-precreate-deep-link
...
feat(payment): add mobile Alipay precreate deep link
2026-07-23 14:06:18 +08:00
Wesley Liddick
aee9ab36cb
Merge pull request #4721 from superman2003/fix/ccswitch-grokbuild-4720
...
fix(frontend): import Grok keys into Grok Build
2026-07-23 11:18:02 +08:00
Wesley Liddick
31e7ae8195
Merge pull request #4726 from feitianbubu/fix/model-rate-limit-reset-format
...
fix(admin): 模型限流恢复时间进位到天并在提示中补全日期
2026-07-23 11:17:54 +08:00
Heatherm Huang
ce3272c41b
Build composite subscription bucket two
2026-07-23 09:20:52 +08:00