系统架构总览

读者:新成员、AI Agent、需要快速判断“这个需求应该改哪个 repo”的人。

本页只回答三件事

  1. retaintive 的系统由哪些 repo / runtime / 数据存储组成。
  2. 数据从外部进入系统后,按什么路径被处理并展示给用户。
  3. 哪些概念容易混在一起,应该拆开理解。

具体 backend 代码分层、auth chain、API request lifecycle 见 Backend 架构 Pattern。后端 pipeline / Lambda / AI prompt 全景见 2-backend.md。前端 5 层架构见 1-frontend.md


一句话定位

retaintive 是面向健身工作室的 AI 通话分析 + 线索追踪 + 业务运营平台

核心链路:

客户打电话 / 发短信 / 填表
→ RingCentral 或邮箱进入系统
→ 后台 Lambda 下载录音、转录、AI 分析、写入业务数据库
→ studio-api 查询 Neon / DynamoDB
→ studio-web 展示 Dashboard、Calls、Messages、Leads、Tasks

架构概念导航图(Level 0)

读 retaintive 架构文档时会碰到多组概念:Plane 分层、Pipeline、Hexagonal / Layered、Multi-tenant。它们不是互相替代的选择,而是从不同角度看同一个系统。下面这张图展示它们的层级关系 — Pipeline、代码分层、Multi-tenant 都是 Data Plane 内部的子问题:

架构概念导航图 — Plane 分层与 Data Plane 内部子问题的关系

6 个维度,各管什么

系统里有 6 个维度(Plane 分层 + 代码分层 + 多租户)。它们各自管什么、改一处会影响什么 — 用一通电话当例子串起来:

维度管什么改了会影响什么一通电话发生什么
Management Plane(管理层)人配置规则的入口 — admin / Studio 后台 / CDK 部署 / AWS Console加/删 store、改 RC 账号绑定、调整 IAM 权限。低频但高权限 — 错了会让整个 tenant 看不到自己的数据管理员之前配好"这个 RC 号码归 store_X"的映射规则(一次配,多通电话受益)
Control Plane(配置层)运行时配置的路由表 — PhoneStoreAssignments DDB / tenant_members / rc_stores路由表错 = 电话分给错的 store。这层有 cache,新 store 加完 Lambda 要 invalidate cacheLambda 进来, PhoneStoreAssignments 拿到 store_id(无人介入,纯查表)
Data Plane(数据层)业务数据实际处理的高频路径 — Lambda 执行 / 数据库写入 / S3 录音存储这层是延迟敏感的(SLA 看这里)。改了 = 影响生产 throughput。高频高并发拿到 store_id 后,这通电话被实际转录、AI 分析、写库
Pipeline(Data Plane 内部)数据处理按什么顺序经过哪些 Lambda改阶段顺序 = 改整个数据流。新增阶段要插队列 / 改 schema(高 blast radius)这通电话沿 transcribe-processor → SQS → ai-analysis-processor → SQS → contacts-analyzer 走过去
代码分层(Lambda 内部)单个 Lambda 代码怎么组织handler 接事件 / core 业务逻辑 / adapter 调外部改这层不影响其他 Lambda。重构、换 AI vendor、加 caching 都在这层ai-analysis-processor 内部:handler 接 SQS event → core 调 AI → adapter 写 Neon
Multi-tenant(横切所有层)每行数据带的隔离键 — V1 = store_id,Final = tenant_id 路由到具体 DB改这层 = 改隔离边界(SOX / compliance 级别的事)。改 query 不带 store_id = 跨 tenant 泄露每一步都带着 store_id。V1 之后还会先查 tenant_id 决定路由到哪个 Neon project

判断你要改的事在哪个维度:

  • "我要加一个 Lambda 来处理新事件" → Data Plane / Pipeline,先看 backend.md
  • "我要给 admin 加一个配置 store 的页面" → Management Plane,改 studio-api 或 control plane admin UI
  • "我要让某个 store 路由到不同 AI provider" → Control Plane,加 PhoneStoreAssignments 配置或 control plane 加字段
  • "我要重构 contacts-analyzer 的代码结构" → 代码分层,不影响其他 Lambda
  • "我要让一个客户的数据放独立数据库" → Multi-tenant,见 multi-tenant/overview.md

