wucm667
5465003d07
test(group): 补充分组列表可用账号数与总账号数统计正确性的集成测试
...
修复 #2579 报告的可用账号数等于总数问题:
上游已通过 loadAccountCounts / GetAccountCount 两处 SQL 中的
COUNT(*) FILTER (WHERE status='active' AND schedulable=true)
正确区分可用账号,但缺少覆盖 active < total 场景的测试,
导致回归容易被忽略。
新增三个集成测试:
- TestListWithFilters_ActiveAccountCount_LessThanTotal
含 active+schedulable、disabled、active+unschedulable 三类账号,
断言 AccountCount=3、ActiveAccountCount=1,
并验证 GetAccountCount 返回值与 ListWithFilters 字段一致。
- TestListWithFilters_RateLimitedAccountCount
验证 rate_limit_reset_at 未过期的账号计入 ActiveAccountCount(仍可调度),
同时单独出现在 RateLimitedAccountCount 中。
- TestListWithAccountCountSort_AttachesActiveCount
通过 SortBy=account_count 触发 listWithAccountCountSort 路径,
验证排序按 total 而非 active,且两个字段均被正确附加。
Fixes #2579
2026-05-20 11:33:29 +08:00
Wesley Liddick
03730fbcf3
Merge pull request #2585 from Arron196/feature/channel-monitor-openai-detection
...
优化渠道监控 OpenAI 检测协议与内置模板
2026-05-20 08:50:44 +08:00
benjamin
a5072f77bd
feat(channel-monitor): 保存模板协议快照
...
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-19 22:05:43 +08:00
name
2eb622f2f6
Remove ops retry replay storage
2026-05-19 19:37:41 +08:00
Wesley Liddick
2a242aec0f
Merge pull request #2573 from wucm667/feat/redeem-code-expiry
...
feat(redeem): 兑换码支持设置使用有效期
2026-05-19 16:25:12 +08:00
wucm667
e4aaf0af29
feat(redeem): 兑换码支持设置使用有效期
2026-05-19 15:53:28 +08:00
Wesley Liddick
1b6ed24c33
Merge pull request #2492 from DaydreamCoding/feat/dingtalk-login
...
feat(dingtalk): 钉钉 OAuth 登录接入 + internal_only 用户属性同步
2026-05-19 15:36:13 +08:00
DaydreamCoding
b19da9c7fe
feat(dingtalk): 钉钉 OAuth 登录接入与 internal_only 用户属性同步
...
⚠️ 应用类型约束:当前实现仅支持「钉钉登录-企业内部应用」(DingTalk 开放平台
internal_app 类型)。第三方个人应用、第三方企业应用类型暂不支持——OAuth 流程
相同但 corp 校验、跨企业行为不同。backend 通过 DingTalkAppKind 校验对非
internal_app 类型 fail-closed(硬约束)。
钉钉 OAuth 登录主链
- 4 步 OAuth 链:ExchangeCodeForUserToken / GetUnionIdByUserToken /
GetUserIdByUnionId / GetStaffInfoByUserId;app token 缓存
- pending session 机制持久化 OAuth 中间态;cookie-only token 持久化
- 三种分流:bind_login_required / email_completion / choose_account_action
- corp_restriction_policy 支持 none + internal_only;stale "whitelist" 在
加载层与写入层均静默 coerce 为 none + slog.Warn
- bypass_registration 开关:企业内部模式豁免全局 REGISTRATION_DISABLED
- isReservedEmail / signup_source / canUnbindProvider / OAuth pending flow
等横切点支持 dingtalk provider
- migration 136:4 表 CHECK 约束加入 'dingtalk' provider 值
internal_only 模式同步企业邮箱/姓名/部门到用户属性
- SyncCorpEmail / SyncDisplayName / SyncDept 三个独立开关 + 对应
SyncXxxAttrKey 目标属性 key(默认 dingtalk_email / dingtalk_name /
dingtalk_department);非 internal_only policy 在写入层与加载层均
coerce 为 false,admin handler 与 setting_service 双层兜底
- 同步语义:首次注册写 users.username(昵称优先 → 企业姓名 fallback),
之后每次登录刷新 3 个属性;空值也写入以覆盖旧值
- 邮箱三级 fallback:org_email > email > extension["企业邮箱"]
(钉钉自定义字段 JSON)
- 部门路径递归向上拼接,跳过 dept_id=1 选首个真实子部门,剥离根组织名
- GetUnionIdByUserToken 同时返回 OIDC /contact/users/me 的 nick 字段;
新增 GetDeptInfo 调用 OAPI /topapi/v2/department/get
- AuthHandler 注入 UserAttributeService;OAuth pending flow 在
createPendingOAuthAccount / bindPendingOAuthLogin 分别派发到
AfterRegistration(syncUsername=true)/ AfterLogin
- migration 137 seed dingtalk_email/name/department 三个用户属性定义
附带修复(同集成路径暴露的两个 OAuth 注册回归)
- LoginOrRegisterOAuthWithTokenPair 新建用户分支用 inferLegacySignupSource
覆写 caller 显式传入的 signupSource,导致 dingtalk/linuxdo/oidc/wechat
渠道授权按 email 渠道读取;改为只在 caller 未显式传入时回退邮箱推断
- mergeProviderDefaultGrantSettings 把 parse fallback 默认值
(Concurrency=5 / Balance=0) 当作"未配置"哨兵,admin 显式设 5 时被误判
退回全局默认(复现:全局默认 1 + 渠道默认并发 5 + grant_on_signup → 新
用户实际 concurrency=1);去掉哨兵,admin 任何 >=0 值都覆盖 globalDefaults
前端
- DingTalk Login / Callback / EmailCompletion / ChoiceAccount / Error
视图;router + auth API client
- admin SettingsView:corp policy radio(none / internal_only)+ bypass
注册开关 + i18n;internal_only 下展示三同步开关 + 目标 attr key 下拉
(拉取 user attribute definitions),展示 fieldEmail /
qyapi_get_department_list 钉钉权限申请提示
- Profile:S1 主动绑定 / S5 解绑钉钉按钮 + 合成邮箱防自锁
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 15:27:47 +08:00
DaydreamCoding
664e9fdcd4
feat(usage): 用户用量按平台拆分 + UsersView 列设置可配置 + 用量列排序
...
后端
- BatchUserUsageStats / UserDashboardStats 新增 ByPlatform 字段
复用 ops 路径 COALESCE(g.platform, a.platform) 语义,不冗余 DB 字段
- 抽出 usageLogEffectivePlatformExpr 常量供管理员与用户两路径共用
- GetBatchUsersUsage cacheKey 加 v=2 + 当日日期,修复跨午夜旧缓存兼容新字段
前端
- 新建 PlatformUsageBreakdown:管理员用量列 hover tooltip 展示各平台 today/total
- 新建 PlatformCostCell:单平台 today/total 紧凑单元格
- UsersView 列设置新增 Claude/OpenAI/Gemini/Antigravity 四个平台子列,默认隐藏可手动启用
- 普通用户 Dashboard 新增 Row 3 平台拆分卡片,受 isSimple 控制
- 平台之和 < 总值时显式展示"其他"行,避免数字对不齐
- last_active_at 从 FORCED_VISIBLE_COLUMNS 移除,允许用户隐藏并持久化
- 列设置加 schema 版本号 + 迁移机制,老用户升级时新增默认隐藏列自动应用
- UsersView 用量列(汇总 + 4 平台子列)加入前端单页排序:列头单按钮 + 弹出菜单
切换"今日 / 近30天",三态循环 desc → asc → off;菜单底部备注"仅对本页数据排序"
- sortedUsers computed 在 server-side-sort 结果之上叠加本地排序,缺失值按 0 处理;
usageSort 状态独立 localStorage 持久化,互不干扰后端 sort_by
- i18n 新增 admin.users.sortBy / sortCurrentPageOnly
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 15:25:34 +08:00
Wesley Liddick
902af920b7
Merge pull request #2456 from Evsdrg/fix/unbounded-queries-and-sort
...
fix(repo): 公告查询添加分页上限,优化分组按账户数排序的数据加载方式
2026-05-19 14:51:59 +08:00
Wesley Liddick
e365aae450
Merge pull request #2450 from wucm667/codex/issue-2431-responses-api-support
...
feat: 支持后台配置 OpenAI Responses API 路由
2026-05-19 14:47:10 +08:00
cepvor
ab6510f1a0
fix(repo): 为公告查询添加分页上限,优化分组按账户数排序的数据加载
...
- announcement ListActive: 添加 Limit(200) 防止无界查询
- group listWithAccountCountSort: 改为先只查 ID + sort_order,
再批量加载账户统计,排序分页后仅加载当前页的完整实体,
避免全量加载所有字段后做内存排序。
Co-Authored-By: deepseek-v4-pro[1m] <deepseek-ai@claude-code-best.win>
2026-05-14 16:38:45 +08:00
wucm667
862819042c
feat(openai): 支持后台配置 Responses API 路由
2026-05-14 11:46:24 +08:00
2ue
4840194b18
Fix lint issues in image billing change
2026-05-12 16:04:24 +08:00
2ue
bb4c1abe28
Fix image billing size normalization
2026-05-12 15:21:31 +08:00
Wesley Liddick
d52da45363
Merge pull request #2202 from Michael-Jetson/main
...
新增三大功能:兑换码邀请返利、批量修改用户并发数、Markdown页面渲染
2026-05-07 09:35:14 +08:00
shaw
fff4a300c6
feat(risk-control): add content moderation audit
2026-05-07 09:14:47 +08:00
Michael-Jetson
4cbd4932a0
feat: add redeem code affiliate rebate, batch concurrency API, and markdown page rendering
...
1. Redeem code affiliate rebate: balance-type redeem codes now trigger
invite rebate for the inviter. Payment fulfillment uses context key
to prevent double-rebate.
2. Batch concurrency update: new POST /admin/users/batch-concurrency
endpoint supporting mode=set/add with all=true for all users.
3. Markdown page rendering: new GET /api/v1/pages/:slug API serves local
.md files. Custom menu items with url="md:slug" render markdown with
collapsible TOC sidebar, scroll spy, and copy buttons on code blocks.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-05 06:44:37 -07:00
2ue
6faa344916
feat: add OpenAI image generation controls
2026-05-05 03:26:54 +08:00
shaw
0b84d12dbb
fix: correct affiliate audit record sources
2026-05-03 22:12:57 +08:00
lyen1688
0a914e034c
fix: include matured affiliate quota in admin overview
2026-05-03 20:33:13 +08:00
lyen1688
6a41cf6a51
feat: add admin affiliate record pages
2026-05-03 20:33:13 +08:00
shaw
733627cf9d
fix: improve sticky session scheduling
2026-04-30 11:38:11 +08:00
shaw
8bf2a7b88a
fix(scheduler): resolve SetSnapshot race conditions and remove usage throttle
...
Backend: Fix three race conditions in SetSnapshot that caused account
scheduling anomalies and broken sticky sessions:
- Use Lua CAS script for atomic version activation, preventing version
rollback when concurrent goroutines write snapshots simultaneously
- Add UnlockBucket to release rebuild lock immediately after completion
instead of waiting 30s TTL expiry
- Replace immediate DEL of old snapshots with 60s EXPIRE grace period,
preventing readers from hitting empty ZRANGE during version switches
Frontend: Remove serial queue throttle (1-2s delay per request) from
usage loading since backend now uses passive sampling. All usage
requests execute immediately in parallel.
2026-04-29 22:48:39 +08:00
shaw
9b6dcc57bd
feat(affiliate): 完善邀请返利系统
...
- 修复返利不到账的根因:tryClaimAffiliateRebateAudit 中 PostgreSQL 参数类型推断冲突
- 补全 OAuth 注册路径(LinuxDo/OIDC/WeChat/Pending Flow)的邀请码绑定
- 前端 OAuth 注册页面传递 aff_code 参数
- 新增返利冻结期机制:可配置冻结时间,到期后自动解冻(懒解冻)
- 新增返利有效期:绑定后 N 天内有效,过期不再产生返利
- 新增单人返利上限:超出上限部分精确截断
- 增强返利流程 slog 结构化日志,便于排查问题
- 已邀请用户列表增加返利明细列
2026-04-26 12:42:35 +08:00
shaw
4e1bb2b445
feat(affiliate): add feature toggle and per-user custom invite settings
...
- 在系统设置「功能开关」中新增邀请返利总开关,默认关闭;
关闭态:菜单隐藏、注册忽略 aff、新充值不返利,但已有 quota 仍可转余额
- 支持管理员为指定用户设置专属邀请码(覆盖随机码,全局唯一)
- 支持管理员为指定用户设置专属返利比例(覆盖全局比例,可单条/批量调整)
- 在系统设置邀请返利卡片内嵌入专属用户管理表格(搜索/编辑/批量/删除),
删除采用项目通用 ConfirmDialog,会同时清除专属比例并把邀请码重置为系统随机码
- /affiliate 用户页新增「我的返利比例」卡片与动态使用说明,让用户直观看到
分享后能拿到多少(同源 resolveRebateRatePercent 计算,与实际充值一致)
- 新增数据库迁移 132 添加 aff_rebate_rate_percent 与 aff_code_custom 列
- 新增 admin 路由组 /api/v1/admin/affiliates/users/* 共 5 个端点
- AffiliateService 改为只依赖 *SettingService,去除冗余的 SettingRepository
- 邀请码格式校验放宽到 [A-Z0-9_-]{4,32},兼容旧 12 位系统码与新自定义码
- 补充单元测试与集成测试覆盖新方法、冲突路径与边界值
2026-04-25 20:22:07 +08:00
shaw
095f457c57
feat(openai): port /responses/compact account support flow (PR #1555 )
...
将 vansour/sub2api#1555 的 OpenAI compact 能力建模手工移植到当前 main:账号
级 compact 状态/auto-force_on-force_off 模式、compact-only 模型映射、调度器
tier 分层(已支持 > 未知 > 已知不支持)、管理后台 compact 主动探测,以及对应
i18n/状态徽章。普通 /responses 流量行为不变,无数据库迁移。
2026-04-25 14:52:58 +08:00
shaw
aa8ee33b0a
refactor(affiliate): tighten DI and harden inviter code validation
...
- Drop SetAffiliateService setters and ProvideAuthService /
ProvidePaymentService / ProvideUserHandler wrappers in favor of direct
Wire constructor injection. AffiliateService has no back-edge to
Auth/Payment/User, so the indirection was never required.
- Change RegisterWithVerification's variadic affiliateCode to a fixed
parameter; adjust all call sites.
- Validate aff_code length and charset in BindInviterByCode before any
DB lookup, eliminating timing-side-channel and useless DB roundtrips
on malformed input.
- Make affiliate cache invalidation synchronous; surface Redis errors
via the project logger instead of swallowing them in a detached
goroutine.
- Add an integration test guarding cross-layer tx propagation in
AccrueQuota and a unit test pinning the aff_code format rules.
2026-04-25 08:44:18 +08:00
VpSanta33
f03de00cb9
feat: add affiliate invite rebate flow and admin rebate-rate setting
2026-04-24 22:22:26 +08:00
erio
5e060b2222
Merge remote-tracking branch 'upstream/main' into feat/channel-insights
...
# Conflicts:
# backend/cmd/server/wire_gen.go
2026-04-23 22:30:45 +08:00
erio
67518a59ac
revert: remove fork-only changes from release sync
...
Revert payment/wechat, sora/claude-max cleanup, fork-only migrations,
and cosmetic changes that were brought in by the release sync commit.
Keep only channel-monitor related improvements:
- PublicSettingsInjectionPayload named struct with drift test
- ChannelMonitorRunner graceful shutdown in wire
- image_output_price in SupportedModelChip
- Simplified buildSelfNavItems in AppSidebar
- Gateway WARN logs for 503 branches
2026-04-23 21:40:58 +08:00
erio
748a84d871
sync: bring over remaining release/custom-0.1.115 changes
...
- Extract PublicSettingsInjectionPayload named struct with drift test
- Add channel_monitor_default_interval_seconds to SSR injection
- Add image_output_price to SupportedModelChip
- Simplify AppSidebar buildSelfNavItems (admins see available channels)
- Add gateway WARN logs for 503 no-available-accounts branches
- Wire ChannelMonitorRunner into provideCleanup for graceful shutdown
- Add migrations 130/131 (CC template userid fix + mimicry field cleanup)
- Clean up fork-only features (sora, claude max simulation, client affinity)
- Remove ~320 obsolete i18n keys
- Add codexUsage utility, WechatServiceButton, BulkEditAccountModal
- Tidy go.sum
2026-04-23 20:55:18 +08:00
Wesley Liddick
827a4498e0
Merge pull request #1829 from ZHOUKAILIAN/feature/codex-oauth-proxy-message
...
fix: 明确 OpenAI OAuth 未配置代理时的错误提示
2026-04-23 16:55:04 +08:00
Wesley Liddick
8dbbd94299
Merge pull request #1836 from wucm667/fix/account-daily-weekly-quota-cache-invalidation
...
fix: 修复账户配额跨越时调度快照入队逻辑
2026-04-23 16:49:25 +08:00
james-6-23
dc5d42addc
feat(rpm): RPM 限流模块优化
...
P0:
- rpm_override 嵌入 Auth Cache Snapshot,消除每请求 DB 查询 (snapshot v6→v7)
- 429 RPM 响应返回 Retry-After 头(当前分钟剩余秒数)
P1:
- ClearAll 按钮直连 DELETE API,带 loading 防重复
- 新增 GET /admin/users/:id/rpm-status 管理员 RPM 用量查询端点
优化:
- checkRPM 从级联互斥改为并行取最严,user.rpm_limit 作为全局硬上限始终生效
- Override/Group 变更后自动失效 auth cache
- fail-open 语义不变,Redis 故障不阻塞业务
2026-04-23 16:34:37 +08:00
wucm667
bcf4aedcde
fix: 修复账户配额跨越时调度快照入队逻辑
2026-04-23 14:53:57 +08:00
wx-11
11cf23da7d
修改403逻辑: 先临时冷却,再根据连续次数决定是否判坏号
2026-04-23 12:58:13 +08:00
zhoukailian
2489ea3699
fix: clarify OpenAI OAuth proxy errors
2026-04-23 12:23:04 +08:00
shaw
45065c23d5
fix(ci): run 108a migration before 109 in backfill integration test
2026-04-22 18:36:44 +08:00
IanShaw027
9de7a72cce
fix(upgrade): close payment and oidc compatibility gaps
2026-04-22 18:01:51 +08:00
IanShaw027
ad4600964e
fix(ci): clean up lint and dead code
2026-04-22 16:38:36 +08:00
IanShaw027
36aed35957
fix(auth): harden oauth identity upgrade paths
2026-04-22 14:56:56 +08:00
IanShaw027
01a991f56f
fix(test): restore identity repo integration imports
2026-04-22 13:22:33 +08:00
IanShaw027
81c827ee51
fix(profile): stabilize identity binding management
2026-04-22 13:19:28 +08:00
IanShaw027
06136af805
fix(upgrade): preserve legacy auth and payment compatibility
2026-04-22 13:18:10 +08:00
IanShaw027
1ffebbb568
fix(migrations): keep auth identity and payment upgrades safe
2026-04-22 12:29:52 +08:00
IanShaw027
18481a100b
fix(migrations): defer online ddl follow-ups safely
2026-04-22 11:17:45 +08:00
IanShaw027
7fbd5177c2
fix(ci): make legacy migration cleanup resilient
2026-04-22 09:15:39 +08:00
IanShaw027
fdf72eb511
fix(ci): repair integration repository tests
2026-04-22 02:42:43 +08:00
IanShaw027
b13e34f831
fix(ci): align auth and payment verification tests
2026-04-22 02:32:53 +08:00