1. 02 Mar, 2026 5 commits
  2. 01 Mar, 2026 14 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(identity): 指纹缓存 TTL 懒续期机制 · d869ac95
      QTom authored
      - TTL 改为 7 天,配合 24 小时自动续期保持活跃账号永不过期
      - 版本升级时采用合并语义,仅更新请求中实际存在的字段
      - 添加产品名验证防止浏览器 UA 误判为更新版本
      d869ac95
    • 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
    • Gemini Wen's avatar
      c6e26c5a
    • QTom's avatar
      fix(ci): 修复 golangci-lint 和 API 合约测试失败 · b2141a96
      QTom authored
      - 修复 errcheck: singleflight 返回值类型断言添加 ok 检查
      - 修复 gofmt: 格式化 setting_service.go 和 claude_code_validator_test.go
      - 修复 TestAPIContracts: 在 GET /admin/settings 期望中添加 min_claude_code_version 字段
      b2141a96
    • 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
      57ebe382
    • 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: update mixed channel warning message · b67bf222
      erio authored
      b67bf222
    • 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 21 commits
    • erio's avatar
    • shaw's avatar
      fix(ci): 将 gosec 集成到 golangci-lint 解决安全扫描超时 · fbfbb26f
      shaw authored
      standalone gosec 扫描 24 万行 Go 代码在 CI 中持续超时,
      将其作为 golangci-lint 的内置 linter 运行,复用 AST 解析和缓存大幅提速。
      
      - 在 .golangci.yml 中启用 gosec 并迁移原有排除规则
      - golangci-lint timeout 从 5m 提升到 30m
      - 从 security-scan.yml 移除 standalone gosec 步骤
      - 删除不再需要的 .gosec.json 配置文件
      fbfbb26f
    • shaw's avatar
      be18bc6f
    • QTom's avatar
      212cbbd3
    • QTom's avatar
      test(sora): 补充测试 stub 中缺失的 AddGroupToAllowedGroups 方法 · 6f9e6903
      QTom authored
      feat/admin-apikey-group-update 分支给 UserRepository 接口新增了
      AddGroupToAllowedGroups 方法,需要在测试 stub 中补充实现以通过编译。
      - sora_client_handler_test.go: stubUserRepoForHandler
      - sora_generation_service_test.go: stubUserRepoForQuota
      6f9e6903
    • 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: move RPM prefetch before routing segment in legacy/mixed paths · ff9683b0
      QTom authored
      Ensures isAccountSchedulableForRPM calls within the routing segment
      hit the prefetch cache instead of querying Redis individually.
      ff9683b0
    • 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
      feat: flatten RPM config fields in Account DTO · 37fa9805
      QTom authored
      37fa9805
    • QTom's avatar
      f648b8e0
    • QTom's avatar
      678c3ae1
    • QTom's avatar
      c1c31ed9
    • QTom's avatar
    • QTom's avatar
    • 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
    • alfadb's avatar
      fix(ops): use normalized error type for all classification functions · 093d7ba8
      alfadb authored
      - Compute normalizedType once and pass to classifyOpsPhase,
        classifyOpsSeverity, classifyOpsIsBusinessLimited, classifyOpsIsRetryable
        instead of raw parsed.ErrorType
      - Add test case verifying known type takes precedence over conflicting code
      
      Addresses Copilot review feedback on PR #680.
      093d7ba8