1. 08 Feb, 2026 1 commit
    • yangjianbo's avatar
      test: 完善自动化测试体系(7个模块,73个任务) · bb5a5dd6
      yangjianbo authored
      
      
      系统性地修复、补充和强化项目的自动化测试能力:
      
      1. 测试基础设施修复
         - 修复 stubConcurrencyCache 缺失方法和构造函数参数不匹配
         - 创建 testutil 共享包(stubs.go, fixtures.go, httptest.go)
         - 为所有 Stub 添加编译期接口断言
      
      2. 中间件测试补充
         - 新增 JWT 认证中间件测试(有效/过期/篡改/缺失 Token)
         - 补充 rate_limiter 和 recovery 中间件测试场景
      
      3. 网关核心路径测试
         - 新增账户选择、等待队列、流式响应、并发控制、计费、Claude Code 检测测试
         - 覆盖负载均衡、粘性会话、SSE 转发、槽位管理等关键逻辑
      
      4. 前端测试体系(11个新测试文件,163个测试用例)
         - Pinia stores: auth, app, subscriptions
         - API client: 请求拦截器、响应拦截器、401 刷新
         - Router guards: 认证重定向、管理员权限、简易模式限制
         - Composables: useForm, useTableLoader, useClipboard
         - Components: LoginForm, ApiKeyCreate, Dashboard
      
      5. CI/CD 流水线重构
         - 重构 backend-ci.yml 为统一的 ci.yml
         - 前后端 4 个并行 Job + Postgres/Redis services
         - Race 检测、覆盖率收集与门禁、Docker 构建验证
      
      6. E2E 自动化测试
         - e2e-test.sh 自动化脚本(Docker 启动→健康检查→测试→清理)
         - 用户注册→登录→API Key→网关调用完整链路测试
         - Mock 模式和 API Key 脱敏支持
      
      7. 修复预存问题
         - tlsfingerprint dialer_test.go 缺失 build tag 导致集成测试编译冲突
      Co-Authored-By: default avatarClaude Opus 4.6 <noreply@anthropic.com>
      bb5a5dd6
  2. 07 Feb, 2026 32 commits
    • yangjianbo's avatar
      perf(日志): 降噪优化,将常规成功日志降级为 Debug 级别 · 53e1c8b2
      yangjianbo authored
      
      
      - GIN Logger 中间件跳过 /health 和 /setup/status 的请求日志
      - UsageCleanup 空闲轮询(no_task)日志降级为 slog.Debug
      - Scheduler 常规 rebuild ok 日志降级为 slog.Debug
      - DashboardAggregation 常规聚合完成日志降级为 slog.Debug
      - TokenRefresh 无刷新活动时周期日志降级为 slog.Debug
      
      生产环境(Info 级别)下自动静默,debug 模式下仍可见。
      错误、警告类日志保持原有级别不变。
      Co-Authored-By: default avatarClaude Opus 4.6 <noreply@anthropic.com>
      53e1c8b2
    • yangjianbo's avatar
      test: 为代码审核修复添加详细单元测试(7个测试文件,50+测试用例) · 00caf0bc
      yangjianbo authored
      
      
      新增测试文件:
      - cors_test.go: CORS 条件化头部测试(12个测试,覆盖白名单/黑名单/通配符/凭证/多源/Vary)
      - gateway_helper_backoff_test.go: nextBackoff 退避测试(6个测试+基准,验证指数增长/边界/抖动/收敛)
      - billing_cache_jitter_test.go: jitteredTTL 抖动测试(5个测试+基准,验证范围/上界/方差/均值)
      - subscription_calculate_progress_test.go: calculateProgress 纯函数测试(9个测试,覆盖日/周/月限额/超限截断/过期)
      - openai_gateway_handler_test.go: SSE JSON 转义测试(7个子用例,验证双引号/反斜杠/换行符安全)
      
      更新测试文件:
      - response_transformer_test.go: 增强 generateRandomID 测试(7个测试,含并发/字符集/降级计数器)
      - security_headers_test.go: 适配 GenerateNonce 新签名
      - api_key_auth_test.go: 适配 NewSubscriptionService 新参数
      Co-Authored-By: default avatarClaude Opus 4.6 <noreply@anthropic.com>
      00caf0bc
    • yangjianbo's avatar
      fix: 修复代码审核发现的10个问题(P0安全+P1数据一致性+P2性能优化) · 9634494b
      yangjianbo authored
      
      
      P0: OpenAI SSE 错误消息 JSON 注入 — 使用 json.Marshal 替代 fmt.Sprintf
      P1: subscription 续期包裹 Ent 事务确保原子性
      P1: CSP nonce 生成处理 crypto/rand 错误,失败降级为 unsafe-inline
      P1: singleflight 透传数据库真实错误,不再吞没为 not found
      P1: GetUserSubscriptionsWithProgress 提取 calculateProgress 消除 N+1
      P2: billing_cache/gateway_helper 迁移到 math/rand/v2 消除全局锁争用
      P2: generateRandomID 降级分支增加原子计数器防碰撞
      P2: CORS 非白名单 origin 不再设置 Allow-Headers/Methods/Max-Age
      P2: Turnstile 验证移除 VerifyCode 空值跳过条件防绕过
      P2: Redis Cluster Lua 脚本空 KEYS 添加兼容性警告注释
      Co-Authored-By: default avatarClaude Opus 4.6 <noreply@anthropic.com>
      9634494b
    • yangjianbo's avatar
      fix: 修复批量更新凭证明细与缓存TTL抖动 · 4a20a2a8
      yangjianbo authored
      - BatchUpdateCredentials 返回 success/failed/results 及 success_ids/failed_ids
      
      - billing jitteredTTL 改为只减不增,确保TTL不超上界
      
      - crypto/rand 失败时随机ID降级避免 panic
      
      - OpenAI SelectAccount 失败日志去重并补充字段
      
      - 修复两处类型断言以通过 errcheck
      4a20a2a8
    • yangjianbo's avatar
      fix: 修复函数签名变更后的调用参数不匹配 · 836ba14b
      yangjianbo authored
      
      
      - handleUpstreamError 补齐新增的三个参数 (0, "", false)
      - handleStreamingResponse 移除已删除的 nil 参数
      Co-Authored-By: default avatarClaude Opus 4.6 <noreply@anthropic.com>
      836ba14b
    • yangjianbo's avatar
      fix(audit): 第二批审计修复 — P0 生产 Bug、安全加固、性能优化、缓存一致性、代码质量 · 2588fa6a
      yangjianbo authored
      
      
      基于 backend-code-audit 审计报告,修复剩余 P0/P1/P2 共 34 项问题:
      
      P0 生产 Bug:
      - 修复 time.Since(time.Now()) 计时逻辑错误 (P0-03)
      - generateRandomID 改用 crypto/rand 替代固定索引 (P0-04)
      - IncrementQuotaUsed 重写为 Ent 原子操作消除 TOCTOU 竞态 (P0-05)
      
      安全加固:
      - gateway/openai handler 错误响应替换为泛化消息,防止内部信息泄露 (P1-14)
      - usage_log_repo dateFormat 参数改用白名单映射,防止 SQL 注入 (P1-16)
      - 默认配置安全加固:sslmode=prefer、response_headers=true、mode=release (P1-18/19, P2-15)
      
      性能优化:
      - gateway handler 循环内 defer 替换为显式 releaseWait 闭包 (P1-02)
      - group_repo/promo_code_repo Count 前 Clone 查询避免状态污染 (P1-03)
      - usage_log_repo 四个查询添加 LIMIT 10000 防止 OOM (P1-07)
      - GetBatchUsageStats 添加时间范围参数,默认最近 30 天 (P1-10)
      - ip.go CIDR 预编译为包级变量 (P1-11)
      - BatchUpdateCredentials 重构为先验证后更新 (P1-13)
      
      缓存一致性:
      - billing_cache 添加 jitteredTTL 防止缓存雪崩 (P2-10)
      - DeductUserBalance/UpdateSubscriptionUsage 错误传播修复 (P2-12)
      - UserService.UpdateBalance 成功后异步失效 billingCache (P2-13)
      
      代码质量:
      - search 截断改为按 rune 处理,支持多字节字符 (P2-01)
      - TLS Handshake 改为 HandshakeContext 支持 context 取消 (P2-07)
      - CORS 预检添加 Access-Control-Max-Age: 86400 (P2-16)
      
      测试覆盖:
      - 新增 user_service_test.go(UpdateBalance 缓存失效 6 个用例)
      - 新增 batch_update_credentials_test.go(fail-fast + 类型验证 7 个用例)
      - 新增 response_transformer_test.go、ip_test.go、usage_log_repo_unit_test.go、search_truncate_test.go
      - 集成测试:IncrementQuotaUsed 并发测试、billing_cache 错误传播测试
      - config_test.go 补充 server.mode/sslmode 默认值断言
      Co-Authored-By: default avatarClaude Opus 4.6 <noreply@anthropic.com>
      2588fa6a
    • shaw's avatar
      6aaa4aee
    • yangjianbo's avatar
      fix(oauth): SessionStore.Stop() 添加 sync.Once 防重入保护 (P1-05) · f6ca7019
      yangjianbo authored
      
      
      oauth 和 openai 包的 SessionStore.Stop() 直接调用 close(stopCh),
      重复调用会导致 panic。使用 sync.Once 包裹确保幂等安全。
      
      新增单元测试覆盖连续调用和 50 goroutine 并发调用场景。
      Co-Authored-By: default avatarClaude Opus 4.6 <noreply@anthropic.com>
      f6ca7019
    • yangjianbo's avatar
    • yangjianbo's avatar
      fix(security): 修复密码重置链接 Host Header 注入漏洞 (P0-07) · e75d3e35
      yangjianbo authored
      
      
      ForgotPassword 原来从 c.Request.Host 构建重置链接基础 URL,攻击者
      可伪造 Host 头将重置链接指向恶意域名窃取 token。
      
      修复方案:
      - ServerConfig 新增 frontend_url 配置项
      - auth_handler 改为从配置读取前端 URL,未配置时拒绝请求
      - Validate() 校验 frontend_url 必须为绝对 HTTP(S) URL
      - 新增 TestValidateServerFrontendURL 单元测试
      - config.example.yaml 添加配置说明
      Co-Authored-By: default avatarClaude Opus 4.6 <noreply@anthropic.com>
      e75d3e35
    • shaw's avatar
      fix(gateway): harden digest logging and align antigravity ops · 1439eb39
      shaw authored
      - avoid panic by using safe UUID prefix truncation in Gemini digest fallback logs\n- remove unconditional Antigravity 429 full-body debug logs and honor log truncation config\n- align Antigravity quick preset mappings to opus 4.6-thinking targets only\n- restore scope rate-limit aggregation/output in ops availability stats
      1439eb39
    • yangjianbo's avatar
      perf(service): 优化 model 替换函数,用 gjson/sjson 替代全量 JSON 序列化 · 8226a4ce
      yangjianbo authored
      
      
      SSE 热路径中 replaceModelInSSELine 和 replaceModelInResponseBody 原来
      使用 json.Unmarshal/Marshal 对每个事件做全量反序列化再序列化,现改为
      gjson.Get/sjson.Set 精确字段操作,消除 O(n) 中间 map 分配,保持 JSON
      字段顺序不变。涉及 OpenAIGatewayService 和 GatewayService 两个服务。
      
      新增 23 个单元测试覆盖:顶层/嵌套 model 替换、不匹配跳过、空行/[DONE]/
      非法 JSON 等边界情况。
      
      Fixes: P1-08
      Co-Authored-By: default avatarClaude Opus 4.6 <noreply@anthropic.com>
      8226a4ce
    • yangjianbo's avatar
      fix(middleware): 管理员JWT增加TokenVersion校验 · 65c0d8b5
      yangjianbo authored
      管理员改密后旧JWT会被拒绝,并补充单元测试覆盖。
      65c0d8b5
    • yangjianbo's avatar
      a9e256ce
    • erio's avatar
    • erio's avatar
      fix(antigravity): fetch default mapping from API and sync Redis on rate limit · 2656320d
      erio authored
      1. Frontend: replace hardcoded antigravityDefaultMappings with async
         fetch from GET /admin/accounts/antigravity/default-model-mapping,
         eliminating the duplicate data source that caused frontend/backend
         mapping inconsistency.
      
      2. Backend: convert handleSmartRetry and antigravityRetryLoop from
         standalone functions to AntigravityGatewayService methods, enabling
         Redis cache sync (updateAccountModelRateLimitInCache) after both
         rate-limit write paths — long-delay branch and retry-exhausted branch.
      2656320d
    • erio's avatar
      style: fix gofmt formatting in gateway_service.go · b4f6c4f9
      erio authored
      Remove extra blank line that caused golangci-lint gofmt check to fail.
      b4f6c4f9
    • yangjianbo's avatar
      perf(middleware): 优化订阅模式认证中间件,5次串行调用降至2步同步+1步异步 · 0e514ed8
      yangjianbo authored
      
      
      - 为 GetActiveSubscription 添加 ristretto L1 缓存 + singleflight 防击穿
      - 合并 ValidateSubscription + CheckUsageLimits 为纯内存 ValidateAndCheckLimits
      - 窗口维护操作(激活/重置)异步化,不再阻塞首字节
      - 缓存返回浅拷贝,避免并发 data race 和缓存污染
      - 所有管理操作(分配/续期/撤销/扩展/窗口重置)同步失效 L1 缓存
      - 新增 SubscriptionCacheConfig 可配置 L1 缓存大小/TTL/抖动
      Co-Authored-By: default avatarClaude Opus 4.6 <noreply@anthropic.com>
      0e514ed8
    • erio's avatar
    • erio's avatar
      test(antigravity): add missing unit tests for upstream and custom model_mapping · 386126b1
      erio authored
      - Add GetAccessToken upstream branch tests (success/failure/empty/nil)
      - Add mapAntigravityModel wildcard-target-equals-request edge case tests
      - Add upstream account smart retry test case
      - Add GeminiMessagesCompatService custom model_mapping and empty model tests
      386126b1
    • erio's avatar
      fix(antigravity): support upstream accounts and custom model_mapping in scheduling · de092728
      erio authored
      - GetAccessToken: add upstream branch to read api_key from credentials
      - shouldTriggerAntigravitySmartRetry: relax check from IsOAuth to Platform-based
      - isModelSupportedByAccount/WithContext: replace IsAntigravityModelSupported
        whitelist with mapAntigravityModel for unified scheduling/forwarding logic
      - mapAntigravityModel: fix edge case where wildcard target equals request model
      - Update tests for new behavior and add custom model_mapping test cases
      de092728
    • erio's avatar
      edb09370
    • erio's avatar
      43a4840d
    • erio's avatar
      feat(antigravity): comprehensive enhancements - model mapping, rate limiting, scheduling & ops · 5e98445b
      erio authored
      Key changes:
      - Upgrade model mapping: Opus 4.5 → Opus 4.6-thinking with precise matching
      - Unified rate limiting: scope-level → model-level with Redis snapshot sync
      - Load-balanced scheduling by call count with smart retry mechanism
      - Force cache billing support
      - Model identity injection in prompts with leak prevention
      - Thinking mode auto-handling (max_tokens/budget_tokens fix)
      - Frontend: whitelist mode toggle, model mapping validation, status indicators
      - Gemini session fallback with Redis Trie O(L) matching
      - Ops: enhanced concurrency monitoring, account availability, retry logic
      - Migration scripts: 049-051 for model mapping unification
      5e98445b
    • erio's avatar
      fix(antigravity): reduce 429 fallback cooldown from 5min to 30s · 8917afab
      erio authored
      The default fallback cooldown when rate limit reset time cannot be
      parsed was 5 minutes, which is too aggressive and causes accounts
      to be unnecessarily locked out. Reduce to 30 seconds for faster
      recovery. Config override still works (unit remains minutes).
      8917afab
    • erio's avatar
      fix(antigravity): auto-fix max_tokens <= budget_tokens causing 400 error · 49233ec2
      erio authored
      When extended thinking is enabled, Claude API requires max_tokens >
      thinking.budget_tokens. If misconfigured, this auto-adjusts max_tokens
      to budget_tokens + 1000 instead of returning a 400 error.
      
      - Add ensureMaxTokensGreaterThanBudget helper function
      - Extract Gemini25FlashThinkingBudgetLimit constant (24576)
      - Log adjustment for debugging
      49233ec2
    • shaw's avatar
      fix: 账号测试根据类型使用不同的 beta header · 39a5b17d
      shaw authored
      - OAuth 账号:使用完整的 DefaultBetaHeader 和 Claude Code 客户端 headers
      - API Key 账号:使用 APIKeyBetaHeader(不含 oauth beta)
      39a5b17d
    • shaw's avatar
      5299f3dc
    • shaw's avatar
    • yangjianbo's avatar
      test(codex): 清理无用的 opencode 缓存测试 · 4e01126f
      yangjianbo authored
      移除不再需要的 setupCodexCache 调用与辅助函数(已不再回源/读写缓存)
      4e01126f
    • yangjianbo's avatar
      feat(codex): 移除 opencode 指令回源与缓存 · 55b56328
      yangjianbo authored
      - 不再从 GitHub 拉取 opencode codex_header.txt\n- 删除 ~/.opencode 缓存与异步刷新逻辑\n- 所有 instructions 统一使用内置 codex_cli_instructions.md
      55b56328
    • yangjianbo's avatar
      feat(gateway): 支持强制 Codex CLI 模式并伪装 UA · ce764bf2
      yangjianbo authored
      - Codex CLI 请求仅使用内置 instructions,不再读取 opencode 缓存/回源\n- 新增 gateway.force_codex_cli(环境变量 GATEWAY_FORCE_CODEX_CLI)\n- ForceCodexCLI=true 时转发上游强制 User-Agent=codex_cli_rs/0.0.0\n- 更新 deploy 示例配置
      ce764bf2
  3. 06 Feb, 2026 7 commits