Commit Graph

456 Commits

Author SHA1 Message Date
erio
0d6c1c7790 feat: add independent load_factor field for scheduling load calculation 2026-03-06 05:07:10 +08:00
Wesley Liddick
32d619a56b Merge pull request #780 from mt21625457/feat/codex-remote-compact-outcome-logging
feat(openai-handler): support codex remote compact outcome logging
2026-03-05 16:59:02 +08:00
程序猿MT
61e9598b08 fix(lint): remove redundant context type in compact outcome logger 2026-03-05 16:51:46 +08:00
程序猿MT
bfe7a5e452 test(openai-handler): add codex remote compact outcome coverage 2026-03-05 16:46:14 +08:00
程序猿MT
77d916ffec feat(openai-handler): support codex remote compact outcome logging 2026-03-05 16:46:12 +08:00
guoyongchang
831abf7977 refactor: 移除冗余中间类型和不必要代码
- 移除 ScheduledTestOutcome 中间类型,RunTestBackground 直接返回 *ScheduledTestResult
- 简化 SaveResult 直接接受 *ScheduledTestResult
- 移除 handler 中不必要的 nil 检查
- 移除前端 ScheduledTestsPanel 中多余的 String() 转换

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:37:07 +08:00
guoyongchang
3a089242f8 feat: 支持基于 crontab 的定时账号测试
每个测试计划绑定一个账号和一个模型,按 cron 表达式定期执行测试,
保存历史结果并在前端账号管理页面中提供完整的增删改查和结果查看功能。

主要变更:
- 新增 scheduled_test_plans / scheduled_test_results 两张表及迁移
- 后端 service 层:CRUD 服务 + 后台 cron runner(每分钟扫描到期计划并发执行)
- RunTestBackground 方法通过 httptest 在内存中执行账号测试并解析 SSE 输出
- Redis leader lock + pg_try_advisory_lock 双重保障多实例部署只执行一次
- REST API:5 个管理端点(计划 CRUD + 结果查询)
- 前端 ScheduledTestsPanel 组件:计划管理、启用开关、内联编辑、结果展开查看
- 中英文 i18n 支持

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:06:05 +08:00
shaw
33988637b5 fix: SMTP测试连接和发送测试邮件返回具体错误信息而非internal error 2026-03-05 10:54:41 +08:00
shaw
078fefed03 fix: 修复账号管理页面容量列显示为0的bug 2026-03-05 09:48:00 +08:00
Wesley Liddick
27abae21b8 Merge pull request #724 from PMExtra/feat/registration-email-domain-whitelist
feat(registration): add email domain whitelist policy
2026-03-04 15:51:51 +08:00
shaw
0819c8a51a refactor: 消除重复的 normalizeAccountIDList,补充 PR#754 新增组件的单元测试
- 删除 account_today_stats_cache.go 中重复的 normalizeAccountIDList,统一使用 id_list_utils.go 的 normalizeInt64IDList
- 新增 snapshot_cache_test.go:覆盖 snapshotCache、buildETagFromAny、parseBoolQueryWithDefault
- 新增 id_list_utils_test.go:覆盖 normalizeInt64IDList、buildAccountTodayStatsBatchCacheKey
- 新增 ops_query_mode_test.go:覆盖 shouldFallbackOpsPreagg、cloneOpsFilterWithMode
2026-03-04 15:22:46 +08:00
Wesley Liddick
9dcd3cd491 Merge pull request #754 from xvhuan/perf/admin-core-large-dataset
perf(admin): 优化后台大数据场景加载性能(仪表盘/用户/账号/Ops)
2026-03-04 15:15:13 +08:00
Wesley Liddick
49767cccd2 Merge pull request #755 from xvhuan/perf/admin-usage-fast-pagination-main
perf(admin-usage): 优化 usage 大表分页,默认避免全量 COUNT(*)
2026-03-04 14:15:57 +08:00
xvhuan
f6fe5b552d fix(admin): resolve CI lint and user subscriptions regression 2026-03-04 14:07:17 +08:00
PMExtra
bd0801a887 feat(registration): add email domain whitelist policy 2026-03-04 13:54:18 +08:00
xvhuan
05b1c66aa8 perf(admin-usage): avoid expensive count on large usage_logs pagination 2026-03-04 13:51:27 +08:00
xvhuan
80ae592c23 perf(admin): optimize large-dataset loading for dashboard/users/accounts/ops 2026-03-04 13:45:49 +08:00
shaw
ba6de4c4d4 feat: /keys页面支持表单筛选 2026-03-04 11:29:31 +08:00
Wesley Liddick
a11ac188c2 Merge pull request #738 from DaydreamCoding/feat/ungrouped-key-setting
feat(gateway): 系统设置控制未分组 Key 调度 — Handler 层中间件拦截
2026-03-03 21:03:31 +08:00
shaw
838dad8759 feat: 重构 /v1/usage 端点,支持 quota_limited 和 unrestricted 双模式
- quota_limited 模式:返回 Key 级别的总额度、速率限制窗口用量和过期时间
- unrestricted 模式:返回订阅限额或钱包余额信息(向后兼容)
- 新增 model_stats 字段,支持 start_date/end_date 参数查询按模型用量统计
- 提取 buildUsageData/parseUsageDateRange 等辅助方法,减少主函数复杂度
- 新增 APIKeyService.GetRateLimitData 和 UsageService.GetAPIKeyModelStats
2026-03-03 20:59:12 +08:00
QTom
0c7cbe3566 feat(gateway): 系统设置控制未分组 Key 调度 — Handler 层中间件拦截
新增系统设置 allow_ungrouped_key_scheduling(默认关闭),
未分组的 API Key 在网关请求时直接返回 403,
由 RequireGroupAssignment 中间件统一拦截,
支持 Anthropic / Google 两种错误格式响应。

