1. 22 Apr, 2026 8 commits
  2. 21 Apr, 2026 8 commits
  3. 20 Apr, 2026 9 commits
  4. 19 Apr, 2026 1 commit
    • erio's avatar
      fix: delete scheduled test plans when account is deleted · 6579f28b
      erio authored
      Accounts use soft-delete (setting deleted_at), so PostgreSQL's
      ON DELETE CASCADE on scheduled_test_plans.account_id never fires.
      Add plan deletion to the existing account deletion transaction
      to ensure atomicity.
      
      Closes Wei-Shaw/sub2api#1728
      6579f28b
  5. 16 Apr, 2026 1 commit
  6. 15 Apr, 2026 3 commits
    • erio's avatar
      feat(usage): add account cost to breakdown sub-table and admin usage log · db27e8f0
      erio authored
      - UserBreakdownItem: add AccountCost field + SQL aggregation
      - UserBreakdownSubTable: add orange account cost column
      - Admin usage table: add account_cost column (after cost, default visible)
      - Column settings: add account_cost toggle option
      db27e8f0
    • erio's avatar
      test(usage): add unit tests for account_cost and fix gofmt · 22680dc6
      erio authored
      - Fix mock for GetModelStatsWithFilters: add account_cost column
      - Add assertion: GetStatsWithFilters always returns TotalAccountCost
      - New test: GetModelStatsAccountCostColumn verifies scan of AccountCost
      - New test: GetGroupStatsAccountCostColumn verifies scan of AccountCost
      - New test: GetStatsWithFiltersAlwaysReturnsAccountCost (no AccountID filter)
      - Integration test: add TotalAccountCost/TodayAccountCost assertions
      - Fix gofmt alignment in usage_log_types.go
      22680dc6
    • erio's avatar
      feat(usage): add account cost display to admin dashboard and usage pages · 6ade6d30
      erio authored
      - Add account_cost column to dashboard aggregation tables (migration 107)
      - DashboardStats: add TotalAccountCost/TodayAccountCost fields
      - ModelStat/GroupStat: add AccountCost field with SQL aggregation
      - GetStatsWithFilters: always return TotalAccountCost (remove accountID filter)
      - Dashboard Token cards: show user(green)/cost(orange)/standard(gray)
      - Usage stats card: show account cost and standard below main value
      - Model/Group distribution tables: add orange cost column
      6ade6d30
  7. 14 Apr, 2026 10 commits
    • erio's avatar
      fix: merge 5 PR-related improvements · 58677dd5
      erio authored
      - gateway_handler: pass ParsedRequest to RecordUsage + set in gin.Context
      - channel_handler: add FeaturesConfig to CRUD (WebSearch channel toggle)
      - channel_repo: features_config JSONB persistence (Create/Get/Update/List)
      - security_headers: add Stripe CSP domains (script-src + frame-src)
      58677dd5
    • erio's avatar
      fix: merge 30 general improvements from release branch · 6ac8ccde
      erio authored
      Bug fixes:
      - Detached context for GetAccountConcurrencyBatch (prevent all-zero on request cancel)
      - Filter soft-deleted users in GetByGroupID
      - Stripe CSP policy (allow Stripe.js in script-src and frame-src)
      - WebSearch API key validation on save
      - RECHARGING status in payment result success check
      - Windows test fixes (logger Sync deadlock, config path escaping)
      
      Feature enhancements:
      - Webhook multi-instance dispatch (extractOutTradeNo + GetWebhookProvider)
      - EasyPay mobile H5 payment (device param + PayURL2)
      - SSE error propagation in WebSearch emulation
      - AccountStatsCost DTO field for admin usage logs
      - Plans sort by sort_order instead of created_at
      - UsageMapHook for streaming response usage data
      - apicompat Instructions field passthrough
      - EffectiveLoadFactor for ops concurrency/metrics
      - Usage billing RETURNING balance for notify system
      - BulkUpdate mixed channel warning with details
      - println to slog migration in auth cache
      - Wire ProviderSet cleanup
      - CI cache-dependency-path optimization
      
      Frontend:
      - Refund eligibility check per provider (canRequestRefund)
      - Plan sort_order editing
      - Dead code cleanup (simulate_claude_max, client_affinity)
      - GroupsView platform switch guard
      - channels features_config API type
      - UsageView account_stats_cost export
      6ac8ccde
    • erio's avatar
      fix: resolve cherry-pick conflicts and restore compilation · d6965b06
      erio authored
      - Restore gateway_cache.go to upstream (no lua embeds)
      - Restore payment_order.go to upstream (use out_trade_no lookup)
      - Restore payment_fulfillment.go to upstream (same reason)
      - Add FeaturesConfig field and IsWebSearchEmulationEnabled to Channel
      - Add applyAccountStatsCost wrapper function
      - Add SettingKeyWebSearchEmulationConfig constant
      - Add WebSearchEmulationEnabled to SystemSettings
      - Add notify code rate limiting methods to EmailCache interface
      - Remove AllowUserRefund references (ent schema not present)
      - Fix duplicate import in payment_handler.go
      - Fix wire_gen.go argument mismatches
      d6965b06
    • erio's avatar
      fix: audit round-3 — proxy safety, intervals persistence, SMTP timeout, sort fix · 0a4ece5f
      erio authored
      - Skip websearch provider when ProxyID is set but proxy not found (prevent
        silent direct connection bypass)
      - Fix sortByStableRandomWeight: pair factors with items so sort.Slice swap
        keeps weights aligned
      - Allow empty platform in account_stats_pricing_rules (wildcard matching),
        only force anthropic default for main model_pricing
      - Add channel_account_stats_pricing_intervals table and repo layer support
        for interval-based pricing in account stats rules
      - calculateTokenStatsCost now uses interval pricing when available
      - Replace smtp.SendMail/tls.Dial with net.Dialer timeout (10s dial, 20s IO)
        to prevent goroutine leak on SMTP hang
      - Fix gofmt formatting issues
      - Web Search label: black text with red warning hint
      0a4ece5f
    • erio's avatar
      fix: round-2 audit fixes — security, code quality, and UI improvements · a9880ee7
      erio authored
      Security (HIGH):
      - Normalize all Redis cache keys to lowercase (verifyCode, passwordReset)
      - Fix verify code TTL renewal on failed attempts: use remaining TTL via
        ExpiresAt field instead of resetting to full 15-minute window
      - Add 3 missing fields to diffSettings audit log (promo_code, invitation_code,
        custom_endpoints)
      
      Code quality (MEDIUM):
      - Extract filterVerifiedEmails shared helper (balance_notify_service.go)
      - Add Pricing array non-empty validation for channel pricing rules
      - Add platform token semantics comment in gateway_service.go
      - Complete validatePlanPatch test coverage (+10 test cases)
      - Replace string types with QuotaThresholdType/QuotaResetMode across frontend
      - Remove duplicate getPlatformTextColor/getRateBadgeClass in ChannelsView
      - Return EMAIL_NOT_FOUND error on RemoveNotifyEmail miss
      
      UI improvements:
      - Reorder cost tooltip: user billing above separator, account billing below
      - Add NaN guard to accountBilled function
      - Move timezone selector inline into reset-mode row (no longer standalone)
      a9880ee7
    • erio's avatar
      fix: address audit findings for websearch, email verification, and pricing · 74f8a30f
      erio authored
      - Fix websearch provider failover: proxy error from provider-specific proxy
        now continues to next provider instead of aborting the entire loop
      - Fix SMTP failure locking users out: send email first, then write cache
        and increment rate counter
      - Fix notify email cache key case sensitivity: normalize to lowercase
      - Add OriginalPrice validation to validatePlanPatch and validatePlanRequired
      - Add empty scope validation for channel pricing rules (group_ids/account_ids)
      - Add platform color to account search dropdown in channel pricing rules
      74f8a30f
    • erio's avatar
      fix: batch 1 audit fixes — quota SQL fixed mode, public recharge URL,... · ed8a9d97
      erio authored
      fix: batch 1 audit fixes — quota SQL fixed mode, public recharge URL, WebSearch bool fallback, UpdatePlan validation
      
      H1: incrementUsageBillingAccountQuota now uses shared dailyExpiredExpr/weeklyExpiredExpr
          constants (supporting fixed reset mode) instead of hardcoded '24 hours'/'168 hours'
      H4: public settings endpoint now maps balance_low_notify_recharge_url
      H6: GetWebSearchEmulationMode tolerates legacy bool values (true→enabled)
      H7: UpdatePlan validates non-nil patch fields (rejects negative price, empty name, etc.)
      H8: UsageTable accountBilled() helper with total_cost ?? 0 null guard
      H9: AdminUsageLog TS type adds channel_id + billing_tier
      M2: account.go "fixed" literals replaced with thresholdTypeFixed constant
      M13: SystemSettings TS type adds web_search_emulation_enabled
      UI: QuotaLimitCard title labels now use flex-1 to align with flex-1 input boxes
      ed8a9d97
    • erio's avatar
      fix: audit fixes for websearch, notifications, and channel pricing · b7fb2e43
      erio authored
      P0: fix wildcard matching test assertion (config order, not longest prefix)
      P0: add TotalRecharged to auth cache snapshot (v5) for percentage threshold
      P1: move pricing rules into per-platform sections in ChannelsView
      P1: populate account name cache when editing existing channel rules
      P1: sanitize email subject headers to prevent SMTP injection
      P1: make Redis INCR+EXPIRE idempotent for rate limiting
      P1: deep copy FeaturesConfig in Channel.Clone()
      P2: clean up stale email="" placeholder comments
      P2: replace log.Printf with slog in email_service.go
      b7fb2e43
    • erio's avatar
      feat(notify): convert email lists to NotifyEmailEntry struct with toggle support · 915b7a4a
      erio authored
      - Change balance_notify_extra_emails and account_quota_notify_emails
        from []string to []NotifyEmailEntry{email, disabled, verified}
      - Add per-email enable/disable toggle for both user and admin notifications
      - Add PUT /user/notify-email/toggle API endpoint
      - Fix critical bug: API key auth cache snapshot missing balance notify
        fields (Email, Username, BalanceNotifyEnabled, etc.), causing
        notifications to never fire on cached request paths
      - Bump cache snapshot version 3→4 to invalidate stale entries
      - Add SQL migration 104 to convert old format data
      - Backward compatible: parseNotifyEmails auto-detects old/new format
      - User balance notify: max 3 emails (primary + 2 extra)
      - Admin quota notify: unlimited emails, each with toggle
      915b7a4a
    • erio's avatar
      fix: address audit findings for notify, websearch and security · 4e96a6fa
      erio authored
      - Fix GetByKeyForAuth missing user.FieldEmail and user.FieldUsername (notifications sent to empty address)
      - Guard against empty email in collectBalanceNotifyRecipients
      - Remove non-atomic TotalRecharged read-modify-write in admin balance adjustment
      - HTML-escape userName/siteName/accountName in notification email templates
      - Fix timer leak in ProfileBalanceNotifyCard (add onUnmounted cleanup)
      - Add warning log on websearch proxy URL resolution failure
      4e96a6fa