> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# 系统架构总览

> **读者**：新成员、AI Agent、需要快速判断“这个需求应该改哪个 repo”的人。
>
> **本页只回答三件事**：
>
> 1. retaintive 的系统由哪些 repo / runtime / 数据存储组成。
> 2. 数据从外部进入系统后，按什么路径被处理并展示给用户。
> 3. 哪些概念容易混在一起，应该拆开理解。
>
> 具体 backend 代码分层、auth chain、API request lifecycle 见 [Backend 架构 Pattern](/system-design/backend-patterns.md)。后端 pipeline / Lambda / AI prompt 全景见 [2-backend.md](/architecture/2-backend.md)。前端 5 层架构见 [1-frontend.md](/architecture/1-frontend.md)。

***

## 一句话定位

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

核心链路：

```text
客户打电话 / 发短信 / 填表
→ 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 内部的子问题：

<object type="image/svg+xml" data="/images/arch-concept-nav.svg" style="max-width: 800px; width: 100%;">架构概念导航图 — Plane 分层与 Data Plane 内部子问题的关系</object>

### 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 cache     | Lambda 进来,**查** `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](/architecture/2-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](/system-design/multi-tenant/overview.md)

详细文档: [Multi-Tenant 总览](/system-design/multi-tenant/overview.md) · [Pipeline 全景分析](/system-design/pipeline-architecture-analysis.md) · [Backend 架构 Pattern](/system-design/backend-patterns.md) · [Store-Level 隔离](/system-design/store-level-isolation.md)

***

## 系统全景（Level 1）

### 7 个核心 repo,各管什么

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

| Repo                                | 是什么                                                                                                                                  | 管什么维度                                              | 不是                                                                                                                      |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `studio-website-monorepo/apps/web`  | Vue 3 SPA,浏览器里跑,静态部署 Cloudflare Pages                                                                                                | Interface 层(用户界面)                                  | 不直接连数据库,不跑 backend 业务逻辑                                                                                                 |
| `studio-website-monorepo/apps/api`  | Hono app 跑在 AWS Lambda + API Gateway,前端**专用** API                                                                                    | Interface 层(前端 API connector)                      | **不是**通话转录 / AI 分析 pipeline。它只**读** Neon / DDB 给前端返 JSON                                                                |
| `callytics-infrastructure/lambda/*` | 后台 processing Lambda(transcribe / ai-analysis / contacts-analyzer / message-processor / lead-processor),消费 SQS / EventBridge         | Data 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` 它                                                                      |
| `ringcentralSubscriptionService`    | RingCentral webhook 接收 + OAuth token 管理 + 订阅生命周期(创建/续期),路由电话事件到下游 SQS                                                                | **Ingress** + Management Plane(OAuth 管理)           | 不做转录,不做 AI,不写业务表(只贴标签 + 路由)                                                                                             |
| `lead-tracking`                     | IMAP 邮箱轮询(每 5 分钟),解析潜在客户表单邮件,**原子** `db.batch()` 写 **4 张 Neon 表** + 1 张 DDB                                                          | **Ingress** + Data Plane(Lead 入口的 source of truth) | 不消费 SQS。完全自主拉(poller)                                                                                                   |
| `retaintive-studio-control-plane`   | Tenant identity SoT(自己 Neon project + Admin UI deployed `control-plane.retaintive.ai`)。V1 = IDENTITY ONLY                            | **Control 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/web` 和 `apps/api` 同 repo 不同 runtime。前端 build 失败 ≠ 后端 deploy 失败;后端 deploy 失败 ≠ 前端有问题。

详细数据流见 [frontend.md](/architecture/1-frontend.md) Layer 3 数据流时序;部署细节见 [frontend.md](/architecture/1-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/api                                                                                                            | Vue 3 + Vite + Cloudflare Pages                     |
| `studio-website-monorepo/apps/api` | 前端**专用 connector** — 查 Neon / DDB 给前端返 JSON,验 Cognito JWT,做 store 权限 gate                                                                                | Hono + AWS Lambda + API Gateway + Cognito           |
| `callytics-common`                 | 全 stack **schema SoT + 共享代码**(Drizzle schema 24 张表 + Task Orchestrator / Contact Writer / Timeline Writer / Policy Guard)。改 schema 在这里改,其他 repo `import` | TypeScript + Drizzle ORM                            |
| `retaintive-studio-control-plane`  | **Tenant identity SoT** + Admin UI(`control-plane.retaintive.ai`)。V1 = IDENTITY ONLY,自己独立 Neon project。是未来 multi-tenant 路由的地基                            | Bun + Drizzle + Neon + Cloudflare Worker + Wrangler |

***

### 数据库和共享 schema

```mermaid
flowchart LR
    common["callytics-common"]
    api["apps/api"]
    infra["callytics-infra"]
    neon["Neon PostgreSQL"]
    ddb["DynamoDB"]
    s3["S3"]

    common -. types .-> api
    common -. types .-> infra
    api -->|reads| neon
    api -->|legacy reads| ddb
    infra -->|writes| neon
    infra -->|legacy dual-write / config| ddb
    infra --> s3
```

| 存储                  | 当前角色                                               | 典型数据                                                                                 |
| ------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------ |
| **Neon PostgreSQL** | **Primary SoT** for business data                  | contacts, calls, messages, leads, tasks, contact\_timeline, store\_config            |
| **DynamoDB**        | call-analysis + LeadTracking + OAuth/config/legacy | call-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 queue | SMS/VM 处理入口                       | `call-analytics-{env}-message-processing-queue-{region}` |
| ai-analysis queue        | 转录完成后的 AI 分析入口                    | `call-analytics-{env}-ai-analysis-queue-{region}`        |
| dailyBatchQueue.fifo     | per-call contact analysis fan-out | FIFO queue                                               |

### 共享表和字段

| 表 / 数据                                       | 写入方                                                         | 读取方                                                  |
| -------------------------------------------- | ----------------------------------------------------------- | ---------------------------------------------------- |
| Neon `calls`                                 | transcribe-processor, ai-analysis-processor                 | studio-api, contacts-analyzer                        |
| Neon `contacts`                              | ai-analysis-processor, message-processor, contacts-analyzer | studio-api                                           |
| Neon `messages`                              | message-processor                                           | studio-api                                           |
| Neon `leads`                                 | lead-tracking                                               | studio-api, lead-processor                           |
| Neon `tasks` / `contact_timeline` from leads | lead-processor                                              | studio-api                                           |
| DDB `LeadTracking-v2`                        | lead-tracking                                               | studio-api, ai-analysis-processor, contacts-analyzer |
| DDB `call-analysis`                          | ai-analysis-processor                                       | studio-api, contacts-analyzer                        |

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

***

### 环境

| 环境   | API                             | 前端                     | AWS Region  |
| ---- | ------------------------------- | ---------------------- | ----------- |
| test | `studio-api-test.retaintive.ai` | Cloudflare Pages test  | `us-west-2` |
| pre  | `studio-api-pre.retaintive.ai`  | Cloudflare Pages pre   | `us-east-2` |
| prod | `studio-api.retaintive.ai`      | `studio.retaintive.ai` | `us-east-1` |

***

## 深入阅读路线

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