全栈实现:常量 → 结构体 → 解析/更新/初始化 → DTO → 管理接口 →
中间件 → 路由注册 → 前端设置界面 + i18n。
2026-03-03 19:56:27 +08:00
shaw
b8b5cec35c fix: resolve CI lint errors and test compilation failures for rate limit feature
- Fix errcheck: properly handle rows.Close() error via named return + defer closure
- Fix gofmt: auto-format billing_cache.go, api_key_service.go, billing_cache_service.go
- Add missing rate limit interface methods to 4 test stubs (GetRateLimitData, IncrementRateLimitUsage, ResetRateLimitWindows)
- Fix NewBillingCacheService calls missing the new apiKeyRepo parameter
2026-03-03 15:43:08 +08:00
Wesley Liddick
43c203333e Merge pull request #733 from DaydreamCoding/fix/group-isolation
fix(gateway): 分组隔离 — 禁止未分组账号被跨组调度
2026-03-03 15:10:30 +08:00
shaw
a80ec5d8bb feat: apikey支持5h/1d/7d速率控制 2026-03-03 15:01:10 +08:00
QTom
530a16291c fix(gateway): 分组隔离 — 禁止未分组账号被跨组调度
当 API Key 无分组时,调度仅从未分组账号池中选取。
修复 isAccountInGroup 在 groupID==nil 时的逻辑,
同时补全 scheduler_snapshot_service 和 gemini_compat_service
中的 SimpleMode 保护,确保分组隔离在所有调度路径生效。

新增 ListSchedulableUngroupedByPlatform/s 方法,
使用 Ent 的 Not(HasAccountGroups()) 谓词实现未分组账号隔离。
新增 17 个单元和端到端隔离测试,覆盖所有分支和边界条件。
2026-03-03 13:20:58 +08:00
Wesley Liddick
b7df7ce5d5 Merge pull request #726 from DaydreamCoding/feat/dual-mode-umq
feat(gateway): 双模式用户消息队列 — 串行队列 + 软性限速
2026-03-03 08:41:34 +08:00
erio
e97c376681 fix: security hardening and architectural improvements for custom menu
1. (Critical) Filter admin-only menu items from public API responses -
   both GetPublicSettings handler and GetPublicSettingsForInjection now
   exclude visibility=admin items, preventing unauthorized access to
   admin menu URLs.

2. (Medium) Validate JSON array structure in sanitizeCustomMenuItemsJSON -
   use json.Unmarshal into []json.RawMessage instead of json.Valid to
   reject non-array JSON values that would cause frontend runtime errors.

3. (Medium) Decouple router from business JSON parsing - move origin
   extraction logic from router.go to SettingService.GetFrameSrcOrigins,
   eliminating direct JSON parsing of custom_menu_items in the routing
   layer.

4. (Low) Restrict custom menu item ID charset to [a-zA-Z0-9_-] via
   regex validation, preventing route-breaking characters like / ? # or
   spaces.

5. (Low) Handle crypto/rand error in generateMenuItemID - return error
   instead of silently ignoring, preventing potential duplicate IDs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 07:05:01 +08:00
