1. 21 Apr, 2026 2 commits
    • erio's avatar
      feat(channel-monitor): request templates with snapshot apply + headers/body override · a2964259
      erio authored
      Problem:
      Upstream channels can reject monitor probes based on client fingerprint
      (e.g. "only Claude Code clients allowed"). The monitor had no way to
      customize the outgoing request to bypass such restrictions.
      
      Solution:
      Introduce reusable request templates that carry extra_headers plus an
      optional body override; monitors reference a template and receive a
      snapshot copy on apply. Template edits do NOT auto-propagate — users
      must click "apply to associated monitors" to refresh snapshots, so a
      bad template edit cannot instantly break all production monitors.
      
      Data model (migration 112):
      - channel_monitor_request_templates: id, name, provider, description,
        extra_headers jsonb, body_override_mode ('off'|'merge'|'replace'),
        body_override jsonb. Unique (provider, name).
      - channel_monitors: +template_id (FK, ON DELETE SET NULL), +extra_headers,
        +body_override_mode, +body_override (the three runtime snapshot fields).
      
      Checker (channel_monitor_checker.go):
      - callProvider + runCheckForModel accept a CheckOptions carrying the
        snapshot fields. mergeHeaders applies user headers on top of adapter
        defaults (forbidden list: Host / Content-Length / Transfer-Encoding /
        Connection / Content-Encoding).
      - buildRequestBody:
          off     -> adapter default body
          merge   -> shallow-merge over default; per-provider deny list
                     (model/messages/contents) protects the challenge contract
          replace -> user body verbatim
      - Replace mode skips challenge validation; instead HTTP 2xx + non-empty
        extracted response text = operational, empty = failed.
      - 4 new unit tests cover all three modes + replace/empty-response case.
      
      Admin API:
      - /admin/channel-monitor-templates CRUD + /:id/apply (overwrite snapshot
        on all template_id=id monitors, returns affected count).
      - channel_monitor request/response DTOs gain the 4 new fields.
      
      Frontend:
      - channelMonitorTemplate.ts API client.
      - MonitorAdvancedRequestConfig.vue shared component for headers textarea
        + body mode radio + body JSON editor; used by both template and monitor
        forms.
      - MonitorTemplateManagerDialog.vue: provider tabs, list/create/edit/
        delete/apply, live "associated monitors" count per row.
      - MonitorFiltersBar: new 模板管理 button next to 新增监控.
      - MonitorFormDialog: collapsible 高级 section with template dropdown
        (filtered by form.provider, clears on provider change) + embedded
        AdvancedRequestConfig. Picking a template copies its fields into the
        form (snapshot semantics mirrored on the client).
      - i18n zh/en entries for all new copy.
      
      chore: bump version to 0.1.114.32
      a2964259
    • erio's avatar
      refactor(channel-status): drop breadcrumb + subtitle from MonitorHero · 0c48f08f
      erio authored
      The "CHANNEL · STATUS" breadcrumb and the zh/en subtitles above the
      window-picker were redundant with the existing "渠道状态" page title
      shown in the layout header. Remove the left column and right-align the
      7d/15d/30d tabs + overall chip.
      
      Also drop the now-unreferenced channelStatus.hero.* i18n keys from both
      locales (grep confirms no remaining usage).
      
      chore: bump version to 0.1.114.31
      0c48f08f
  2. 20 Apr, 2026 3 commits
    • erio's avatar
      refactor(channel-monitor): remove INTELLIGENCE MONITOR hero title · 0d01bd90
      erio authored
      Subtitle + breadcrumb already convey context; the giant h1 was visual
      noise. Drops orphan i18n key `channelStatus.hero.title` and shrinks
      hero section vertical padding accordingly.
      
      Bump VERSION to 0.1.114.26
      0d01bd90
    • erio's avatar
      feat(channel-monitor): redesign user dashboard as card grid · a1425b45
      erio authored
      Reference check-cx UI: INTELLIGENCE MONITOR hero + 3-column card grid
      with 60-point timeline bars.
      
      Backend:
      - Add PrimaryPingLatencyMs + Timeline[60] to UserMonitorView
      - ListRecentHistoryForMonitors: batch CTE + ROW_NUMBER() window query
      - indexLatestByModel / indexAvailabilityByModel helpers
      
      Frontend:
      - 7 new components: ProviderIcon, MonitorMetricPair, MonitorAvailabilityRow,
        MonitorTimeline, MonitorHero, MonitorCard, MonitorCardGrid
      - ChannelStatusView 381→~180 lines (delegated to subcomponents)
      - AbortController reload concurrency protection
      - HSL 0-120° availability color mapping
      - Replace emoji with Icon component (bolt / globe)
      - i18n: monitorCommon.* shared namespace, channelStatus.hero.*
      
      Bump VERSION to 0.1.114.24
      a1425b45
    • erio's avatar
      feat(monitor): admin channel monitor MVP with SSRF protection and batch aggregation · 20a4e418
      erio authored
      新增 admin「渠道监控」模块(参考 BingZi-233/check-cx),独立于现有 Channel 体系。
      admin 配置 + 后台定时调用上游 LLM chat completions 健康检查 + 所有登录用户只读可见。
      
      后端:
      - ent: channel_monitor + channel_monitor_history(AES-256-GCM 加密 api_key)
      - service 按职责拆分:service/aggregator/validate/checker/runner/ssrf
      - provider strategy map 替代 switch(openai/anthropic/gemini)
      - repository batch 聚合(ListLatestForMonitorIDs + ComputeAvailabilityForMonitors)消除 N+1
      - runner: ticker(5s) + pond worker pool(5) + inFlight 防并发 + TrySubmit 防雪崩
        + 凌晨 3 点 cron 清理 30 天历史
      - SSRF 防护:强制 https + 私网/loopback/云元数据 IP 拒绝(127/8、10/8、172.16/12、
        192.168/16、169.254/16、100.64/10、::1、fc00::/7、fe80::/10)+ DialContext
        在 socket 层防 DNS rebinding
      - API key sanitize:擦除 url.Error 与上游响应 body 中的 sk-/sk-ant-/AIza/JWT 模式
      - APIKeyDecryptFailed 标志位 + 单 monitor 路径检测,避免空 key 调用上游
      
      handler:
      - admin: CRUD + 手动触发 + 历史接口(api_key 脱敏)
      - user: 只读列表 + 状态详情(去除 api_key/endpoint)
      - ParseChannelMonitorID 共用 + dto.ChannelMonitorExtraModelStatus 共用
      
      前端:
      - 路由 /admin/channels/{pricing,monitor} + /monitor(用户只读)
      - AppSidebar 父项 expandOnly 支持
      - ChannelMonitorView 拆为 8 个子组件 + ChannelStatusView 拆出 detail dialog
      - composables/useChannelMonitorFormat + constants/channelMonitor 共享
      - i18n monitorCommon namespace 消除 admin/user 两 view 重复
      
      合规:所有文件符合 CLAUDE.md(Go ≤ 500 行 / Vue ≤ 300 行 / 函数 ≤ 30 行)
      CI: go build / gofmt / golangci-lint(0 issues) / make test-unit / pnpm build 全绿
      20a4e418
  3. 22 Apr, 2026 4 commits
  4. 21 Apr, 2026 11 commits
  5. 20 Apr, 2026 5 commits
  6. 14 Apr, 2026 9 commits
    • erio's avatar
      feat: websearch quota enhancements and balance notify hint · 7c729293
      erio authored
      - QuotaLimit changed to *int64 (null=unlimited, >0=limited)
      - Add reset-usage endpoint (POST /admin/settings/web-search-emulation/reset-usage)
      - Show quota usage in header always (collapsed and expanded)
      - Add reset quota button in expanded provider view
      - Quota input: empty=unlimited with ∞ placeholder, must be >0 if set
      - Add email verification hint on balance notify card
      7c729293
    • erio's avatar
      fix(notify): add verification flow for saved unverified emails · 95f9b27e
      erio authored
      - Add "verify" button next to saved unverified emails in
        ProfileBalanceNotifyCard (send code → enter code → verify)
      - Backend: VerifyAndAddNotifyEmail now marks existing unverified
        emails as verified instead of returning "already exists"
      - Inline verification UI with countdown timer and resend button
      95f9b27e
    • erio's avatar
      fix(notify): use real-time balance for crossing detection and simplify email logic · 31550a2c
      erio authored
      - Fix cached balance causing threshold crossing to never trigger:
        read real-time balance from billingCacheService instead of stale
        API key auth snapshot
      - Remove email="" placeholder concept; all emails are user-managed
      - Only send notifications to verified && non-disabled emails
      - Frontend: pre-fill user's email in add input when list is empty
      - Remove FilterEnabledEmails/IsPrimaryDisabled helpers (no longer needed)
      31550a2c
    • 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(notify): add explicit save button for balance threshold · 61aa197b
      erio authored
      Replace blur-based auto-save with an explicit Save button so users
      know when their threshold is persisted. Shows success toast on save.
      61aa197b
    • erio's avatar
    • erio's avatar
      feat(notify): improve balance notify card UX · 81287e96
      erio authored
      - Show system default threshold as placeholder in custom threshold input
      - Display user's primary email with "Primary" badge
      - Support adding multiple pending emails before verification
      - Each pending email has independent send/verify/resend flow
      - Expose balance_low_notify_threshold in PublicSettings API
      - Clean up timers on unmount to prevent leaks
      81287e96
    • 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
    • erio's avatar
      feat(notify): add balance low & account quota notification system · b32d1a2c
      erio authored
      - User balance low notification: email alert when balance drops below
        configurable threshold (user email + verified extra emails)
      - Account quota notification: broadcast email to admin-configured
        recipients when daily/weekly/total quota usage exceeds alert threshold
      - Admin settings: global enable/disable, default threshold, quota
        notification email list (Email Settings tab)
      - User profile: enable/disable, custom threshold, add/remove extra
        notification emails with verification code flow
      - Account quota: per-dimension alert toggle and threshold in quota
        control card
      - Trigger logic: first-crossing only (old >= threshold && new < threshold
        for balance; old < threshold && new >= threshold for quota), naturally
        prevents duplicate notifications without Redis dedup
      b32d1a2c
  7. 31 Mar, 2026 1 commit
  8. 14 Feb, 2026 1 commit
  9. 08 Feb, 2026 1 commit
    • shaw's avatar
      feat(ui): 用户列表页显示当前并发数 · e4d74ae1
      shaw authored
      优化 /admin/users 页面的并发数列,显示「当前/最大」格式,
      参考 AccountCapacityCell 的设计风格。
      
      - 后端 UserHandler 注入 ConcurrencyService,批量查询用户当前并发数
      - 新增 UserConcurrencyCell 组件,支持颜色状态(空闲灰/使用中黄/满载红)
      - 前端 AdminUser 类型添加 current_concurrency 字段
      e4d74ae1
  10. 06 Feb, 2026 1 commit
  11. 02 Feb, 2026 1 commit
  12. 26 Jan, 2026 1 commit
    • shaw's avatar
      feat(auth): 实现 TOTP 双因素认证功能 · 1245f07a
      shaw authored
      新增功能:
      - 支持 Google Authenticator 等应用进行 TOTP 二次验证
      - 用户可在个人设置中启用/禁用 2FA
      - 登录时支持 TOTP 验证流程
      - 管理后台可全局开关 TOTP 功能
      
      安全增强:
      - TOTP 密钥使用 AES-256-GCM 加密存储
      - 添加 TOTP_ENCRYPTION_KEY 配置项,必须手动配置才能启用功能
      - 防止服务重启导致加密密钥变更使用户无法登录
      - 验证失败次数限制,防止暴力破解
      
      配置说明:
      - Docker 部署:在 .env 中设置 TOTP_ENCRYPTION_KEY
      - 非 Docker 部署:在 config.yaml 中设置 totp.encryption_key
      - 生成密钥命令:openssl rand -hex 32
      1245f07a