清理: - 删除 34 份过时文档(gap reports/QA临时报告/验收报告/阶段性文档) - 删除 docs/.hermes/skills 第三方 skills 副本(16 文件) - 删除 skills-lock.json 目录归集: - 根目录仅保留 README.md 索引 - product/ — 产品与架构设计(PRD + ARCHITECTURE + P2设计文档 + AI/企业路线图) - tracking/ — Chatwoot parity 开发跟踪 - requirements/ — M01-M12 模块需求 - plans/ — 历史实现计划 - parity/ — 路由 parity 与前端契约 - qa/ — QA 报告与测试计划 - ops/ — 运维部署 命名规范: - 全小写 kebab-case,禁止全大写文件名 - product/tracking/ops 用 NN- 序号前缀 - requirements 用 MNN- 两位零填充模块号 - plans/qa 用 YYYY-MM-DD- 日期前缀 - requirements M1-M9 零填充为 M01-M09(修复字典序) 同步更新: - backend/cmd/route_parity/main.go 路径默认值 - backend/scripts/parity_frontend_smoke.sh 报告路径 - 所有 docs 内部交叉引用 - .gitignore 排除编译产物 (backend/gochat, backend/route_parity) - 新增迁移 000052/000053 - 前端 WS 相关修改
58 KiB
58 KiB
GoChat 技术架构设计文档
版本: v3.0 | 日期: 2026-07-09 项目定位: Go 语言 1:1 重写 Chatwoot(开源多渠道客服平台) 技术栈: Go 1.24 + Gin + GORM + PostgreSQL 16 + pgvector + Redis 7 + WebSocket 对标版本: Chatwoot v4.14.0(前端 vendored,直接对接 GoChat API)
1. 项目概况
| 指标 | 数值 |
|---|---|
| Go 源码文件(非测试) | 692 |
| 测试文件 | 331 |
| 测试代码行 | ~117,000 |
| 源码行(非测试) | ~162,000 |
| 数据库迁移 | 53 个(含 up/down) |
| 注册 API 路由 | 972 |
| 内部包 | 30 |
| Handler 文件 | 144 |
| Service 文件 | 130 |
| Repository 文件 | 96 |
| Model 文件 | 108 |
| 渠道 Provider | 9(Web Widget/Telegram/Email/Facebook/Instagram/WhatsApp/Twilio/LINE/TikTok) |
| AI/LLM 文件 | 18+(Captain + Copilot + Eino 框架 + Multi-Provider) |
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 # RegisterRoutes(106路由注册)
│ │
│ ├── 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 关键设计决策
- 软删除统一: 所有表支持
deleted_at(GORM软删除),所有查询自动过滤已删除记录 - JSONB广泛使用: feature_flags, permissions, config, metadata, guardrails 等灵活字段用 JSONB
- 外键约束: messages 引用 conversations/accounts/inboxes (数据一致性保证)
- 索引策略: 每张表都有
deleted_at索引 + 业务字段条件索引 (WHERE deleted_at IS NULL) - 时间戳统一: 所有表使用
created_at/updated_at/deleted_at(TIMESTAMP WITH TIME ZONE) - UUID公开标识: conversations 有 uuid 字段,用于公开API(避免内部ID泄露)
- 向量搜索: 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 格式:
// 成功 - 单条
{"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 结构体(持有全部依赖)
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 接口
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 | 已实现 |
| WhatsAppProvider | (pending) | (pending) | 基础结构 | |
| 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 (精简+合并) |