1. 27 Apr, 2026 1 commit
  2. 26 Apr, 2026 2 commits
    • gaoren002's avatar
      615557ec
    • shaw's avatar
      feat(affiliate): 完善邀请返利系统 · 9b6dcc57
      shaw authored
        - 修复返利不到账的根因:tryClaimAffiliateRebateAudit 中 PostgreSQL 参数类型推断冲突
        - 补全 OAuth 注册路径(LinuxDo/OIDC/WeChat/Pending Flow)的邀请码绑定
        - 前端 OAuth 注册页面传递 aff_code 参数
        - 新增返利冻结期机制:可配置冻结时间,到期后自动解冻(懒解冻)
        - 新增返利有效期:绑定后 N 天内有效,过期不再产生返利
        - 新增单人返利上限:超出上限部分精确截断
        - 增强返利流程 slog 结构化日志,便于排查问题
        - 已邀请用户列表增加返利明细列
      9b6dcc57
  3. 25 Apr, 2026 4 commits
    • shaw's avatar
      feat(affiliate): add feature toggle and per-user custom invite settings · 4e1bb2b4
      shaw authored
      - 在系统设置「功能开关」中新增邀请返利总开关,默认关闭;
        关闭态:菜单隐藏、注册忽略 aff、新充值不返利,但已有 quota 仍可转余额
      - 支持管理员为指定用户设置专属邀请码(覆盖随机码,全局唯一)
      - 支持管理员为指定用户设置专属返利比例(覆盖全局比例,可单条/批量调整)
      - 在系统设置邀请返利卡片内嵌入专属用户管理表格(搜索/编辑/批量/删除),
        删除采用项目通用 ConfirmDialog,会同时清除专属比例并把邀请码重置为系统随机码
      - /affiliate 用户页新增「我的返利比例」卡片与动态使用说明,让用户直观看到
        分享后能拿到多少(同源 resolveRebateRatePercent 计算,与实际充值一致)
      - 新增数据库迁移 132 添加 aff_rebate_rate_percent 与 aff_code_custom 列
      - 新增 admin 路由组 /api/v1/admin/affiliates/users/* 共 5 个端点
      - AffiliateService 改为只依赖 *SettingService,去除冗余的 SettingRepository
      - 邀请码格式校验放宽到 [A-Z0-9_-]{4,32},兼容旧 12 位系统码与新自定义码
      - 补充单元测试与集成测试覆盖新方法、冲突路径与边界值
      4e1bb2b4
    • shaw's avatar
      feat(openai): port /responses/compact account support flow (PR #1555) · 095f457c
      shaw authored
      将 vansour/sub2api#1555 的 OpenAI compact 能力建模手工移植到当前 main:账号
      级 compact 状态/auto-force_on-force_off 模式、compact-only 模型映射、调度器
      tier 分层(已支持 > 未知 > 已知不支持)、管理后台 compact 主动探测,以及对应
      i18n/状态徽章。普通 /responses 流量行为不变,无数据库迁移。
      095f457c
    • 4fuu's avatar
      fix(openai): bump codex CLI version from 0.104.0 to 0.125.0 · 1e57e88e
      4fuu authored
      The hardcoded codex CLI version (0.104.0) causes upstream rejection
      when using gpt-5.5 with compact, as the server treats the request
      as an outdated client and returns 400/502.
      
      Update codexCLIVersion, codexCLIUserAgent, and openAICodexProbeVersion
      to 0.125.0 to match the current Codex CLI release.
      
      Fixes #1933, #1887, #1865
      Related: #1609, #1298, #849
      1e57e88e
    • shaw's avatar
      refactor(affiliate): tighten DI and harden inviter code validation · aa8ee33b
      shaw authored
      - Drop SetAffiliateService setters and ProvideAuthService /
        ProvidePaymentService / ProvideUserHandler wrappers in favor of direct
        Wire constructor injection. AffiliateService has no back-edge to
        Auth/Payment/User, so the indirection was never required.
      - Change RegisterWithVerification's variadic affiliateCode to a fixed
        parameter; adjust all call sites.
      - Validate aff_code length and charset in BindInviterByCode before any
        DB lookup, eliminating timing-side-channel and useless DB roundtrips
        on malformed input.
      - Make affiliate cache invalidation synchronous; surface Redis errors
        via the project logger instead of swallowing them in a detached
        goroutine.
      - Add an integration test guarding cross-layer tx propagation in
        AccrueQuota and a unit test pinning the aff_code format rules.
      aa8ee33b
  4. 24 Apr, 2026 1 commit
  5. 23 Apr, 2026 6 commits
    • erio's avatar
      revert: remove fork-only changes from release sync · 67518a59
      erio authored
      Revert payment/wechat, sora/claude-max cleanup, fork-only migrations,
      and cosmetic changes that were brought in by the release sync commit.
      Keep only channel-monitor related improvements:
      - PublicSettingsInjectionPayload named struct with drift test
      - ChannelMonitorRunner graceful shutdown in wire
      - image_output_price in SupportedModelChip
      - Simplified buildSelfNavItems in AppSidebar
      - Gateway WARN logs for 503 branches
      67518a59
    • erio's avatar
      sync: bring over remaining release/custom-0.1.115 changes · 748a84d8
      erio authored
      - Extract PublicSettingsInjectionPayload named struct with drift test
      - Add channel_monitor_default_interval_seconds to SSR injection
      - Add image_output_price to SupportedModelChip
      - Simplify AppSidebar buildSelfNavItems (admins see available channels)
      - Add gateway WARN logs for 503 no-available-accounts branches
      - Wire ChannelMonitorRunner into provideCleanup for graceful shutdown
      - Add migrations 130/131 (CC template userid fix + mimicry field cleanup)
      - Clean up fork-only features (sora, claude max simulation, client affinity)
      - Remove ~320 obsolete i18n keys
      - Add codexUsage utility, WechatServiceButton, BulkEditAccountModal
      - Tidy go.sum
      748a84d8
    • erio's avatar
      test(payment): cover ErrOrderNotFound sentinel contract · d5dac84e
      erio authored
      Service layer (payment_fulfillment_order_not_found_test.go):
      - TestHandlePaymentNotification_UnknownOrder_ReturnsSentinel: in-memory
        sqlite ent client, query for a non-existent out_trade_no → errors.Is
        must recognise ErrOrderNotFound (handler relies on this to ack 200).
      - TestHandlePaymentNotification_NonSuccessStatus_Skips: non-success
        notification short-circuits before DB lookup → nil error.
      - TestErrOrderNotFound_DistinctFromOtherErrors: generic errors must not
        match the sentinel (prevents silently swallowing DB failures).
      
      Handler layer (payment_webhook_handler_test.go):
      - TestUnknownOrderWebhookAcksWithSuccess: locks the two ingredients the
        handleNotify ack path depends on — fmt.Errorf %w wrapping preserves
        errors.Is recognition, and writeSuccessResponse(stripe) returns an
        empty 200 body that Stripe treats as acknowledged.
      d5dac84e
    • erio's avatar
      fix(payment): ack unknown-order webhooks with 2xx to stop provider retries · 75e1b40f
      erio authored
      Introduce a sentinel ErrOrderNotFound in the payment service layer so the
      webhook handler can distinguish "the out_trade_no does not exist in our DB"
      from other fulfillment failures, and downgrade the former to a WARN log +
      success response.
      
      Background
      - Providers (Stripe, Alipay, Wxpay, EasyPay, ...) retry webhooks whenever
        we answer non-2xx. When a webhook endpoint is misconfigured (e.g. a
        foreign environment points at us) or our orders table has been wiped,
        we return 500 forever and the provider retries for days, spamming logs.
      - The old code also collapsed "order not found" and "DB query failed" into
        the same branch — a DB blip would be reported as "order not found" and
        swallowed.
      
      Service layer (payment_fulfillment.go)
      - Add `var ErrOrderNotFound = errors.New("payment order not found")`.
      - In HandlePaymentNotification, distinguish the two error paths:
        * dbent.IsNotFound(err) → wrap with ErrOrderNotFound so callers can
          errors.Is(...) it.
        * anything else → wrap the original err with %w so it still bubbles up
          as 500 and the provider retries (DB hiccup should be retried).
      
      Handler layer (payment_webhook_handler.go)
      - Before returning 500, check errors.Is(err, service.ErrOrderNotFound):
        emit a WARN (with provider / outTradeNo / tradeNo for discoverability),
        then call writeSuccessResponse so the provider sees its expected 2xx
        body (Stripe empty body / Wxpay JSON / others "success").
      - Other errors retain the existing 500 behavior.
      
      Monitoring note: because this path now swallows unknown-order webhooks
      silently from the provider's perspective, the WARN log line is the only
      signal. Alert on "unknown order, acking to stop retries" if you want
      visibility into misrouted webhooks or accidental data loss.
      75e1b40f
    • erio's avatar
      fix(dto): drop obsolete public settings drift test · 1949425a
      erio authored
      The drift test referenced service.PublicSettingsInjectionPayload, a
      named type introduced by a5b05538 but dropped when we cherry-picked
      that commit into feat/channel-insights (we kept the inline struct from
      HEAD to avoid pulling fork-only helpers from setting_service.go). The
      test therefore could not compile. The 2 new public-settings fields
      (channel_monitor_enabled, available_channels_enabled) are still covered
      by manual wiring in GetPublicSettingsForInjection.
      1949425a
    • james-6-23's avatar
      feat(rpm): RPM 限流模块优化 · dc5d42ad
      james-6-23 authored
      P0:
      - rpm_override 嵌入 Auth Cache Snapshot,消除每请求 DB 查询 (snapshot v6→v7)
      - 429 RPM 响应返回 Retry-After 头(当前分钟剩余秒数)
      
      P1:
      - ClearAll 按钮直连 DELETE API,带 loading 防重复
      - 新增 GET /admin/users/:id/rpm-status 管理员 RPM 用量查询端点
      
      优化:
      - checkRPM 从级联互斥改为并行取最严,user.rpm_limit 作为全局硬上限始终生效
      - Override/Group 变更后自动失效 auth cache
      - fail-open 语义不变,Redis 故障不阻塞业务
      dc5d42ad
  6. 22 Apr, 2026 22 commits
  7. 21 Apr, 2026 4 commits