erio
bf6fe5e962 fix: custom menu security hardening and code quality improvements
- Add admin menu permission check in CustomPageView (visibility + role)
- Sanitize SVG content with DOMPurify before v-html rendering (XSS prevention)
- Decouple router.go from dto package using anonymous struct
- Consolidate duplicate parseCustomMenuItems into dto.ParseCustomMenuItems
- Enhance menu item validation (count, length, ID uniqueness limits)
- Add audit logging for purchase_subscription and custom_menu_items changes
- Update API contract test to include custom_menu_items field

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 06:23:56 +08:00
erio
067810fa98 feat: custom menu pages with iframe embedding and CSP injection
Add configurable custom menu items that appear in sidebar, each rendering
an iframe-embedded external page. Includes shared URL builder with
src_host/src_url tracking, CSP frame-src multi-origin deduplication,
admin settings UI, and i18n support.

chore: bump version to 0.1.87.19

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 06:18:20 +08:00
QTom
a9285b8a94 feat(gateway): 双模式用户消息队列 — 串行队列 + 软性限速
新增 UMQ (User Message Queue) 双模式支持:
- serialize: 账号级分布式串行锁 + RPM 自适应延迟(严格限流)
- throttle: 仅 RPM 自适应前置延迟,不阻塞并发(软性限速)

后端:
- config: 新增 Mode 字段,保留 Enabled 向后兼容
- service: 新增 UserMessageQueueService(Lua 锁/延迟算法/清理 worker)
- repository: 新增 UserMsgQueueCache(Redis Lua acquire/release/force-release)
- handler: 新增 UserMsgQueueHelper(SSE ping + 等待循环 + throttle)
- gateway: 按 mode 分支集成 serialize/throttle 逻辑
- lint: 修复 gofmt rewrite rules、errcheck 类型断言、staticcheck QF1012

前端:
- 三态选择器 UI(关闭/软性限速/串行队列)替代 toggle 开关
- BulkEdit 支持 null 语义(不修改)
- i18n 中英文文案

通过 6 轮专家评审(42 次 review)、golangci-lint、单元测试、集成测试。
2026-03-03 01:05:11 +08:00
PMExtra
0fba1901c8 fix(ci): fix backend unit test constructor arg and gofmt issues 2026-03-02 10:54:14 +08:00
PMExtra
7e02082209 feat(settings): add default subscriptions for new users
- add default subscriptions to admin settings

- auto-assign subscriptions on register and admin user creation

- add validation/tests and align settings UI with subscription selector patterns
2026-03-02 03:59:31 +08:00
QTom
8fb7d476b8 feat(admin): 代理密码可见性 + 复制代理 URL 功能
- 新增 AdminProxy / AdminProxyWithAccountCount DTO,遵循项目 Admin DTO 分层模式
- Proxy.Password 恢复 json:"-" 隐藏,ProxyFromService 不再赋值密码(纵深防御)
- 管理员接口使用 ProxyFromServiceAdmin / ProxyWithAccountCountFromServiceAdmin
- 前端代理列表新增 Auth 列:显示用户名 + 掩码密码 + 眼睛图标切换可见性
- Address 列新增复制按钮:左键复制完整 URL,右键选择格式
- 编辑模态框密码预填充 + 脏标记,避免误更新
2026-03-01 21:29:31 +08:00
erio
65459a99b6 feat(dashboard): add group usage distribution chart to usage page
Add a doughnut chart showing usage statistics broken down by group on
the admin usage records page. The chart appears alongside the existing
model distribution chart (2-column grid), with the token usage trend
chart moved to a separate full-width row below.

