Files
gochat/docs/ARCHITECTURE_DESIGN.md
T
2026-06-04 15:44:48 +08:00

1192 lines
58 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# GoChat 技术架构设计文档
> 版本: v2.0 | 日期: 2026-05-25 | 作者: CTO
> 项目定位: Go 语言 1:1 重写 Chatwoot(开源多渠道客服平台)
> 技术栈: Go 1.24 + Gin + GORM + PostgreSQL + Redis + WebSocket
---
## 1. 项目概况
| 指标 | 数值 |
|------|------|
| Go 源码文件 | 418 |
| 测试文件 | 104 |
| 测试代码行 | 33,711 |
| 总代码行 | 90,422 |
| 数据库表 | 33 |
| API 路由 | 106 |
| Go 包 | 42 |
| 内部模块 | 26 |
GoChat 是一个开源企业级多渠道客服平台,以 Go 语言重写 Chatwoot 核心功能。系统采用单体架构 + 模块化设计,按业务域分包(domain-driven),通过接口解耦各模块,渠道通过插件接口注册以保证扩展性。
---
## 2. 项目目录结构
```
gochat/
├── cmd/ # 应用入口
│ ├── gochat/ # 主HTTP服务器入口
│ │ └── main.go # Gin server 启动
│ ├── migrate/ # 数据库迁移独立工具
│ │ └── main.go
│ └── test_debug/ # 测试调试辅助工具
├── configs/ # Viper 配置文件
│ ├── default.yaml # 默认配置基线
│ ├── development.yaml # 开发环境覆盖
│ ├── production.yaml # 生产环境覆盖
│ └── test.yaml # 测试环境覆盖
├── internal/ # 核心业务代码(Go不可外部引用)
│ ├── app/ # 应用生命周期
│ │ ├── app.go # App 结构体(持有所有依赖)
│ │ ├── bootstrap.go # 依赖注入编排(12步启动序列)
│ │ ├── database.go # PostgreSQL 连接池管理
│ │ ├── redis.go # Redis 连接 + PubSub
│ │ ├── shutdown.go # graceful shutdown 信号处理
│ │
│ ├── config/ # 配置管理
│ │ ├── config.go # Config 结构体(Server/DB/Redis/JWT/Captain/OAuth/SAML/Push/Webhook
│ │ ├── reloader.go # fsnotify 热加载(11字段无需重启)
│ │
│ ├── auth/ # 认证授权
│ │ ├── jwt.go # JWT 签发/验证(access + refresh 双令牌)
│ │ ├── refresh_store.go # Refresh Token Redis 存储
│ │ ├── oauth.go # OAuth2 (Google/GitHub) 回调处理
│ │ ├── mfa.go # TOTP MFA 启用/验证/禁用
│ │ ├── saml.go # SAML 2.0 SP 发起/IdP 回调
│ │ ├── permission.go # RBAC 权限矩阵(角色→权限映射)
│ │ ├── policy.go # Pundit-style 策略引擎
│ │ ├── platform_auth.go # Platform API Key 认证
│ │ ├── webhook_registry.go # Webhook Token 注册表
│ │
│ ├── middleware/ # Gin 中间件链
│ │ ├── auth.go # AuthMiddleware (JWT Bearer)
│ │ ├── cors.go # CORS (通配符子域名支持)
│ │ ├── ratelimit.go # 速率限制 (Redis滑动窗口)
│ │ ├── account_scope.go # AccountScope (账号上下文注入)
│ │ ├── super_admin.go # SuperAdmin (超级管理员守卫)
│ │ ├── security_headers.go # 安全响应头
│ │ ├── webhook_auth.go # WebhookAuth (渠道回调认证)
│ │ ├── recovery.go # panic 恢复
│ │ ├── request_logger.go # 结构化请求日志
│ │
│ ├── model/ # GORM 数据模型层
│ │ ├── base.go # BaseModel (ID/CreatedAt/UpdatedAt/DeletedAt)
│ │ ├── account.go # Account 模型
│ │ ├── user.go # User + AccountUser 模型
│ │ ├── contact.go # Contact + ContactInbox 模型
│ │ ├── inbox.go # Inbox + InboxMember 模型
│ │ ├── conversation.go # Conversation 模型
│ │ ├── message.go # Message + Attachment 模型
│ │ ├── notification.go # Notification + NotificationPreference 模型
│ │ ├── platform_app.go # PlatformApp 模型
│ │ ├── captain.go # Captain Assistant/Document/Scenario/CustomTool/Response
│ │ ├── copilot.go # Copilot Thread/Message 模型
│ │ ├── team.go # Team + TeamMember 模型
│ │ ├── reporting.go # ReportingEvent/Rollup 模型
│ │ ├── dashboard_app.go # DashboardApp 模型
│ │ ├── portal.go # Portal (Help Center) 模型
│ │ ├── category.go # Category 模型
│ │ ├── article.go # Article 模型
│ │ ├── folder.go # Folder 模型
│ │ ├── channel.go # Channel 配置子类型模型
│ │
│ ├── repository/ # 数据访问层(21+ Repo
│ │ ├── account_repo.go # Account CRUD + 软删除
│ │ ├── user_repo.go # User CRUD + 关联查询
│ │ ├── contact_repo.go # Contact CRUD + 搜索
│ │ ├── contact_inbox_repo.go # ContactInbox 关联
│ │ ├── conversation_repo.go # Conversation CRUD + 状态/标签/优先级
│ │ ├── inbox_repo.go # Inbox CRUD + 成员管理
│ │ ├── inbox_member_repo.go # InboxMember 座席分配
│ │ ├── message_repo.go # Message CRUD + 附件
│ │ ├── notification_repo.go # Notification CRUD + 未读计数
│ │ ├── notification_pref_repo.go # 通知偏好设置
│ │ ├── push_token_repo.go # Push 设备令牌
│ │ ├── webhook_sub_repo.go # Webhook 事件订阅
│ │ ├── team_repo.go # Team CRUD
│ │ ├── team_member_repo.go # TeamMember CRUD
│ │ ├── captain_*_repo.go # Captain 6 repos
│ │ ├── copilot_*_repo.go # Copilot 2 repos
│ │ ├── reporting_*_repo.go # Reporting 2 repos
│ │ ├── dashboard_app_repo.go # DashboardApp CRUD
│ │ ├── platform_app_repo.go # PlatformApp CRUD + API Key
│ │ ├── portal_*_repo.go # Help Center 5 repos
│ │
│ ├── service/ # 业务逻辑层
│ │ ├── auth_service.go # 登录/注册/刷新/切换账号
│ │ ├── account_service.go # Account 管理 + 成员增删
│ │ ├── contact_service.go # Contact 管理 + 搜索
│ │ ├── conversation_service.go # Conversation CRUD + 状态流转 + Agent分配
│ │ ├── inbox_service.go # Inbox CRUD + 渠道配置
│ │ ├── inbox_member_service.go # 座席分配/移除
│ │ ├── message_service.go # 消息收发 + 附件处理
│ │ ├── notification_service.go # 通知管理 + 未读计数
│ │ ├── notification_delivery_service.go # 通知推送管道(Push/Webhook/Email)
│ │ ├── push_subscription_service.go # Push 设令牌管理
│ │ ├── push_delivery_service.go # Web Push 发送 (VAPID)
│ │ ├── webhook_subscription_service.go # Webhook 订阅管理
│ │ ├── webhook_delivery_service.go # Webhook 事件投递 + 签名
│ │ ├── profile_service.go # 用户个人信息更新
│ │ ├── team_service.go # Team CRUD + 成员管理
│ │ ├── captain_*_service.go # Captain AI 5 services
│ │ ├── copilot_service.go # Copilot Thread + AI建议/摘要/翻译
│ │ ├── analytics_service.go # 报表聚合 + 指标计算
│ │ ├── dashboard_app_service.go # 自定义Dashboard + Widget管理
│ │ ├── platform_app_service.go # Platform App 管理 + API Key
│ │ ├── portal_*_service.go # Help Center 5 services
│ │ ├── autoassignment/ # 智能分配服务
│ │ │ ├── service.go # RoundRobin + 负载均衡分配
│ │ │ ├── rate_limiter.go # 分配速率限制
│ │ │ ├── listener.go # EventBus 事件监听
│ │
│ ├── automation/ # 自动化引擎
│ │ ├── model.go # AutomationRule + Macro + CsatSurvey 模型
│ │ ├── service.go # AutomationRuleService
│ │ ├── action_service.go # 规则动作执行引擎
│ │ ├── condition_filter.go # 条件过滤器
│ │ ├── condition_validator.go # 条件验证器
│ │ ├── macro_service.go # Macro CRUD + 执行
│ │ ├── csat_survey_service.go # CSAT 满意度调查
│ │ ├── *_listener.go # 多个EventBus监听器
│ │
│ ├── channel/ # 渠道抽象层
│ │ ├── provider.go # Provider 接口定义(注册表模式)
│ │ ├── dispatcher.go # 事件分发器(注册Listener
│ │ ├── broker.go # 消息中转器(进出分流)
│ │ ├── incoming.go # IncomingMessageHandler 接口
│ │ ├── outgoing.go # OutgoingMessageHandler 接口
│ │ ├── lifecycle.go # 渠道生命周期管理
│ │ ├── config.go # 渠道配置结构
│ │ ├── event.go # 渠道事件类型定义
│ │ ├── listener.go # Listener 接口
│ │ ├── facebook/ # Facebook + Instagram 渠道
│ │ │ ├── provider.go # FacebookProvider (Meta API)
│ │ │ ├── instagram_provider.go # InstagramProvider
│ │ │ ├── listener.go # FacebookEventListener + InstagramEventListener
│ │ │ ├── service.go # FacebookService (消息/媒体处理)
│ │ │ ├── repository.go # FacebookRepository (DB访问)
│ │ │ ├── pipeline.go # 消息处理管道
│ │ │ ├── media.go # 媒体下载/上传
│ │ │ ├── user_mapping.go # FB用户→Contact映射
│ │ │ ├── webhook_handler.go # HTTP webhook 处理
│ │ │ ├── types.go # FB消息/事件类型
│ │ ├── telegram/ # Telegram 渠道
│ │ │ ├── provider.go # TelegramProvider (Bot API)
│ │ │ ├── webhook_handler.go # Telegram webhook HTTP处理
│ │ │ ├── service.go # TelegramService
│ │ │ ├── repository.go # TelegramRepository
│ │ │ ├── pipeline.go # 消息处理管道
│ │ │ ├── types.go # TG消息/事件类型
│ │ ├── whatsapp/ # WhatsApp 渠道
│ │ │ ├── provider.go # WhatsAppProvider (Business API)
│ │ │ ├── service.go # WhatsAppService
│ │ │ ├── repository.go # WhatsAppRepository
│ │ │ ├── pipeline.go # 消息处理管道
│ │ │ ├── types.go # WA消息/事件类型
│ │ ├── email/ # Email 渠道
│ │ │ ├── imap_listener.go # IMAP 收信监听
│ │ │ ├── smtp_sender.go # SMTP 发信
│ │ │ ├── service.go # EmailService
│ │ │ ├── repository.go # EmailRepository
│ │ │ ├── pipeline.go # 邮件处理管道
│ │ │ ├── webhook_handler.go # Email webhook HTTP处理
│ │ │ ├── types.go # Email消息类型
│ │ │ ├── provider/ # Provider 注册桥接
│ │ │ │ ├── facebook.go # FB Provider → channel.Register
│ │ │ │ ├── telegram.go # TG Provider → channel.Register
│ │ │ │ ├── whatsapp.go # WA Provider → channel.Register
│ │ │ │ ├── email.go # Email Provider → channel.Register
│ │ │ │ ├── web_widget.go # WebWidget Provider → channel.Register
│ │
│ ├── handler/ # HTTP 处理层
│ │ ├── api/v1/ # API v1 Handlers (49文件)
│ │ │ ├── auth_handler.go # Auth: login/register/refresh/logout
│ │ │ ├── mfa_handler.go # MFA: enable/verify/disable
│ │ │ ├── saml_handler.go # SAML: SP发起/IdP回调/metadata
│ │ │ ├── account_handler.go # Account CRUD + 成员 + 设置
│ │ │ ├── contact_handler.go # Contact CRUD + 搜索
│ │ │ ├── conversation_handler.go # Conversation CRUD + 状态/标签/优先级
│ │ │ ├── inbox_handler.go # Inbox CRUD
│ │ │ ├── inbox_member_handler.go # 座席分配
│ │ │ ├── message_handler.go # Message CRUD + retry
│ │ │ ├── profile_handler.go # Profile GET/PUT/avatar
│ │ │ ├── notification_handler.go # 通知管理
│ │ │ ├── platform_app_handler.go # Platform App CRUD + API Key
│ │ │ ├── team_handler.go # Team CRUD + 成员
│ │ │ ├── captain_*_handler.go # Captain AI 4 handlers
│ │ │ ├── copilot_handler.go # Copilot Thread + AI动作
│ │ │ ├── analytics_handler.go # 报表/指标
│ │ │ ├── live_report_handler.go # 实时报表
│ │ │ ├── dashboard_app_handler.go # Dashboard + Widget
│ │ │ ├── portal_handler.go # Help Center Portal
│ │ │ ├── category_handler.go # Help Center 分类
│ │ │ ├── article_handler.go # Help Center 文章
│ │ │ ├── folder_handler.go # Help Center 文件夹
│ │ │ ├── portal_member_handler.go # Portal 成员
│ │ │ ├── automation_rule_handler.go # 自动化规则
│ │ │ ├── macro_handler.go # Macro CRUD + execute
│ │ │ ├── csat_survey_handler.go # CSAT 满意度调查
│ │ │ ├── push_subscription_handler.go # Push 设备管理
│ │ │ ├── webhook_subscription_handler.go # Webhook 管理
│ │ │ ├── web_widget_handler.go # WebWidget 配置/CRUD
│ │ │ ├── *_routes.go # 各模块路由注册函数
│ │ ├── webhook/ # 渠道 Webhook Handler
│ │ │ ├── facebook_webhook_handler.go # FB/IG webhook
│ │ │ ├── telegram_webhook_handler.go # TG webhook
│ │ ├── ws/ # WebSocket Handler
│ │ │ ├── handler.go # WS升级 + 消息分发
│ │
│ ├── router/ # 路由注册中心
│ │ ├── router.go # RegisterRoutes106路由注册)
│ │
│ ├── ws/ # WebSocket 核心层
│ │ ├── hub.go # Hub (连接池管理 + 广播)
│ │ ├── auth.go # WSAuthenticator (JWT + pubsub_token)
│ │ ├── broadcast.go # 事件广播分发
│ │ ├── presence.go # 在线状态追踪
│ │ ├── typing.go # 输入状态推送
│ │ ├── heartbeat.go # 心跳保活
│ │ ├── event_types.go # WS事件类型定义
│ │
│ ├── pubsub/ # 事件总线
│ │ ├── pubsub.go # PubSub 接口定义
│ │ ├── redis_pubsub.go # Redis Pub/Sub (watermill-redisstream)
│ │ ├── event_bus.go # EventBus (topic发布/订阅)
│ │
│ ├── llm/ # LLM Provider层
│ │ ├── provider.go # LLMProvider 接口
│ │ ├── openai_provider.go # OpenAI/volcengine/Ollama 统一适配
│ │
│ ├── dispatch/ # 事件分发
│ │ ├── dispatcher.go # Dispatcher (事件→Listener路由)
│ │ ├── event.go # 事件类型定义
│ │ ├── listener_registry.go # Listener 注册表
│ │
│ ├── worker/ # 后台任务
│ │ ├── worker.go # Worker池 (goroutine并发)
│ │
│ ├── security/ # 安全模块
│ │ ├── encryption.go # 加密/解密
│ │ ├── jwt_security.go # JWT 安全检查
│ │ ├── sql_safety.go # SQL 注入防护
│ │ ├── ssrf_protection.go # SSRF 防护
│ │ ├── webhook_signing.go # Webhook HMAC签名
│ │
│ ├── database/ # 数据库管理
│ │ ├── migrate.go # golang-migrate 迁移执行
│ │
│ ├── autoassignment/ # 智能分配
│ ├── campaign/ # 营销活动
│ ├── canned/ # 快捷回复
│ ├── csat/ # CSAT 模型
│ ├── goimap_stub/ # IMAP 客户端桩
│ ├── pgvector_stub/ # pgvector 桩
│ ├── database/ # DB 迁移管理
├── pkg/ # 可外部引用的公共工具包
│ ├── crypto/ # bcrypt Hash/Check
│ ├── logger/ # zap 结构化日志封装
│ ├── pagination/ # offset/limit 分页器
│ ├── response/ # {data, meta} 统一响应格式
│ ├── validator/ # go-playground/validator/v10 自定义规则
│ ├── testutil/ # 测试辅助工具
├── migrations/ # SQL 迁移文件(golang-migrate
│ ├── 000001_init_schema.up.sql # 核心表(22表)
│ ├── 000002_add_captain_ai_tables.up.sql # Captain AI 表(8表)
│ ├── 000003_add_rate_limit_state.up.sql # Rate Limit 表(1表)
│ ├── 000004_add_saml_config_tables.up.sql # SAML 表(2表)
│ ├── 000005_add_dashboard_apps_table.up.sql # Dashboard App 表(1表)
│ + 对应 down.sql 回滚文件
├── deploy/ # 部署配置
│ ├── k8s/ # Kubernetes manifests
│ ├── docker/ # Docker 相关
├── tests/ # 测试目录
│ ├── e2e/ # 端到端测试
│ │ ├── auth_e2e_test.go # 认证流程
│ │ ├── account_e2e_test.go # Account CRUD
│ │ ├── conversation_e2e_test.go # 会话流程
│ │ ├── crm_e2e_test.go # CRM 流程
│ │ ├── rbac_e2e_test.go # RBAC 流程
│ │ ├── dashboard_app_e2e_test.go # Dashboard 流程
│ │ ├── channel_incoming_e2e_test.go # 渠道流入
│ │ ├── middleware_e2e_test.go # 中间件测试
│ ├── helpers/ # 测试辅助
│ │ ├── pg_helper.go # PostgreSQL 测试连接
├── scripts/ # 脚本
│ ├── coverage/ # 覆盖率报告
├── docker-compose.yml # 主 compose
├── docker-compose.dev.yml # 开发 compose
├── docker-compose.prod.yml # 生产 compose
├── docker-compose.test.yml # 测试 compose
├── Dockerfile # 生产镜像构建
├── Dockerfile.dev # 开发镜像
├── .env.example # 环境变量模板
├── Makefile # 构建/测试/迁移命令
├── go.mod # Go 模块定义
├── go.sum # 依赖锁定
├── .air.toml # Air 热重载配置
```
---
## 3. 模块划分
### 3.1 分层架构总览
GoChat 采用 **四层分层架构**,各层职责明确,通过接口解耦:
```
┌──────────────────────────────────────────────────────┐
│ Handler (HTTP层) │
│ Gin Handler → 参数校验 → 调用Service → 统一响应格式 │
├──────────────────────────────────────────────────────┤
│ Service (业务层) │
│ 业务逻辑编排 → 跨Repo事务 → EventBus事件发布 │
├──────────────────────────────────────────────────────┤
│ Repository (数据层) │
│ GORM查询封装 → 软删除 → 分页 → 条件过滤 │
├──────────────────────────────────────────────────────┤
│ Model (模型层) │
│ GORM结构体 → 表映射 → 关联定义 → 验证标签 │
├──────────────────────────────────────────────────────┤
│ Database (基础设施) │
│ PostgreSQL连接池 → Redis PubSub → Migrations │
└──────────────────────────────────────────────────────┘
```
### 3.2 模块分组与职责
| 分组 | 模块 | 职责 | 关键文件 |
|------|------|------|---------|
| **应用生命周期** | app | 启动编排、graceful shutdown | bootstrap.go, app.go, shutdown.go |
| **配置管理** | config | Viper多环境叠加、热加载 | config.go, reloader.go |
| **认证授权** | auth | JWT、OAuth、MFA、SAML、RBAC | jwt.go, oauth.go, mfa.go, saml.go, permission.go |
| **HTTP中间件** | middleware | Auth、CORS、RateLimit、AccountScope、SecurityHeaders | auth.go, cors.go, ratelimit.go |
| **数据模型** | model | GORM结构体定义、表映射 | base.go, account.go, user.go, conversation.go |
| **数据访问** | repository | CRUD封装、软删除、分页 | 21+ repo文件 |
| **业务逻辑** | service | 业务编排、事务、事件发布 | 20+ service文件 |
| **HTTP处理** | handler/api/v1 | 参数校验、响应格式化 | 49 handler文件 |
| **路由注册** | router | 路由编排、中间件分组 | router.go |
| **渠道抽象** | channel | Provider接口、Dispatcher、进/出消息 | provider.go, dispatcher.go |
| **渠道实现** | channel/facebook,telegram,whatsapp,email | 各渠道Provider+Service+Repo+Pipeline | 各子包 |
| **WebSocket** | ws | Hub、认证、广播、状态、输入 | hub.go, auth.go, broadcast.go |
| **事件总线** | pubsub | Redis Pub/Sub + EventBus | pubsub.go, redis_pubsub.go, event_bus.go |
| **LLM集成** | llm | OpenAI/Ollama/volcengine统一适配 | provider.go, openai_provider.go |
| **自动化引擎** | automation | 规则CRUD+执行、Macro、CSAT | service.go, action_service.go |
| **智能分配** | autoassignment | RoundRobin+负载均衡分配 | service.go, round_robin.go |
| **报表分析** | reporting | ReportingEvent聚合 | model.go, service.go |
| **后台任务** | worker | goroutine并发池 | worker.go |
| **安全防护** | security | 加密、SQL注入防护、SSRF防护、Webhook签名 | encryption.go, sql_safety.go |
| **数据库管理** | database | golang-migrate迁移执行 | migrate.go |
### 3.3 公共工具包 (pkg/)
| 包 | 职责 |
|---|------|
| crypto | bcrypt Hash/Check 封装 |
| logger | zap 结构化日志(级别/格式/输出配置) |
| pagination | offset/limit 分页器 + 元数据计算 |
| response | `{data, meta}` 统一JSON响应格式 |
| validator | go-playground/validator/v10 自定义验证规则 |
| testutil | 测试辅助(DB setup/teardown、mock helper |
### 3.4 模块依赖关系图
```
cmd/gochat/main.go
app.Bootstrap()
┌─────────────┼─────────────┐
│ │ │
▼ ▼ ▼
config database redis
│ │ │
└─────────────┼─────────────┘
auth (JWT/OAuth/MFA/SAML)
┌─────────────┼─────────────┐
│ │ │
▼ ▼ ▼
repository service middleware
│ │ │
▼ ▼ │
model handler ────────┤
│ │
▼ ▼
router ──→ Gin Engine
┌─────────────┼─────────────┐
│ │ │
▼ ▼ ▼
channel ws/Hub pubsub
(providers) (WebSocket) (EventBus)
│ │ │
▼ ▼ ▼
FB/TG/WA/Email broadcast Redis stream
```
---
## 4. 数据库设计
### 4.1 技术选型
- **主数据库**: PostgreSQL 16 (带 pgvector 扩展,用于 Captain AI 向量搜索)
- **缓存层**: Redis 7+ (Pub/Sub + Rate Limit + Refresh Token + Session)
- **ORM**: GORM v2 (模型定义 + AutoMigrate + 软删除)
- **迁移工具**: golang-migrate (版本化SQL迁移)
- **测试模式**: SQLite (单元测试无需PG) / PostgreSQL (e2e测试)
### 4.2 数据库表总览 (33表)
#### 核心基础表 (M1 — 初始化)
| 表名 | 用途 | 关键字段 |
|------|------|---------|
| accounts | 多租户账户 | name, locale, timezone, status, feature_flags(JSON) |
| users | 用户 | email(唯一), password_hash, role, provider, totp_secret |
| account_users | 用户-账号关联 | user_id, account_id, role, custom_role_id |
| custom_roles | 自定义角色 | account_id, name, permissions(JSONB) |
| contacts | 客户联系人 | account_id, name, email, phone_number, identifier |
| inboxes | 收件箱/渠道入口 | account_id, channel_type, channel_id, enable_auto_assignment |
| contact_inboxes | 联系人-收件箱关联 | contact_id, inbox_id, source_id, pubsub_token |
| inbox_members | 座席分配 | inbox_id, user_id, role, availability_status |
| conversations | 会话 | account_id, inbox_id, contact_id, assignee_id, status, priority, uuid |
| messages | 消息 | conversation_id(FK), account_id(FK), sender_id, content, message_type |
| attachments | 附件 | message_id, file_type, file_url, file_size, metadata(JSONB) |
| notifications | 通知 | account_id, user_id, notification_type, primary_actor, read_at |
| notification_preferences | 通知偏好 | user_id, channel, event_type, enabled, preferences(JSONB) |
#### 渠道配置表 (M1)
| 表名 | 用途 |
|------|------|
| channels | 渠道配置基表 (account_id, inbox_id, type) |
| channel_telegrams | Telegram Bot 配置 (bot_token, bot_name) |
| channel_web_widgets | Web Widget 配置 (website_url, welcome_title, welcome_text) |
| channel_facebook_pages | Facebook Page 配置 (page_id, access_token) |
| channel_whatsapps | WhatsApp Business 配置 (phone_number, business_id) |
#### 平台管理表 (M2-M4)
| 表名 | 用途 | 关键字段 |
|------|------|---------|
| platform_apps | 平台应用管理 | name, api_key, account_id, type, status |
| reporting_events | 事件上报 | account_id, inbox_id, user_id, name, event_start/end_time |
| reporting_events_rollups | 报表聚合 | dimension, dimension_value, metric_name, period |
| rate_limit_states | 速率限制状态 | Redis-backed, DB持久化 |
#### 认证安全表 (M2-M4)
| 表名 | 用途 | 关键字段 |
|------|------|---------|
| saml_configs | SAML 配置 | account_id, idp_url, certificate, sp_entity_id |
| saml_sessions | SAML 会话 | session_id, name_id, account_id, expires_at |
#### Captain AI 表 (M10)
| 表名 | 用途 | 关键字段 |
|------|------|---------|
| captain_assistants | AI 助手 | account_id, name, config(JSONB), guardrails(JSONB), status |
| captain_documents | AI 文档 | assistant_id, external_link, content, content_fingerprint, status |
| captain_assistant_responses | AI 响应记录 | assistant_id, conversation_id, response_text, source |
| captain_scenarios | AI 场景 | assistant_id, name, trigger_conditions(JSONB), actions(JSONB) |
| captain_custom_tools | AI 自定义工具 | account_id, name, tool_config(JSONB) |
| captain_inboxes | 助手-收件箱绑定 | assistant_id, inbox_id |
#### Copilot 表 (M10)
| 表名 | 用途 | 关键字段 |
|------|------|---------|
| copilot_threads | Copilot 会话线程 | account_id, user_id, status |
| copilot_messages | Copilot 消息 | thread_id, role, content, metadata(JSONB) |
#### Dashboard 表 (M11)
| 表名 | 用途 | 关键字段 |
|------|------|---------|
| dashboard_apps | 自定义仪表板 | account_id, name, config(JSONB), widgets(JSONB数组) |
### 4.3 关键设计决策
1. **软删除统一**: 所有表支持 `deleted_at` (GORM软删除),所有查询自动过滤已删除记录
2. **JSONB广泛使用**: feature_flags, permissions, config, metadata, guardrails 等灵活字段用 JSONB
3. **外键约束**: messages 引用 conversations/accounts/inboxes (数据一致性保证)
4. **索引策略**: 每张表都有 `deleted_at` 索引 + 业务字段条件索引 (`WHERE deleted_at IS NULL`)
5. **时间戳统一**: 所有表使用 `created_at/updated_at/deleted_at` (TIMESTAMP WITH TIME ZONE)
6. **UUID公开标识**: conversations 有 uuid 字段,用于公开API(避免内部ID泄露)
7. **向量搜索**: captain_documents 未来通过 pgvector 支持语义搜索 (当前用 stub)
### 4.4 ER 关系图(核心实体)
```
Account ──1:N──→ User (via account_users)
Account ──1:N──→ Inbox
Account ──1:N──→ Contact
Account ──1:N──→ Conversation
Account ──1:N──→ Notification
Account ──1:N──→ CaptainAssistant
Account ──1:N──→ DashboardApp
Account ──1:N──→ PlatformApp
Inbox ──1:N──→ InboxMember (User)
Inbox ──1:N──→ Conversation
Inbox ──1:1──→ Channel (polymorphic: telegram/web_widget/facebook/whatsapp)
Contact ──1:N──→ ContactInbox ──→ Inbox
Contact ──1:N──→ Conversation
Conversation ──1:N──→ Message
Conversation ──1:N──→ Attachment (via Message)
Conversation ──1:1──→ Assignee (User)
CaptainAssistant ──1:N──→ CaptainDocument
CaptainAssistant ──1:N──→ CaptainScenario
CaptainAssistant ──1:N──→ CaptainInbox ──→ Inbox
CaptainAssistant ──1:N──→ CaptainAssistantResponse
CopilotThread ──1:N──→ CopilotMessage
```
---
## 5. API 路由设计
### 5.1 路由总体结构
GoChat API 基于 Gin 框架,采用 RESTful 设计,路由分组如下:
```
/health → 健康检查(无认证)
/api/v1/auth/* → 认证路由(公开)
/api/v1/saml/* → SAML 路由(公开)
/api/v1 (AuthRequired) → 主API路由(认证后)
/profile → 用户信息
/notifications → 通知管理
/push_subscriptions → Push 设备
/accounts/:id/webhooks → Webhook 管理
/accounts (AccountScope) → 账号级资源
/accounts/:id/inboxes/* → 收件箱 + WebWidget配置
/accounts/:id/conversations/* → 会话 + 消息
/accounts/:id/contacts/* → 联系人
/accounts/:id/teams/* → 团队
/accounts/:id/platform_apps/* → 平台应用
/accounts/:id/captain/* → Captain AI + Copilot
/accounts/:id/reports/* → 报表
/accounts/:id/live_reports/* → 实时报表
/accounts/:id/dashboard_apps/* → 自定义仪表板
/accounts/:id/portals/* → Help Center
/accounts/:id/automation_rules/* → 自动化规则
/accounts/:id/macros/* → Macro
/accounts/:id/csats/* → CSAT 满意度
/platform/api/v1 (SuperAdmin) → 平台管理路由
/widget (CORS, 无认证) → Widget API
/public/api/v1 (CORS, 无认证) → 公开 CSAT 调查
/webhooks (WebhookAuth) → 渠道回调
/webhooks/facebook/:inbox_id → FB/IG webhook
/webhooks/telegram/:bot_token → TG webhook
/ws → WebSocket 主端点
/cable → WebSocket ActionCable兼容端点
```
### 5.2 中间件链
```
全局中间件(所有路由):
Recovery → RequestLogger → RateLimit → CORS → SecurityHeaders
路由组中间件:
AuthMiddleware → /api/v1, /platform/api/v1
AccountScope → /accounts 子路由
SuperAdmin → /platform/api/v1
CORS → /widget, /public/api/v1
WebhookAuth → /webhooks
```
### 5.3 详细路由列表
#### 认证路由 (公开)
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /api/v1/auth/login | 登录(email+password) |
| POST | /api/v1/auth/register | 注册 |
| POST | /api/v1/auth/refresh | Token刷新 |
| POST | /api/v1/auth/logout | 登出 |
| POST | /api/v1/auth/switch_account | 切换账号 |
| POST | /api/v1/auth/reset_password | 密码重置请求 |
| PATCH | /api/v1/auth/reset_password/confirm | 确认密码重置 |
| GET | /api/v1/auth/google/callback | Google OAuth回调 |
| GET | /api/v1/auth/github/callback | GitHub OAuth回调 |
#### MFA路由 (需认证)
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /api/v1/auth/mfa/enable | 启用TOTP |
| POST | /api/v1/auth/mfa/verify | 验证TOTP |
| POST | /api/v1/auth/mfa/disable | 禁用TOTP |
#### SAML路由 (公开)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/auth/saml/:account_id/login | SAML SP发起登录 |
| POST | /api/v1/auth/saml/:account_id/callback | SAML IdP回调 |
| GET | /api/v1/auth/saml/:account_id/logout | SAML SLO |
| GET | /api/v1/auth/saml/:account_id/metadata | SAML SP Metadata |
#### Profile路由 (认证, 无账号作用域)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/profile | 获取用户信息 |
| PUT | /api/v1/profile | 更新用户信息 |
| PUT | /api/v1/profile/avatar | 更新头像 |
#### Notification路由 (认证, 用户级)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/notifications | 通知列表 |
| GET | /api/v1/notifications/unread_count | 未读数 |
| POST | /api/v1/notifications/read_all | 全部标读 |
| POST | /api/v1/notifications/:id/read | 标读 |
| PUT | /api/v1/notifications/:id | 更新 |
| DELETE | /api/v1/notifications/:id | 删除 |
| GET | /api/v1/accounts/:id/notification_settings | 通知设置 |
| PUT | /api/v1/accounts/:id/notification_settings | 更新设置 |
#### Push/Webhook Subscription路由
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /api/v1/push_subscriptions | 注册Push设备 |
| GET | /api/v1/push_subscriptions | 列出Push设备 |
| DELETE | /api/v1/push_subscriptions/:id | 删除Push设备 |
| GET | /api/v1/accounts/:id/webhooks | Webhook列表 |
| POST | /api/v1/accounts/:id/webhooks | 创建Webhook |
| GET | /api/v1/accounts/:id/webhooks/:webhook_id | Webhook详情 |
| PUT | /api/v1/accounts/:id/webhooks/:webhook_id | 更新Webhook |
| DELETE | /api/v1/accounts/:id/webhooks/:webhook_id | 删除Webhook |
#### Account路由 (AccountScope)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/accounts/ | 账号列表 |
| POST | /api/v1/accounts/ | 创建账号 |
| GET | /api/v1/accounts/:id | 账号详情 |
| PUT | /api/v1/accounts/:id | 更新账号 |
| DELETE | /api/v1/accounts/:id | 删除账号 |
| PUT | /api/v1/accounts/:id/settings | 更新设置 |
| GET | /api/v1/accounts/:id/users | 成员列表 |
| POST | /api/v1/accounts/:id/users | 添加成员 |
| DELETE | /api/v1/accounts/:id/users/:user_id | 移除成员 |
#### Inbox路由 (账号级)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/accounts/:id/inboxes/ | 收件箱列表 |
| POST | /api/v1/accounts/:id/inboxes/ | 创建收件箱 |
| GET | /api/v1/accounts/:id/inboxes/:inbox_id | 收件箱详情 |
| PUT | /api/v1/accounts/:id/inboxes/:inbox_id | 更新 |
| DELETE | /api/v1/accounts/:id/inboxes/:inbox_id | 删除 |
| POST | /api/v1/accounts/:id/inboxes/web_widget | 创建Widget收件箱 |
| GET | /api/v1/accounts/:id/inboxes/:inbox_id/web_widget_config | Widget配置 |
| PUT | /api/v1/accounts/:id/inboxes/:inbox_id/web_widget_config | 更新Widget配置 |
| DELETE | /api/v1/accounts/:id/inboxes/:inbox_id/web_widget | 删除Widget |
#### InboxMember路由 (座席分配)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/accounts/:id/inboxes/:inbox_id/members | 成员列表 |
| POST | /api/v1/accounts/:id/inboxes/:inbox_id/members | 添加成员 |
| PATCH | /api/v1/accounts/:id/inboxes/:inbox_id/members/:user_id | 更新成员 |
| DELETE | /api/v1/accounts/:id/inboxes/:inbox_id/members/:user_id | 移除成员 |
#### Conversation路由 (账号级)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/accounts/:id/conversations/ | 会话列表 |
| POST | /api/v1/accounts/:id/conversations/ | 创建会话 |
| GET | /api/v1/accounts/:id/conversations/search | 搜索会话 |
| POST | /api/v1/accounts/:id/conversations/filter | 过滤会话 |
| GET | /api/v1/accounts/:id/conversations/:id | 会话详情 |
| PATCH | /api/v1/accounts/:id/conversations/:id | 更新会话 |
| DELETE | /api/v1/accounts/:id/conversations/:id | 删除会话 |
| POST | /api/v1/accounts/:id/conversations/:id/assign | 分配Agent |
| POST | /api/v1/accounts/:id/conversations/:id/toggle_status | 切换状态 |
| PATCH | /api/v1/accounts/:id/conversations/:id/labels | 更新标签 |
| POST | /api/v1/accounts/:id/conversations/:id/mute | 静音 |
| POST | /api/v1/accounts/:id/conversations/:id/unmute | 取消静音 |
| PATCH | /api/v1/accounts/:id/conversations/:id/priority | 更新优先级 |
#### Message路由 (嵌套在Conversation下)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/accounts/:id/conversations/:conv_id/messages/ | 消息列表 |
| POST | /api/v1/accounts/:id/conversations/:conv_id/messages/ | 创建消息 |
| GET | /api/v1/accounts/:id/conversations/:conv_id/messages/:id | 消息详情 |
| PATCH | /api/v1/accounts/:id/conversations/:conv_id/messages/:id | 更新消息 |
| DELETE | /api/v1/accounts/:id/conversations/:conv_id/messages/:id | 删除消息 |
| POST | /api/v1/accounts/:id/conversations/:conv_id/messages/:id/retry | 重试 |
#### Contact路由 (账号级)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/accounts/:id/contacts/ | 联系人列表 |
| POST | /api/v1/accounts/:id/contacts/ | 创建联系人 |
| GET | /api/v1/accounts/:id/contacts/search | 搜索联系人 |
| GET | /api/v1/accounts/:id/contacts/:contact_id | 联系人详情 |
| PUT | /api/v1/accounts/:id/contacts/:contact_id | 更新联系人 |
| DELETE | /api/v1/accounts/:id/contacts/:contact_id | 删除联系人 |
#### Team路由 (账号级)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/accounts/:id/teams/ | 团队列表 |
| POST | /api/v1/accounts/:id/teams/ | 创建团队 |
| GET | /api/v1/accounts/:id/teams/:id | 团队详情 |
| PUT | /api/v1/accounts/:id/teams/:id | 更新团队 |
| DELETE | /api/v1/accounts/:id/teams/:id | 删除团队 |
| POST | /api/v1/accounts/:id/teams/:id/members | 添加成员 |
| DELETE | /api/v1/accounts/:id/teams/:id/members/:user_id | 移除成员 |
| GET | /api/v1/accounts/:id/teams/:id/members | 成员列表 |
#### Captain AI路由 (账号级)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/accounts/:id/captain/assistants/ | 助手列表 |
| POST | /api/v1/accounts/:id/captain/assistants/ | 创建助手 |
| GET | /api/v1/accounts/:id/captain/assistants/:id | 助手详情 |
| PUT | /api/v1/accounts/:id/captain/assistants/:id | 更新助手 |
| DELETE | /api/v1/accounts/:id/captain/assistants/:id | 删除助手 |
| POST | /api/v1/accounts/:id/captain/assistants/:id/inboxes | 绑定收件箱 |
| DELETE | /api/v1/accounts/:id/captain/assistants/:id/inboxes/:inbox_id | 解绑收件箱 |
| GET | /api/v1/accounts/:id/captain/assistants/:asst_id/documents/ | 文档列表 |
| POST | /api/v1/accounts/:id/captain/assistants/:asst_id/documents/ | 创建文档 |
| GET | /api/v1/accounts/:id/captain/assistants/:asst_id/documents/:id | 文档详情 |
| DELETE | /api/v1/accounts/:id/captain/assistants/:asst_id/documents/:id | 删除文档 |
| GET | /api/v1/accounts/:id/captain/assistants/:asst_id/scenarios/ | 场景列表 |
| POST | /api/v1/accounts/:id/captain/assistants/:asst_id/scenarios/ | 创建场景 |
| GET | /api/v1/accounts/:id/captain/assistants/:asst_id/scenarios/:id | 场景详情 |
| PUT | /api/v1/accounts/:id/captain/assistants/:asst_id/scenarios/:id | 更新场景 |
| DELETE | /api/v1/accounts/:id/captain/assistants/:asst_id/scenarios/:id | 删除场景 |
| GET | /api/v1/accounts/:id/captain/custom_tools/ | 自定义工具列表 |
| POST | /api/v1/accounts/:id/captain/custom_tools/ | 创建工具 |
| GET | /api/v1/accounts/:id/captain/custom_tools/:id | 工具详情 |
| PUT | /api/v1/accounts/:id/captain/custom_tools/:id | 更新工具 |
| DELETE | /api/v1/accounts/:id/captain/custom_tools/:id | 删除工具 |
#### Copilot路由 (账号级)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/accounts/:id/captain/copilot_threads/ | 线程列表 |
| POST | /api/v1/accounts/:id/captain/copilot_threads/ | 创建线程 |
| GET | /api/v1/accounts/:id/captain/copilot_threads/:id | 线程详情 |
| DELETE | /api/v1/accounts/:id/captain/copilot_threads/:id | 删除线程 |
| POST | /api/v1/accounts/:id/captain/copilot_threads/:id/messages | 发送消息 |
| POST | /api/v1/accounts/:id/captain/copilot/suggest_replies | AI建议回复 |
| POST | /api/v1/accounts/:id/captain/copilot/summarize | AI会话摘要 |
| POST | /api/v1/accounts/:id/captain/copilot/translate | AI翻译 |
#### Analytics路由 (账号级)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/accounts/:id/reports/summary | 报表总览 |
| GET | /api/v1/accounts/:id/reports/agents | Agent指标 |
| GET | /api/v1/accounts/:id/reports/inboxes | Inbox指标 |
| GET | /api/v1/accounts/:id/reports/labels | 标签指标 |
| GET | /api/v1/accounts/:id/reports/teams | 团队指标 |
| GET | /api/v1/accounts/:id/reports/conversations | 会话流量 |
| GET | /api/v1/accounts/:id/reports/conversation_traffic | 会话流量 |
#### Live Report路由
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/accounts/:id/live_reports/conversation_metrics | 实时会话指标 |
#### Dashboard App路由
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/accounts/:id/dashboard_apps/ | Dashboard列表 |
| POST | /api/v1/accounts/:id/dashboard_apps/ | 创建Dashboard |
| GET | /api/v1/accounts/:id/dashboard_apps/search | 搜索Dashboard |
| GET | /api/v1/accounts/:id/dashboard_apps/:id | Dashboard详情 |
| PUT | /api/v1/accounts/:id/dashboard_apps/:id | 更新Dashboard |
| PATCH | /api/v1/accounts/:id/dashboard_apps/:id | Patch更新 |
| DELETE | /api/v1/accounts/:id/dashboard_apps/:id | 删除Dashboard |
| GET | /api/v1/accounts/:id/dashboard_apps/:id/widgets | Widget列表 |
| POST | /api/v1/accounts/:id/dashboard_apps/:id/widgets | 添加Widget |
| PUT | /api/v1/accounts/:id/dashboard_apps/:id/widgets/:idx | 更新Widget |
| DELETE | /api/v1/accounts/:id/dashboard_apps/:id/widgets/:idx | 删除Widget |
#### Help Center (Portal)路由
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/accounts/:id/portals/ | Portal列表 |
| POST | /api/v1/accounts/:id/portals/ | 创建Portal |
| GET | /api/v1/accounts/:id/portals/:portal_id | Portal详情 |
| PUT | /api/v1/accounts/:id/portals/:portal_id | 更新Portal |
| DELETE | /api/v1/accounts/:id/portals/:portal_id | 删除Portal |
| POST | /api/v1/accounts/:id/portals/:portal_id/archive | 归档Portal |
| DELETE | /api/v1/accounts/:id/portals/:portal_id/logo | 删除Logo |
| GET | /api/v1/accounts/:id/portals/:portal_id/categories/ | 分类列表 |
| POST | /api/v1/accounts/:id/portals/:portal_id/categories/ | 创建分类 |
| GET | /api/v1/accounts/:id/portals/:portal_id/categories/:cat_id | 分类详情 |
| PUT | /api/v1/accounts/:id/portals/:portal_id/categories/:cat_id | 更新分类 |
| DELETE | /api/v1/accounts/:id/portals/:portal_id/categories/:cat_id | 删除分类 |
| POST | /api/v1/accounts/:id/portals/:portal_id/categories/reorder | 分类排序 |
| GET | /api/v1/accounts/:id/portals/:portal_id/articles/ | 文章列表 |
| POST | /api/v1/accounts/:id/portals/:portal_id/articles/ | 创建文章 |
| GET | /api/v1/accounts/:id/portals/:portal_id/articles/search | 搜索文章 |
| GET | /api/v1/accounts/:id/portals/:portal_id/articles/status_counts | 状态统计 |
| POST | /api/v1/accounts/:id/portals/:portal_id/articles/reorder | 文章排序 |
| POST | /api/v1/accounts/:id/portals/:portal_id/articles/bulk_update_status | 批量更新状态 |
| POST | /api/v1/accounts/:id/portals/:portal_id/articles/bulk_delete | 批量删除 |
| GET | /api/v1/accounts/:id/portals/:portal_id/articles/:art_id | 文章详情 |
| GET | /api/v1/accounts/:id/portals/:portal_id/articles/:art_id/edit | 编辑视图 |
| PUT | /api/v1/accounts/:id/portals/:portal_id/articles/:art_id | 更新文章 |
| DELETE | /api/v1/accounts/:id/portals/:portal_id/articles/:art_id | 删除文章 |
| GET | /api/v1/accounts/:id/portals/:portal_id/categories/:cat_id/articles | 分类下文章 |
| GET | /api/v1/accounts/:id/portals/:portal_id/folders/ | 文件夹列表 |
| POST | /api/v1/accounts/:id/portals/:portal_id/folders/ | 创建文件夹 |
| GET | /api/v1/accounts/:id/portals/:portal_id/folders/:folder_id | 文件夹详情 |
| PUT | /api/v1/accounts/:id/portals/:portal_id/folders/:folder_id | 更新文件夹 |
| DELETE | /api/v1/accounts/:id/portals/:portal_id/folders/:folder_id | 删除文件夹 |
| GET | /api/v1/accounts/:id/portals/:portal_id/members/ | 成员列表 |
| POST | /api/v1/accounts/:id/portals/:portal_id/members/ | 创建成员 |
| GET | /api/v1/accounts/:id/portals/:portal_id/members/:member_id | 成员详情 |
| PUT | /api/v1/accounts/:id/portals/:portal_id/members/:member_id | 更新成员 |
| DELETE | /api/v1/accounts/:id/portals/:portal_id/members/:member_id | 删除成员 |
#### Automation Rule路由
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/accounts/:id/automation_rules/ | 规则列表 |
| POST | /api/v1/accounts/:id/automation_rules/ | 创建规则 |
| GET | /api/v1/accounts/:id/automation_rules/:id | 规则详情 |
| PUT | /api/v1/accounts/:id/automation_rules/:id | 更新规则 |
| DELETE | /api/v1/accounts/:id/automation_rules/:id | 删除规则 |
| POST | /api/v1/accounts/:id/automation_rules/:id/clone | 克隆规则 |
#### Macro路由
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/accounts/:id/macros/ | Macro列表 |
| POST | /api/v1/accounts/:id/macros/ | 创建Macro |
| GET | /api/v1/accounts/:id/macros/:id | Macro详情 |
| PUT | /api/v1/accounts/:id/macros/:id | 更新Macro |
| DELETE | /api/v1/accounts/:id/macros/:id | 删除Macro |
| POST | /api/v1/accounts/:id/macros/:id/execute | 执行Macro |
#### CSAT路由
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/accounts/:id/csats/ | CSAT列表 |
| GET | /api/v1/accounts/:id/csats/metrics | CSAT指标 |
| POST | /api/v1/accounts/:id/csats/:id/update_review_notes | 更新审阅笔记 |
#### Platform App路由 (账号级)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/v1/accounts/:id/platform_apps/ | 应用列表 |
| POST | /api/v1/accounts/:id/platform_apps/ | 创建应用 |
| GET | /api/v1/accounts/:id/platform_apps/search | 搜索应用 |
| GET | /api/v1/accounts/:id/platform_apps/:id | 应用详情 |
| PUT | /api/v1/accounts/:id/platform_apps/:id | 更新应用 |
| DELETE | /api/v1/accounts/:id/platform_apps/:id | 删除应用 |
| POST | /api/v1/accounts/:id/platform_apps/:id/regenerate_api_key | 重生API Key |
#### Platform API路由 (超级管理员)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /platform/api/v1/apps | 应用列表 |
| POST | /platform/api/v1/apps | 创建应用 |
| GET | /platform/api/v1/apps/search | 搜索应用 |
| GET | /platform/api/v1/apps/:id | 应用详情 |
| PUT | /platform/api/v1/apps/:id | 更新应用 |
| DELETE | /platform/api/v1/apps/:id | 删除应用 |
| POST | /platform/api/v1/apps/:id/regenerate_api_key | 重生API Key |
#### Widget路由 (公开, CORS)
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /widget/init | Widget初始化 |
| POST | /widget/contact | Widget创建联系人 |
| GET | /widget/conversations | Widget会话列表 |
| POST | /widget/messages | Widget发送消息 |
| GET | /widget/cable_token | 获取Cable令牌 |
#### 公开CSAT路由 (无认证, CORS)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /public/api/v1/conversations/:uuid/csats | 获取CSAT调查 |
| POST | /public/api/v1/conversations/:uuid/csats | 提交CSAT评分 |
#### Webhook回调路由 (渠道认证)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /webhooks/facebook/:inbox_id | FB webhook验证 |
| POST | /webhooks/facebook/:inbox_id | FB webhook回调 |
| POST | /webhooks/telegram/:bot_token | TG webhook回调 |
| ANY | /webhooks/:channel_type/:identifier | 其他渠道(占位) |
#### WebSocket路由
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /ws | WebSocket 主端点 (JWT/pubsub_token认证) |
| GET | /cable | ActionCable兼容端点 |
#### 健康检查
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /health | 服务健康检查 (uptime, version, commit) |
### 5.4 统一响应格式
所有API响应遵循 `{data, meta}` envelope 格式:
```json
// 成功 - 单条
{"data": { ... }, "meta": {}}
// 成功 - 列表
{"data": [ ... ], "meta": {"page": 1, "per_page": 25, "total": 100}}
// 错误
{"error": {"code": "UNAUTHORIZED", "message": "Invalid token"}}
```
---
## 6. 依赖注入与启动序列
### 6.1 Bootstrap 12步序列
```
Step 1: LoadWithEnv(env) → 加载配置(Viper多环境叠加)
Step 2: Validate(cfg) → 校验配置完整性
Step 3: InitLogger → zap结构化日志初始化
Step 4: NewDatabase → PostgreSQL连接池
Step 4b: RunMigrations → golang-migrate执行(可选)
Step 5: NewRedisClient → Redis连接
Step 5b: NewRedisPubSub → Redis Pub/Sub (watermill)
Step 6: Wire Auth Infrastructure → JWT + OAuth + MFA + SAML + RefreshStore + WebhookRegistry
Step 7: Wire Repositories → 21+ Repo实例化(构造函数注入*gorm.DB)
Step 8: Wire Services → 20+ Service实例化(注入Repo+依赖)
Step 9: Wire Handlers → 49 Handler实例化(注入Service
Step 10: Setup Gin Router → 中间件链 + 路由注册
Step 11: Create WebSocket Hub → WS Hub + WSAuthenticator
Step 12: Setup Config Reloader → fsnotify热加载(11字段)
```
### 6.2 App 结构体(持有全部依赖)
```go
type App struct {
config *config.Config
reloader *config.ConfigReloader
db *gorm.DB
pubsub pubsub.PubSub
engine *gin.Engine
wsHub *ws.Hub
}
```
---
## 7. 技术选型与关键依赖
| 依赖 | 版本 | 用途 |
|------|------|------|
| Gin | v1.10 | HTTP 框架 |
| GORM | v1.30 | ORM (PostgreSQL + SQLite + MySQL驱动) |
| golang-migrate | v4.19 | 版本化SQL迁移 |
| watermill + redisstream | v1.5/v1.4 | Redis Pub/Sub 事件总线 |
| go-redis | v9.12 | Redis客户端 |
| gorilla/websocket | v1.5 | WebSocket |
| golang-jwt | v5.2 | JWT签发/验证 |
| go-playground/validator | v10.20 | 参数校验 |
| spf13/viper | v1.19 | 配置管理 |
| go-playground/bluemonday | v1.0 | HTML安全过滤 |
| go-resty | v2.16 | HTTP客户端(渠道API调用) |
| pgvector-go | v0.4 | 向量搜索(Captain AI) |
| gorm.io/datatypes | v1.2 | JSONB类型支持 |
| emersion/go-imap | v1.2 | IMAP邮件收取 |
| fsnotify | v1.7 | 配置文件热加载 |
| miniredis | v2.38 | Redis测试mock |
| uber/zap | v1.23 | 结构化日志 |
| golang.org/x/crypto | v0.45 | bcrypt + argon2 |
| golang.org/x/oauth2 | v0.30 | OAuth2客户端 |
---
## 8. 渠道抽象层设计
### 8.1 Provider 接口
```go
type Provider interface {
Name() string // "facebook", "telegram", etc.
ProcessIncoming(ctx, event) (Message, error) // 进站消息处理
ProcessOutgoing(ctx, message) error // 出站消息发送
ValidateWebhook(ctx, request) error // Webhook验签
}
```
### 8.2 渠道注册表模式
- 全局 `channel.Register(provider)` 注册各Provider
- `channel.Dispatcher` 分发事件到对应Listener
- 每个渠道实现: Provider + Listener + Service + Repository + Pipeline + Types
### 8.3 已实现渠道
| 渠道 | Provider | Listener | Webhook | 状态 |
|------|---------|---------|---------|------|
| Facebook/Instagram | FacebookProvider + InstagramProvider | FBEventListener + IGEventListener | facebook_webhook_handler | 已实现 |
| Telegram | TelegramProvider | (via webhook) | telegram_webhook_handler | 已实现 |
| WhatsApp | WhatsAppProvider | (pending) | (pending) | 基础结构 |
| Email | EmailProvider (IMAP+SMTP) | IMAPListener | email_webhook_handler | 已实现 |
| Web Widget | WebWidgetProvider | (via HTTP) | (内部路由) | 已实现 |
---
## 9. WebSocket 实时通信
### 9.1 双端点设计
- `/ws` — 主WebSocket端点
- `/cable` — ActionCable兼容端点(Chatwoot迁移兼容)
### 9.2 认证方式
- JWT Bearer Token (query param或首条消息)
- pubsub_token (ContactInbox级认证)
### 9.3 功能模块
| 模块 | 职责 |
|------|------|
| Hub | 连接池管理 + 消息广播 |
| WSAuthenticator | JWT + pubsub_token 双认证 |
| Broadcast | EventBus → WS事件分发 |
| Presence | 在线/离线状态追踪 |
| Typing | 输入状态实时推送 |
| Heartbeat | 心跳保活 (ping/pong) |
---
## 10. 安全架构
| 安全措施 | 实现 |
|---------|------|
| JWT认证 | Access Token (短期) + Refresh Token (Redis存储, 长期) |
| MFA (TOTP) | 启用/验证/禁用三步流程 |
| SAML 2.0 | SP发起 + IdP回调 + SLO |
| RBAC | 角色→权限矩阵 (agent/admin/super_admin + custom_roles) |
| Rate Limiting | Redis滑动窗口 (per-IP + per-user) |
| SQL注入防护 | GORM参数化查询 + sql_safety检查 |
| SSRF防护 | URL白名单 + 内网IP过滤 |
| Webhook签名 | HMAC-SHA256 签名验证 |
| HTML安全 | bluemonday HTML过滤 |
| 安全响应头 | X-Frame-Options, CSP, HSTS, X-Content-Type-Options |
| 密码存储 | bcrypt + argon2id |
---
## 11. 测试架构
| 测试层级 | 工具 | 覆盖范围 |
|---------|------|---------|
| 单元测试 | Go testing + testify | Service/Repository/Auth/Middleware/Model (83文件, 141+用例) |
| E2E测试 | Go testing + PG helper | Auth/Account/Conversation/CRM/RBAC/Dashboard/Channel/Middleware |
| 测试DB | SQLite (单元) + PostgreSQL (e2e) | 独立DB, 无副作用 |
| Redis Mock | miniredis | Auth/RateLimit/PubSub测试 |
| Benchmark | Go benchmark | JWT签发/验证性能 |
---
## 12. 部署架构
### 12.1 Docker Compose 模式
```
docker-compose.yml → 主compose (app + postgres + redis)
docker-compose.dev.yml → 开发 (热重载 + debug端口)
docker-compose.prod.yml → 生产 (健康检查 + 资源限制)
docker-compose.test.yml → 测试 (独立PG + 覆盖率)
```
### 12.2 Kubernetes 部署
```
deploy/k8s/ → Deployment + Service + ConfigMap + Secret manifests
```
### 12.3 环境配置优先级
```
.env (最高) → configs/production.yaml → configs/default.yaml → 程序默认值
```
### 12.4 热加载字段(11个,无需重启)
- Log Level, CORS origins, Rate Limit thresholds, JWT expiry, Worker concurrency 等
---
## 13. 与 Chatwoot 的架构差异总结
| 维度 | Chatwoot (Ruby/Rails) | GoChat (Go/Gin) |
|------|---------------------|-----------------|
| 代码组织 | MVC按技术层分层 | 按业务域分包 (domain-driven) |
| 依赖注入 | Rails自动加载 | 手动DI + 构造函数注入 |
| 实时推送 | ActionCable | Redis Pub/Sub + WebSocket Hub |
| 异步任务 | Sidekiq (Ruby进程) | Goroutine + Worker池 |
| DB迁移 | ActiveRecord Migration | golang-migrate (SQL文件) |
| 配置管理 | InstallationConfig表 + ENV | Viper配置层 + fsnotify热加载 |
| 中间件 | Rails before_action | Gin显式中间件链 |
| 权限校验 | Pundit Policy类 | 中间件 + 内联权限函数 |
| 多态关联 | polymorphic (owner_type+owner_id) | 独立关联表 + JSON字段 |
| 事件分发 | Dispatcher + Listener | EventBus接口 + Redis Pub/Sub |
| 路由数量 | 327 | ~106 (精简合并) |
| 表数量 | 87 | 33 (精简+合并) |