1. 02 Mar, 2026 4 commits
    • erio's avatar
      fix: security hardening and architectural improvements for custom menu · e97c3766
      erio authored
      
      
      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: default avatarClaude Opus 4.6 <noreply@anthropic.com>
      e97c3766
    • erio's avatar
      fix: custom menu security hardening and code quality improvements · bf6fe5e9
      erio authored
      
      
      - 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: default avatarClaude Opus 4.6 <noreply@anthropic.com>
      bf6fe5e9
    • erio's avatar
      feat: custom menu pages with iframe embedding and CSP injection · 067810fa
      erio authored
      
      
      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: default avatarClaude Opus 4.6 <noreply@anthropic.com>
      067810fa
    • PMExtra's avatar
  2. 01 Mar, 2026 9 commits
    • PMExtra's avatar
      feat(settings): add default subscriptions for new users · 7e020822
      PMExtra authored
      - 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
      7e020822
    • QTom's avatar
      feat(admin): 代理密码可见性 + 复制代理 URL 功能 · 8fb7d476
      QTom authored
      - 新增 AdminProxy / AdminProxyWithAccountCount DTO,遵循项目 Admin DTO 分层模式
      - Proxy.Password 恢复 json:"-" 隐藏,ProxyFromService 不再赋值密码(纵深防御)
      - 管理员接口使用 ProxyFromServiceAdmin / ProxyWithAccountCountFromServiceAdmin
      - 前端代理列表新增 Auth 列:显示用户名 + 掩码密码 + 眼睛图标切换可见性
      - Address 列新增复制按钮:左键复制完整 URL,右键选择格式
      - 编辑模态框密码预填充 + 脏标记,避免误更新
      8fb7d476
    • erio's avatar
      feat(dashboard): add group usage distribution chart to usage page · 65459a99
      erio authored
      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)
      65459a99
    • QTom's avatar
      feat(gateway): 添加 Claude Code 客户端最低版本检查功能 · 4280aca8
      QTom authored
      - 通过 User-Agent 识别 Claude Code 客户端并提取版本号
      - 在网关层验证客户端版本是否满足管理员配置的最低要求
      - 在管理后台提供版本要求配置选项(英文/中文双语)
      - 实现原子缓存 + singleflight 防止并发问题和 thundering herd
      - 使用 context.WithoutCancel 隔离 DB 查询,避免客户端断连影响缓存
      - 双 TTL 策略:60s 正常、5s 错误恢复,保证性能与可用性
      - 仅检查 Claude Code 客户端,其他客户端不受影响
      - 添加完整单元测试覆盖版本提取、比对、上下文操作
      4280aca8
    • erio's avatar
      c08889b0
    • erio's avatar
    • erio's avatar
      fix: use i18n for mixed-channel warning messages and improve bulk pre-check · 3a04552f
      erio authored
      - 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
      3a04552f
    • erio's avatar
      fix: bulk edit mixed channel warning not showing confirmation dialog · 947800b9
      erio authored
      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
      947800b9
    • erio's avatar
      feat: bulk update accounts pre-check mixed channel risk with confirm dialog · 7aa4c083
      erio authored
      - 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
      7aa4c083
  3. 28 Feb, 2026 12 commits
    • erio's avatar
    • QTom's avatar
      fix: 修复 gofmt 格式问题 · 115d06ed
      QTom authored
      115d06ed
    • QTom's avatar
      fix: sync test constructor calls with new rpmCache parameter · e135435c
      QTom authored
      Add missing nil argument for rpmCache to NewAccountHandler (5 sites)
      and NewGatewayService (2 sites) after RPM feature expanded their
      signatures.
      e135435c
    • QTom's avatar
      fix: add sanitizeExtraBaseRPM to BatchCreate handler · cd09adc3
      QTom authored
      Ensures base_rpm validation (clamp 0-10000) is consistent across
      all four account mutation paths: Create, Update, BulkUpdate, BatchCreate.
      cd09adc3
    • QTom's avatar
      fix: round-3 review fixes for RPM limiting · 2491e9b5
      QTom authored
      - Add sanitizeExtraBaseRPM to BulkUpdate handler (was missing)
      - Add WindowCost scheduling checks to legacy non-sticky selection
        paths (4 sites), matching existing sticky + load-aware coverage
      - Export ParseExtraInt from service package, remove duplicate
        parseExtraIntForValidation from admin handler
      2491e9b5
    • QTom's avatar
      fix: address deep code review issues for RPM limiting · e63c8395
      QTom authored
      - Move IncrementRPM after Forward success to prevent phantom RPM
        consumption during account switch retries
      - Add base_rpm input sanitization (clamp to 0-10000) in Create/Update
      - Add WindowCost scheduling checks to legacy path sticky sessions
        (4 check sites + 4 prefetch sites), fixing pre-existing gap
      - Clean up rpm_strategy/rpm_sticky_buffer when disabling RPM in
        BulkEditModal (JSONB merge cannot delete keys, use empty values)
      - Add json.Number test cases to TestGetBaseRPM/TestGetRPMStickyBuffer
      - Document TOCTOU race as accepted soft-limit design trade-off
      e63c8395
    • QTom's avatar
      fix: address code review issues for RPM limiting feature · 60723757
      QTom authored
      - Use TxPipeline (MULTI/EXEC) instead of Pipeline for atomic INCR+EXPIRE
      - Filter negative values in GetBaseRPM(), update test expectation
      - Add RPM batch query (GetRPMBatch) to account List API
      - Add warn logs for RPM increment failures in gateway handler
      - Reset enableRpmLimit on BulkEditAccountModal close
      - Use union type 'tiered' | 'sticky_exempt' for rpmStrategy refs
      - Add design decision comments for rdb.Time() RTT trade-off
      60723757
    • QTom's avatar
      c1c31ed9
    • QTom's avatar
      feat(admin): 完整实现管理员修改用户 API Key 分组的功能 · 9a91815b
      QTom authored
      ## 核心功能
      - 添加 AdminUpdateAPIKeyGroupID 服务方法,支持绑定/解绑/保持不变三态语义
      - 实现 UserRepository.AddGroupToAllowedGroups 接口,自动同步专属分组权限
      - 添加 HTTP PUT /api-keys/:id handler 端点,支持管理员直接修改 API Key 分组
      
      ## 事务一致性
      - 使用 ent Tx 保证专属分组绑定时「添加权限」和「更新 Key」的原子性
      - Repository 方法支持 clientFromContext,兼容事务内调用
      - 事务失败时自动回滚,避免权限孤立
      
      ## 业务逻辑
      - 订阅类型分组阻断,需通过订阅管理流程
      - 非活跃分组拒绝绑定
      - 负 ID 和非法 ID 验证
      - 自动授权响应,告知管理员成功授权的分组
      
      ## 代码质量
      - 16 个单元测试覆盖所有业务路径和边界用例
      - 7 个 handler 集成测试覆盖 HTTP 层
      - GroupRepo stub 返回克隆副本,防止测试间数据泄漏
      - API 类型安全修复(PaginatedResponse<ApiKey>)
      - 前端 ref 回调类型对齐 Vue 规范
      
      ## 国际化支持
      - 中英文提示信息完整
      - 自动授权成功/失败提示
      9a91815b
    • QTom's avatar
      feat(admin): 添加管理员直接修改用户 API Key 分组的功能 · 000e621e
      QTom authored
      - 新增 PUT /api/v1/admin/api-keys/:id 端点,允许管理员修改任意用户 API Key 的分组绑定
      - 跳过用户级权限校验但保留分组有效性验证,修改后触发认证缓存失效
      - Service 层支持三态语义:nil=不修改,0=解绑,>0=绑定,<0=拒绝
      - 指针值拷贝保证安全隔离,负数 groupID 返回 400 INVALID_GROUP_ID
      - 前端 UserApiKeysModal 新增可点击的分组选择下拉框,支持多 Key 并发更新
      - 下拉支持视口翻转和滚动关闭,按钮有 disabled 和加载状态
      - 覆盖:后端 20 个单元测试 (Service 11 + Handler 9) + 前端 16 个 E2E 测试
      - golangci-lint 0 issues, make test-unit 全部通过
      000e621e
    • yangjianbo's avatar
      1d1fc019
    • yangjianbo's avatar
      feat(sync): full code sync from release · bb664d9b
      yangjianbo authored
      bb664d9b
  4. 26 Feb, 2026 1 commit
  5. 25 Feb, 2026 1 commit
  6. 24 Feb, 2026 2 commits
    • cagedbird043's avatar
    • erio's avatar
      feat: add mixed-channel precheck API for account-group binding · aaac1aac
      erio authored
      Add a dedicated CheckMixedChannel endpoint that allows the frontend
      to pre-validate mixed channel risk before submitting create/update
      requests. This improves UX by showing warnings earlier in the flow
      instead of only after form submission.
      
      Backend changes:
      - Add CheckMixedChannelRequest struct and CheckMixedChannel handler
      - Register POST /check-mixed-channel route
      - Expose CheckMixedChannelRisk as public method on AdminService
      - Simplify Create/Update 409 responses (remove details/require_confirmation)
      - Add comprehensive handler tests and stub methods
      
      Frontend changes:
      - Add checkMixedChannelRisk API function and TypeScript types
      - Refactor CreateAccountModal to precheck before step transition and submission
      - Refactor EditAccountModal to precheck before update submission
      - Replace pendingPayload pattern with action-based dialog flow
      aaac1aac
  7. 23 Feb, 2026 1 commit
  8. 22 Feb, 2026 1 commit
  9. 21 Feb, 2026 1 commit
  10. 19 Feb, 2026 3 commits
  11. 14 Feb, 2026 2 commits
    • yangjianbo's avatar
      feat(accounts): 自动刷新改为ETag增量同步并优化单账号更新体验 · 06b0f62e
      yangjianbo authored
      - 前端自动刷新改为 ETag/304 增量合并,减少全量重刷
      
      - 单账号更新后增加静默窗口,避免刚更新即被自动刷新覆盖
      
      - 列表筛选移除时改为待同步提示,不再立即触发全量补页
      
      - 后端账号列表支持 If-None-Match,命中返回 304
      
      - 单账号接口统一补充运行时容量字段并暴露 ETag 头
      06b0f62e
    • yangjianbo's avatar
      fix(accounts): 账号管理改为单行增量更新并避免全量刷新 · 9cafa46d
      yangjianbo authored
      
      
      - 将编辑与重新授权成功事件改为回传更新后的账号对象
      - 在账号列表页按 id 就地补丁更新单行数据并保留运行时容量字段
      - 单账号操作(刷新凭证/清错/清限流/临时不可调度重置)改为单行更新
      - 后端增强 clear-rate-limit 接口,返回更新后的账号对象
      - 同步前端 clearRateLimit API 类型定义
      Co-Authored-By: default avatarClaude Opus 4.6 <noreply@anthropic.com>
      9cafa46d
  12. 12 Feb, 2026 3 commits