Changes:
- backend/pkg/usagestats: add GroupStat type
- backend/service: add GetGroupStatsWithFilters interface method and implementation
- backend/repository: implement GetGroupStatsWithFilters with LEFT JOIN groups
- backend/handler: add GetGroupStats handler with full filter support
- backend/routes: register GET /admin/dashboard/groups route
- backend/tests: add GetGroupStatsWithFilters stubs to contract/sora tests
- frontend/types: add GroupStat interface
- frontend/api: add getGroupStats API function and types
- frontend/components: add GroupDistributionChart.vue doughnut chart
- frontend/views: update UsageView layout and load group stats in parallel
- frontend/i18n: add groupDistribution, group, noGroup keys (zh + en)
2026-03-01 20:10:51 +08:00
Wesley Liddick
fd57fa4913 Merge pull request #690 from touwaeriol/pr/bulk-edit-mixed-channel-warning
feat: add mixed-channel warning for bulk account edit
2026-03-01 18:25:05 +08:00
Wesley Liddick
8c4d22b3f9 Merge pull request #685 from touwaeriol/pr/admin-create-and-redeem-docs
feat(admin): add create-and-redeem endpoint for payment integrations
2026-03-01 18:24:15 +08:00
QTom
4280aca82c feat(gateway): 添加 Claude Code 客户端最低版本检查功能
- 通过 User-Agent 识别 Claude Code 客户端并提取版本号
- 在网关层验证客户端版本是否满足管理员配置的最低要求
- 在管理后台提供版本要求配置选项(英文/中文双语)
- 实现原子缓存 + singleflight 防止并发问题和 thundering herd
- 使用 context.WithoutCancel 隔离 DB 查询,避免客户端断连影响缓存
- 双 TTL 策略:60s 正常、5s 错误恢复,保证性能与可用性
- 仅检查 Claude Code 客户端,其他客户端不受影响
- 添加完整单元测试覆盖版本提取、比对、上下文操作
2026-03-01 15:45:44 +08:00
erio
c08889b021 fix: remove unused preload/snapshot functions and fix gofmt 2026-03-01 15:22:27 +08:00
erio
73089bbfdf fix: display backend error message directly without i18n translation 2026-03-01 14:49:25 +08:00
erio
3a04552f98 fix: use i18n for mixed-channel warning messages and improve bulk pre-check
- BulkUpdate handler: add structured details to 409 response
- BulkUpdateAccounts: simplify to global pre-check before any DB write;
  remove per-account snapshot tracking which is no longer needed
- MixedChannelError.Error(): restore English message for API compatibility
- BulkEditAccountModal: use t() with details for both pre-check and 409
  fallback paths instead of displaying raw backend strings
- Update test to verify pre-check blocks on existing group conflicts
2026-03-01 14:39:07 +08:00
erio
947800b95f fix: bulk edit mixed channel warning not showing confirmation dialog
The response interceptor in client.ts transforms errors into plain
objects {status, code, message}, but catch blocks were checking
error.response?.status (AxiosError format) which never matched.

- Add error field passthrough in client.ts interceptor
- Refactor BulkEditAccountModal to use pre-check API (checkMixedChannelRisk)
  before submit, matching the single edit flow
- Fix EditAccountModal catch blocks to use interceptor error format
- Add bulk-update mixed channel unit tests
2026-03-01 14:25:16 +08:00
erio
7aa4c083a9 feat: bulk update accounts pre-check mixed channel risk with confirm dialog
- Move mixed channel check before any DB writes in BulkUpdateAccounts
- Return 409 from BulkUpdate handler for MixedChannelError
- Add ConfirmDialog to BulkEditAccountModal for mixed channel warning
- Update mixed channel warning message to Chinese
2026-03-01 14:25:02 +08:00
erio
39ca192c41 feat(admin): add create-and-redeem API and payment integration docs 2026-03-01 00:42:21 +08:00
Wesley Liddick
493bd188d5 Merge pull request #680 from alfadb/fix/ops-normalize-nil-error-type
fix(ops): validate error_type against known whitelist before classification
2026-02-28 22:39:32 +08:00
Wesley Liddick
9fd95df5cf Merge pull request #679 from DaydreamCoding/feat/account-rpm-limit
feat: 添加账号级别 RPM(每分钟请求数)限流功能
2026-02-28 22:37:10 +08:00
QTom
212cbbd3a2 fix: add missing rpmCache nil arg in sora_client_handler_test 2026-02-28 21:30:59 +08:00
QTom
6f9e690345 test(sora): 补充测试 stub 中缺失的 AddGroupToAllowedGroups 方法
feat/admin-apikey-group-update 分支给 UserRepository 接口新增了
AddGroupToAllowedGroups 方法,需要在测试 stub 中补充实现以通过编译。
- sora_client_handler_test.go: stubUserRepoForHandler
- sora_generation_service_test.go: stubUserRepoForQuota
2026-02-28 20:55:31 +08:00
QTom
115d06edf0 fix: 修复 gofmt 格式问题 2026-02-28 20:38:35 +08:00
QTom
e135435ce2 fix: sync test constructor calls with new rpmCache parameter
Add missing nil argument for rpmCache to NewAccountHandler (5 sites)
and NewGatewayService (2 sites) after RPM feature expanded their
signatures.
2026-02-28 20:38:35 +08:00
QTom
cd09adc3cc fix: add sanitizeExtraBaseRPM to BatchCreate handler
Ensures base_rpm validation (clamp 0-10000) is consistent across
all four account mutation paths: Create, Update, BulkUpdate, BatchCreate.
2026-02-28 20:38:06 +08:00