详细文档: Multi-Tenant 总览 · Pipeline 全景分析 · Backend 架构 Pattern · Store-Level 隔离


系统全景(Level 1)

7 个核心 repo,各管什么

这 7 个 repo 是 retaintive 业务的核心。每个 repo 控制一个维度,改之前先认清在哪。

Repo是什么管什么维度不是
studio-website-monorepo/apps/webVue 3 SPA,浏览器里跑,静态部署 Cloudflare PagesInterface 层(用户界面)不直接连数据库,不跑 backend 业务逻辑
studio-website-monorepo/apps/apiHono app 跑在 AWS Lambda + API Gateway,前端专用 APIInterface 层(前端 API connector)不是通话转录 / AI 分析 pipeline。它只 Neon / DDB 给前端返 JSON
callytics-infrastructure/lambda/*后台 processing Lambda(transcribe / ai-analysis / contacts-analyzer / message-processor / lead-processor),消费 SQS / EventBridgeData Plane + Pipeline不是给浏览器直接调用的 API。所有 Lambda 都异步触发
callytics-common共享 Drizzle schema + TypeScript types + 工具函数 + 4 个 domain module(Task Orchestrator / Contact Writer / Timeline Writer / Policy Guard)Data Plane 的 schema SoT + 共享代码不是 runtime 节点,不接收请求,不部署成 Lambda。其他 repo import
ringcentralSubscriptionServiceRingCentral webhook 接收 + OAuth token 管理 + 订阅生命周期(创建/续期),路由电话事件到下游 SQSIngress + Management Plane(OAuth 管理)不做转录,不做 AI,不写业务表(只贴标签 + 路由)
lead-trackingIMAP 邮箱轮询(每 5 分钟),解析潜在客户表单邮件,原子 db.batch()4 张 Neon 表 + 1 张 DDBIngress + Data Plane(Lead 入口的 source of truth)不消费 SQS。完全自主拉(poller)
retaintive-studio-control-planeTenant identity SoT(自己 Neon project + Admin UI deployed control-plane.retaintive.ai)。V1 = IDENTITY ONLYControl Plane(tenant identity 路由)⚠️ V1 standalone,生产业务 pipeline 还没 import 它(callytics-infrastructure / lead-tracking 等都未引用)。是为未来 multi-tenant 路由打的地基

不在表里(跟核心业务无关,内部工具 / dormant): docs(本文档站)/ lark-dm-bot(飞书机器人)/ claude-plugins(开发工具)/ botmux(开发工具)/ landingPage(retaintive 官网,dormant)/ .github-retaintive(Org-level workflow 集中库)。

前端怎么调到后端

前端能"把请求传给后端"不是因为它们在同一个 monorepo,而是因为:

  1. apps/web build 后部署成静态文件到 Cloudflare Pages
  2. 浏览器加载,JavaScript 发 HTTP request 到 studio-api*.retaintive.ai
  3. 域名背后是 AWS API Gateway + Lambda(apps/api 跑的)
  4. API Lambda 验 token(Cognito JWT)、检查 store 权限、查 Neon / DDB,再返回 JSON

关键: apps/webapps/api 同 repo 不同 runtime。前端 build 失败 ≠ 后端 deploy 失败;后端 deploy 失败 ≠ 前端有问题。

详细数据流见 frontend.md Layer 3 数据流时序;部署细节见 frontend.md Layer 4 部署。


Repo 职责速查

收到任务时,先用这张表定位 repo,再读对应 repo 的 CLAUDE.md / README / 代码。

Repo核心功能(它对系统贡献什么)技术栈 / Runtime
ringcentralSubscriptionService系统唯一的电话/SMS 入口。RC 那边所有 webhook 都打到这里,贴上租户标签 + 路由到下游 SQS。没它,系统收不到任何电话事件Lambda + SQS
lead-tracking系统唯一的 Lead 入口(网页表单走邮箱通知)。每 5 分钟轮询 + 解析 + 4 张 Neon 表 + 1 张 DDB 原子写入。下游 task 是这里直接 create 的Lambda + IMAP + EventBridge
callytics-infrastructure整个后端业务大脑 — 5 个 processing Lambda + 7 AI prompt + 共享写入层(Task Orchestrator / Contact Writer 等)。所有 CDK 部署也在这Lambda + SQS + EventBridge + DDB + S3 + Neon + CDK
studio-website-monorepo/apps/web用户唯一看得到的东西 — Vue SPA。不连数据库,所有数据走 apps/apiVue 3 + Vite + Cloudflare Pages
studio-website-monorepo/apps/api前端专用 connector — 查 Neon / DDB 给前端返 JSON,验 Cognito JWT,做 store 权限 gateHono + AWS Lambda + API Gateway + Cognito
callytics-common全 stack schema SoT + 共享代码(Drizzle schema 24 张表 + Task Orchestrator / Contact Writer / Timeline Writer / Policy Guard)。改 schema 在这里改,其他 repo importTypeScript + Drizzle ORM
retaintive-studio-control-planeTenant identity SoT + Admin UI(control-plane.retaintive.ai)。V1 = IDENTITY ONLY,自己独立 Neon project。是未来 multi-tenant 路由的地基Bun + Drizzle + Neon + Cloudflare Worker + Wrangler

数据库和共享 schema

存储当前角色典型数据
Neon PostgreSQLPrimary SoT for business datacontacts, calls, messages, leads, tasks, contact_timeline, store_config
DynamoDBcall-analysis + LeadTracking + OAuth/config/legacycall-analysis, LeadTracking-v2, UserConnections, PhoneNumbers, Stores, config tables
S3文件和配置通话录音, MMS 附件, prompt 配置, Lambda Layer

跨 Repo 边界:最容易踩坑的地方

共享队列

ringcentralSubscriptionService 写入,callytics-infrastructure 消费。改队列名、region、payload shape 时必须同步两个 repo。

队列用途命名模板
transcribe queue通话转录入口call-analytics-{env}-transcribe-queue-{region}
message-processing queueSMS/VM 处理入口call-analytics-{env}-message-processing-queue-{region}
ai-analysis queue转录完成后的 AI 分析入口call-analytics-{env}-ai-analysis-queue-{region}
dailyBatchQueue.fifoper-call contact analysis fan-outFIFO queue

共享表和字段

表 / 数据写入方读取方
Neon callstranscribe-processor, ai-analysis-processorstudio-api, contacts-analyzer
Neon contactsai-analysis-processor, message-processor, contacts-analyzerstudio-api
Neon messagesmessage-processorstudio-api
Neon leadslead-trackingstudio-api, lead-processor
Neon tasks / contact_timeline from leadslead-processorstudio-api
DDB LeadTracking-v2lead-trackingstudio-api, ai-analysis-processor, contacts-analyzer
DDB call-analysisai-analysis-processorstudio-api, contacts-analyzer

新增共享资源优先用 SSM Parameter Store 或明确的 shared config,不要在多个 repo 硬编码同一字符串。


环境

环境API前端AWS Region
teststudio-api-test.retaintive.aiCloudflare Pages testus-west-2
prestudio-api-pre.retaintive.aiCloudflare Pages preus-east-2
prodstudio-api.retaintive.aistudio.retaintive.aius-east-1

深入阅读路线

如果你想理解对应维度
backend API 一次请求怎么经过 auth、route、service、SQL代码分层Backend 架构 Pattern
通话 / SMS / Lead / 每日报告各自的数据线路Pipeline后端架构
跨 repo 通话分析全流程Pipeline后端架构 Layer 2 / Layer 3a
5 条 pipeline 的完整流转和交叉依赖PipelinePipeline 全景分析
前端五层架构、路由、components、query hooks代码分层前端架构
每个 repo 的更详细技术栈repo-overview.md
字段级写入职责PipelineLambda 写入矩阵
多租户 store-level 隔离Multi-tenantStore-Level 数据隔离
多租户架构总览(V1 + Final + 方法论)Plane + Multi-tenantMulti-Tenant 架构总览