Commit Graph

3079 Commits

Author SHA1 Message Date
erio
ef6ec8a15a fix(channel-monitor): drop soft delete, refactor feature flag to declarative form
### 后端修复:日志表不该用软删除

channel_monitor_histories / channel_monitor_daily_rollups 都是日志/聚合表,
没有恢复需求。110 里加的 SoftDeleteMixin 会让 DELETE 自动变成 UPDATE deleted_at,
导致行和索引只增不减,徒增磁盘占用和查询成本。

改回分批物理删(参考 OpsCleanupService.deleteOldRowsByID 模板):

- ent schema 移除 SoftDeleteMixin,重新 go generate
- repo 新增 deleteChannelMonitorBatched 辅助 + 两条 prune SQL 常量
  (WITH batch AS SELECT id LIMIT 5000 → DELETE IN batch)
- DeleteHistoryBefore / DeleteRollupsBefore 改调分批 raw SQL
- 移除 ComputeAvailability / ComputeAvailabilityForMonitors / UpsertDailyRollupsFor /
  ListLatestPerModel / ListLatestForMonitorIDs / ListRecentHistoryForMonitors 等
  raw SQL 中的 deleted_at IS NULL 过滤
- UpsertDailyRollupsFor 的 ON CONFLICT 去掉 deleted_at = NULL 重置
- migration 111 DROP COLUMN deleted_at + 对应索引(110 已部署但 maintenance
  首跑在次日 02:00,此时尚无业务数据在依赖软删除)

### 前端重构:feature flag 声明式 + 复用

