Commit Graph

1812 Commits

Author SHA1 Message Date
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
Wesley Liddick
c221774c51 Merge pull request #693 from salmanmkc/upgrade-github-actions-node24
Upgrade GitHub Actions for Node 24 compatibility
2026-03-01 18:23:50 +08:00
erio
23686b1391 refactor(docs): move integration doc to docs/ and add download link in settings
- Move ADMIN_PAYMENT_INTEGRATION_API.md → docs/ADMIN_PAYMENT_INTEGRATION_API.md
- Update README.md reference path
- Add payment integration doc download link in admin settings UI (Purchase section)
- Add i18n keys: integrationDoc / integrationDocHint (zh + en)
2026-03-01 18:08:42 +08:00
Wesley Liddick
0fffba5423 Merge pull request #692 from DaydreamCoding/feat/CC_UA
feat(gateway): 添加 Claude Code 客户端最低版本检查功能
2026-03-01 18:03:44 +08:00
Salman Muin Kayser Chishti
f6f8695a8e Upgrade GitHub Actions for Node 24 compatibility
Signed-off-by: Salman Muin Kayser Chishti <13schishti@gmail.com>
2026-03-01 09:10:02 +00:00
QTom
b2141a96e2 fix(ci): 修复 golangci-lint 和 API 合约测试失败
- 修复 errcheck: singleflight 返回值类型断言添加 ok 检查
- 修复 gofmt: 格式化 setting_service.go 和 claude_code_validator_test.go
- 修复 TestAPIContracts: 在 GET /admin/settings 期望中添加 min_claude_code_version 字段
2026-03-01 16:39:21 +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
57ebe382f9 fix: remove dead code in BulkUpdateAccounts group binding loop 2026-03-01 15:03:50 +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
b67bf2227e fix: update mixed channel warning message 2026-03-01 14:25:16 +08:00
erio
dde3b59e7b fix: handle mixed channel warning for multi-platform bulk edit
Previously, preCheckMixedChannelRisk() skipped when selectedPlatforms
had more than one entry, and the catch block in submitBulkUpdate had no
409 handling — so multi-platform conflicts just showed a generic error.

- Rename canPreCheck(): only call pre-check API for single-platform
  antigravity/anthropic selections (API requires a single platform param)
- Pass `built` into preCheckMixedChannelRisk() so pendingUpdatesForConfirm
  is set before returning false
- submitBulkUpdate: add 409 mixed_channel_warning catch as fallback for
  multi-platform case, saving baseUpdates for retry
- Remove needsMixedChannelCheck() gate on confirm_mixed_channel_risk flag;
  use mixedChannelConfirmed alone so multi-platform retry also works
2026-03-01 14:25:16 +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
fcc77d1383 refactor(purchase): use URL/searchParams only for purchase query merge 2026-03-01 02:04:19 +08:00
erio
997cd1e332 docs+ui: add bilingual payment integration doc and rename purchase entry to recharge/subscription 2026-03-01 01:53:14 +08:00
erio
2e88e23002 feat(frontend): append purchase query params and make integration doc bilingual 2026-03-01 00:57:26 +08:00
erio
39ca192c41 feat(admin): add create-and-redeem API and payment integration docs 2026-03-01 00:42:21 +08:00
shaw
f7fa71bc28 fix: 将 README 中 Codex WS 配置迁移至使用密钥弹窗
- 移除 README.md / README_CN.md 中的 Codex CLI WebSocket v2 配置示例
- UseKeyModal OpenAI 分组新增 "Codex CLI (WebSocket)" tab,区分普通模式与 WS 模式
- 普通模式 config.toml 不含 WebSocket 字段,WS 模式包含 supports_websockets 和 features 配置
- 所有配置统一使用 sub2api 作为 model_provider 名称
2026-02-28 23:35:31 +08:00
shaw
fbfbb26fd2 fix(ci): 将 gosec 集成到 golangci-lint 解决安全扫描超时
standalone gosec 扫描 24 万行 Go 代码在 CI 中持续超时,
将其作为 golangci-lint 的内置 linter 运行,复用 AST 解析和缓存大幅提速。

- 在 .golangci.yml 中启用 gosec 并迁移原有排除规则
- golangci-lint timeout 从 5m 提升到 30m
- 从 security-scan.yml 移除 standalone gosec 步骤
- 删除不再需要的 .gosec.json 配置文件
2026-02-28 23:12:38 +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
shaw
54de3bf27a fix(ci): gosec 跳过自动生成的代码文件避免扫描超时
为 gosec 添加 -exclude-generated 标志,跳过带有
"// Code generated" 注释的文件(如 wire_gen.go),
防止安全扫描因分析自动生成代码而超时。
2026-02-28 22:30:53 +08:00
Wesley Liddick
4587c3e53e Merge pull request #670 from DaydreamCoding/feat/admin-apikey-group-update
feat(admin): 添加管理员直接修改用户 API Key 分组的功能
2026-02-28 22:20:29 +08:00
shaw
be18bc6fc3 chore: 恢复数据库迁移文件060和修正版本号 2026-02-28 22:02:01 +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
QTom
2491e9b5ad fix: round-3 review fixes for RPM limiting
- 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
2026-02-28 20:38:06 +08:00
QTom
e63c83955a fix: address deep code review issues for RPM limiting
- 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
2026-02-28 20:38:06 +08:00
QTom
4b72aa33f3 fix: add enableRpmLimit to hasAnyFieldEnabled check in BulkEditModal
Without this, submitting a bulk edit with only RPM changes would be
rejected as "no fields selected".
2026-02-28 20:37:37 +08:00
QTom
ff9683b0fc fix: move RPM prefetch before routing segment in legacy/mixed paths
Ensures isAccountSchedulableForRPM calls within the routing segment
hit the prefetch cache instead of querying Redis individually.
2026-02-28 20:37:37 +08:00
QTom
607237571f fix: address code review issues for RPM limiting feature
- 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
2026-02-28 20:37:37 +08:00
QTom
28ca7df297 feat: add RPM display to AccountCapacityCell 2026-02-28 20:37:10 +08:00
QTom
856c955386 feat: add RPM config to CreateAccountModal 2026-02-28 20:37:10 +08:00
QTom
e1c9016d90 feat: add RPM config to EditAccountModal 2026-02-28 20:37:10 +08:00
QTom
953c5036bf feat: add RPM types and i18n translations 2026-02-28 20:37:10 +08:00
QTom
37fa980565 feat: flatten RPM config fields in Account DTO 2026-02-28 20:37:10 +08:00
QTom
f648b8e026 feat: increment RPM counter before request forwarding 2026-02-28 20:37:10 +08:00
QTom
678c3ae132 feat: integrate RPM scheduling checks into account selection flow 2026-02-28 20:37:10 +08:00
QTom
c1c31ed9b2 feat: wire RPMCache into GatewayService and AccountHandler 2026-02-28 20:35:38 +08:00
QTom
777be05348 feat: add RPMCache interface and Redis implementation with Lua scripts 2026-02-28 20:34:22 +08:00
QTom
0bb3e4a98c feat: add RPM getter methods and schedulability check to Account model 2026-02-28 20:34:22 +08:00
QTom
9a91815b94 feat(admin): 完整实现管理员修改用户 API Key 分组的功能
## 核心功能
- 添加 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 规范

## 国际化支持
- 中英文提示信息完整
- 自动授权成功/失败提示
2026-02-28 20:18:14 +08:00
QTom
000e621eb6 feat(admin): 添加管理员直接修改用户 API Key 分组的功能
- 新增 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 全部通过
2026-02-28 20:18:14 +08:00
alfadb
093d7ba858 fix(ops): use normalized error type for all classification functions
- 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.
2026-02-28 19:28:08 +08:00