AppSidebar.vue 里 7 处 `...(flag ? [item] : [])` 样板代码删光,改为 NavItem 加
featureFlag?: () => boolean | undefined 字段,加一个 applyFeatureFlags 递归
过滤(含 children)。语义统一为 `!== false`(宽容策略,undefined 时默认显示,
避免 public settings 未加载完成时菜单闪烁消失 — 对应用户反馈"刷新后菜单消失
要去保存设置才回来")。

- 集中声明 4 个 flag getter:flagChannelMonitor / flagPayment /
  flagOpsMonitoring / flagAdminPayment
- 提取 buildSelfNavItems 复用用户端主菜单和管理员"我的账户"子菜单
- 未来新增开关:在统一位置加一个 flag getter + 给对应 NavItem 加字段
  (不用再动渲染逻辑)

bump 0.1.114.29
2026-04-23 17:31:15 +08:00
erio
8cf83c984e feat(channel-monitor): aggregate history to daily rollups + soft delete
明细只保留 1 天,超过 1 天聚合到新表 channel_monitor_daily_rollups(按
monitor_id/model/bucket_date 维度),聚合保留 30 天。两张表都用 SoftDeleteMixin
软删除(DELETE 自动改为 UPDATE deleted_at = NOW())。

聚合 + 清理任务由 OpsCleanupService 的 cron 统一调度,与运维监控的清理共享
schedule(默认 0 2 * * *)和 leader lock。ChannelMonitorRunner 的 cleanupLoop
被移除,只保留 dueCheckLoop。

读取路径 ComputeAvailability* 改为 UNION 明细(今天 deleted_at IS NULL)+
聚合(过去 windowDays 天 deleted_at IS NULL),SUM(ok)/SUM(total) 自然加权
计算可用率,AVG latency 用 SUM(sum_latency_ms)/SUM(count_latency)。

watermark 表 channel_monitor_aggregation_watermark 单行(id=1),记录
last_aggregated_date,重启后从该日期 +1 继续聚合,首次为 nil 则从
today - 30d 开始回填,单次最多 35 天上限避免长事务。

raw SQL 的 ListLatestPerModel / ListLatestForMonitorIDs / ListRecentHistoryForMonitors
都补上 deleted_at IS NULL 过滤(SoftDeleteMixin interceptor 只对 ent query 生效)。

bump version to 0.1.114.28

GroupBadge 在 MonitorKeyPickerDialog 中复用平台主题色 + 倍率/专属倍率
(顺手优化)。
2026-04-21 10:10:56 +08:00
erio
ba98243cc2 feat(channel-monitor): gate UI by feature switch + polish form UX
- AppSidebar 三处菜单项(管理端渠道监控、用户端/个人页渠道状态)按
  channel_monitor_enabled 条件展开,关闭时隐藏
- ChannelStatusView setInterval 随开关启停:关闭 clearInterval,
  开启/未知态自动启动,避免禁用功能后仍在轮询
- MonitorFormDialog provider Select 改为 3 色单选按钮
  (openai=emerald / anthropic=orange / gemini=sky),i18n 文案
  供应商 → 平台 / Provider → Platform
- MonitorKeyPickerDialog 按钮列表改为 name/key/group 三列表格 +
  搜索框,按 key.group.platform === provider 过滤,避免跨平台误选
- form.provider 变化时清空 api_key,修复切换平台仍保留旧 key 的
  错配 bug
- providerPickerClass 抽取到 useChannelMonitorFormat composable,
  统一 emerald/orange/sky 颜色语义,消除硬编码 Tailwind class 重复
- maskApiKey 工具函数统一(utils/maskApiKey.ts),KeysView 与
  MonitorKeyPickerDialog 共用 slice(0,6)...slice(-4) 策略
- bump version to 0.1.114.27
2026-04-21 01:42:58 +08:00
erio
0d01bd908e refactor(channel-monitor): remove INTELLIGENCE MONITOR hero title
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
2026-04-21 00:27:07 +08:00
erio
7da5124067 feat(channel-monitor): add feature switch settings + fix extra_models save
Settings:
- New "功能开关" tab between 通用设置 and 安全与认证
- ChannelMonitorEnabled toggle: runner skips scheduling when false,
  user-facing list returns empty
- ChannelMonitorDefaultIntervalSeconds (15-3600): pre-fills interval
  when creating a new monitor; each monitor can still override

Bug fix:
- ModelTagInput now commits pending input on blur, not just Enter/Tab.
  Previously clicking "save" with an un-Enter'd extra model would drop
  the value (DB stored extra_models=[] even when user typed entries).

Backend:
- domain_constants: SettingKeyChannelMonitor{Enabled,DefaultIntervalSeconds}
- SettingService.GetChannelMonitorRuntime: lightweight getter used by
  runner tick + user handler per-request (fail-open on DB error)
- Runner tickDueChecks: bails early when feature disabled
- ChannelMonitorUserHandler: checks feature flag before serving
- Comment on runner doc: scheduler state is implicit (every tick re-reads
  ListEnabled from DB), so CRUD ops on monitors self-maintain the schedule

Bump VERSION to 0.1.114.25
2026-04-21 00:21:29 +08:00
erio
a1425b457d feat(channel-monitor): redesign user dashboard as card grid
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
2026-04-20 23:38:59 +08:00
erio
20a4e41872 feat(monitor): admin channel monitor MVP with SSRF protection and batch aggregation
新增 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 全绿
2026-04-20 20:21:02 +08:00
shaw
0b85a8da88 fix: add io.LimitReader bounds to prevent OOM in image handling
Limit image download and multipart upload reads to 20MB to prevent
unbounded memory allocation from abnormal upstream responses.
2026-04-23 10:27:42 +08:00
Wesley Liddick
327da8e260 Merge pull request #1813 from meteor041/meteor041/fix-openai-image-handling
fix: openai image request handling
2026-04-23 10:19:12 +08:00
meteor041
00778dca31 fix openai image request handling 2026-04-23 09:53:57 +08:00
Wesley Liddick
79aff2df31 Merge pull request #1810 from IanShaw027/fix/profile-auth-bindings-i18n
fix(payment,profile,admin): 修复支付二维码流程、绑定提示与后台配置说明
2026-04-23 09:48:41 +08:00
IanShaw027
f35e967516 fix payment qr fallback and admin guidance 2026-04-22 07:33:14 -07:00
github-actions[bot]
6449da6c8d chore: sync VERSION to 0.1.115 [skip ci] 2026-04-22 12:08:51 +00:00
shaw
755c7d5026 chore: revert README files to 78f691d2 version 2026-04-22 19:55:13 +08:00
Wesley Liddick
1da4bd72df Merge pull request #1802 from IanShaw027/fix/profile-auth-bindings-i18n
fix(profile): 修正邮箱重复显示问题并添加国际化语言支持
2026-04-22 19:49:43 +08:00
IanShaw027
5551349349 fix: clean up profile auth binding notes 2026-04-22 19:11:51 +08:00
shaw
c6d25f69d5 chore: 恢复PAYMENT系列文件 2026-04-22 18:48:40 +08:00
shaw
45065c23d5 fix(ci): run 108a migration before 109 in backfill integration test 2026-04-22 18:36:44 +08:00
Wesley Liddick
ddf80f5ea1 Merge pull request #1799 from IanShaw027/rebuild/auth-identity-foundation
fix(auth,payment,profile): 修复认证身份和支付系统的后续问题
2026-04-22 18:18:39 +08:00
Wesley Liddick
c048ca80a4 Merge branch 'main' into rebuild/auth-identity-foundation 2026-04-22 18:17:12 +08:00
IanShaw027
22385be515 Merge remote-tracking branch 'upstream/main' into rebuild/auth-identity-foundation
# Conflicts:
#	backend/internal/service/openai_images.go
2026-04-22 18:13:05 +08:00
shaw
4d0483f5b8 feat: 补充gpt生图模型测试功能 2026-04-22 18:12:03 +08:00
IanShaw027
6b19490393 fix(ci): align openai account tests and remove dead wxpay const 2026-04-22 18:09:46 +08:00
shaw
1e0d466002 feat: 补充gpt生图模型测试功能 2026-04-22 18:06:14 +08:00
IanShaw027
9de7a72cce fix(upgrade): close payment and oidc compatibility gaps 2026-04-22 18:01:51 +08:00
IanShaw027
66b3acc274 fix(lint): remove embedded response selectors in openai images 2026-04-22 17:51:45 +08:00
IanShaw
0bc3a521b5 Merge branch 'Wei-Shaw:main' into rebuild/auth-identity-foundation 2026-04-22 17:24:38 +08:00
IanShaw027
3419cb0112 fix(admin): preserve legacy oidc security write defaults 2026-04-22 17:22:24 +08:00
IanShaw027
a94d89efa7 fix(unit): restore secure oidc defaults and wechat alias reuse 2026-04-22 16:51:23 +08:00
IanShaw027
66680a3056 fix(test): update wechat bind start path assertion 2026-04-22 16:44:25 +08:00
IanShaw027
ad4600964e fix(ci): clean up lint and dead code 2026-04-22 16:38:36 +08:00
IanShaw027
82259d1380 fix(auth): preserve resolved token version on oauth login 2026-04-22 16:01:25 +08:00
IanShaw027
ca4e38aa01 fix(profile): stabilize binding compatibility and frontend checks 2026-04-22 14:57:47 +08:00
IanShaw027
1aab084ecb fix(payment): restore upgrade-safe payment flows 2026-04-22 14:57:16 +08:00
IanShaw027
36aed35957 fix(auth): harden oauth identity upgrade paths 2026-04-22 14:56:56 +08:00
Wesley Liddick
32107b4f95 Merge pull request #1795 from 0x90000/feat/openai-image-api-sync
feat(openai): 同步生图 API 支持并接入图片计费调度
2026-04-22 14:24:41 +08:00
IanShaw027
3d29f7c2fa fix(auth): invalidate access tokens on session revoke 2026-04-22 13:30:34 +08:00
IanShaw027
01a991f56f fix(test): restore identity repo integration imports 2026-04-22 13:22:33 +08:00
IanShaw027
6696e61c7b fix(frontend): preserve callback recovery state 2026-04-22 13:19:41 +08:00
IanShaw027
81c827ee51 fix(profile): stabilize identity binding management 2026-04-22 13:19:28 +08:00
IanShaw027
83cad63ce0 fix(auth): harden oauth callback adoption flows 2026-04-22 13:19:20 +08:00
IanShaw027
06136af805 fix(upgrade): preserve legacy auth and payment compatibility 2026-04-22 13:18:10 +08:00
lucas morgan
6ad333d6b2 fix(openai): 修复生图服务 lint 问题
- 移除不安全的类型断言用法
- 补齐响应体关闭与字符串拼接的 lint 问题
- 按 staticcheck 建议简化选择器与条件表达式
2026-04-22 12:54:39 +08:00
IanShaw027
29caf85104 fix(frontend): stabilize wechat payment resume recovery 2026-04-22 12:30:24 +08:00
IanShaw027
d6a04bb772 fix(payment): support source routing and compatible resume signing 2026-04-22 12:30:17 +08:00
lucas morgan
c548021921 feat(openai): 同步生图 API 支持并接入图片计费调度
- 同步 OpenAI 图片生成与编辑接口
- 接入图片请求解析、账号调度、转发与用量记录
- 接入图片计费与图片用量落库
- 限制 OAuth 生图仅支持无显式模型和尺寸的基础请求
2026-04-22 12:30:08 +08:00
IanShaw027
b2e0712190 fix(settings): preserve oauth config compatibility on upgrade 2026-04-22 12:30:07 +08:00
IanShaw027
767f2f2dfe fix(auth): harden pending oauth and backend mode flows 2026-04-22 12:30:00 +08:00
IanShaw027
1ffebbb568 fix(migrations): keep auth identity and payment upgrades safe 2026-04-22 12:29:52 +08:00
IanShaw027
be9df2bea7 fix(auth): scrub legacy pending oauth tokens on upgrade 2026-04-22 11:29:05 +08:00