# 后端服务架构与本地试运行方案

更新时间：2026-06-03  
阶段：一期本地试运行  
目标：先在本机稳定运行，方便持续调整代码组成；稳定后再按用户要求部署云端。

---

## 0. 当前执行口径

本阶段先不做云端部署，也不急着把所有 Prisma 表完整落库。当前目标是：

1. 把机器人优先的后端架构补齐；
2. 让本地有一个可运行、可调用、可迭代的服务；
3. 先用本地 JSON 持久化草稿和测试提交记录，保留后续切换 PostgreSQL / Prisma 的接口边界；
4. 让财务机器人未来可以先调用本地服务进行规则读取、字段校验、草稿生成、预览和模拟提交；
5. 等业务规则稳定后，再迁移到正式数据库和云端部署。

---

## 1. 一期本地后端定位

```text
财务机器人 / Hermes / Feishu Bot
  ↓ MCP-like tool call / HTTP API
本地后端服务 localhost:8787
  ↓
RuleService          读取入库规则
ResolverService      解析主体、项目
ValidatorService     校验草稿字段和风险
DraftStore           保存 intake_draft
PreviewBuilder       生成中文确认摘要
CommitService        本地模拟提交事实事件
  ↓
本地 JSON runtime store
```

本地服务不是最终云端版本，但接口形态尽量按最终后端设计，便于后续迁移。

---

## 2. 服务模块

### 2.1 `RuleService`

来源：

```text
docs/intake_rules_一期草案.json
```

职责：

- 返回某个 `intent` 的规则；
- 返回所有支持的 `intent`；
- 给 `finance_get_intake_rules`、`/api/intake/rules` 使用。

### 2.2 `ResolverService`

来源：

```text
backend/data/seed/subjects.json
backend/data/seed/projects.json
```

职责：

- 把用户口述的主体名称解析为 `subject`；
- 把用户口述的项目名称解析为 `project`；
- 如果无具体项目但有主体，可返回主体基础经营项目候选；
- 未来切换数据库后，仍保留这个服务边界。

### 2.3 `ValidatorService`

来源：

```text
docs/intake_rules_一期草案.json
```

职责：

- 按 intent 的阻塞字段检查草稿；
- 返回 `ok`、`missing_fields`、`warnings`、`risk_flags`；
- 缺字段时返回中文追问句，不只返回技术错误。

### 2.4 `DraftStore`

来源：

```text
backend/data/runtime/intake_drafts.json
```

职责：

- 创建 `intake_draft`；
- 查询草稿；
- 更新草稿状态；
- 保存校验结果、预览摘要、风险标记；
- 用 `idempotency_key` 防止机器人重复写入。

### 2.5 `PreviewBuilder`

职责：

- 生成用户确认/审批前摘要；
- 明确本次会创建什么、暂时不会创建什么；
- 输出风险提示和缺失字段。

### 2.6 `CommitService`

本地试运行阶段职责：

- 不直接连接真实财务数据库；
- 将已校验草稿转成一条本地模拟提交事件；
- 写入：

```text
backend/data/runtime/committed_records.json
```

未来迁移阶段：

- 替换为 Prisma transaction；
- 按 intent 创建正式事实表记录；
- 保留幂等、审计、月结锁定检查。

---

## 3. HTTP API

### 3.1 健康检查

```http
GET /health
```

返回服务状态、版本、当前支持的 intent 数量。

### 3.2 规则读取

```http
GET /api/intake/rules?intent=record_reimbursement
```

返回某个 intent 的完整入库规则。

### 3.3 草稿校验

```http
POST /api/intake/validate
```

请求：

```json
{
  "intent": "record_reimbursement",
  "draft": {}
}
```

返回：

```json
{
  "ok": false,
  "missing_fields": [
    {
      "field": "items[].amount",
      "level": "blocking",
      "question": "每一笔分别是多少钱？"
    }
  ],
  "warnings": [],
  "normalized_draft": {}
}
```

### 3.4 创建草稿

```http
POST /api/intake/drafts
```

创建并保存 intake draft。

### 3.5 查询草稿

```http
GET /api/intake/drafts/:id
```

返回本地保存的草稿。

### 3.6 预览草稿

```http
POST /api/intake/preview
```

返回中文摘要、风险提示、会创建/暂不创建的对象。

### 3.7 模拟提交

```http
POST /api/intake/drafts/:id/commit
```

本地阶段只写入模拟提交事件；不连接真实数据库。

### 3.8 主体/项目解析

```http
POST /api/subjects/resolve
POST /api/projects/resolve
```

供机器人把用户自然语言解析成候选主体/项目。

---

## 4. MCP-like 调用入口

本地试运行阶段提供一个简单 MCP-like HTTP 入口：

```http
GET  /mcp/tools
POST /mcp/call
```

请求示例：

```json
{
  "tool": "finance_get_intake_rules",
  "arguments": {
    "intent": "record_reimbursement"
  }
}
```

后续真正做 MCP Server 时，可以复用同一批 service，而不是重写业务逻辑。

---

## 5. 本地数据边界

本地运行产生的数据放在：

```text
backend/data/runtime/
```

包括：

```text
intake_drafts.json
committed_records.json
```

这些只是本地试运行数据，不是最终正式账本。

---

## 6. 启动方式

```bash
cd backend
npm start
```

默认端口：

```text
127.0.0.1:8787
```

健康检查：

```bash
curl http://127.0.0.1:8787/health
```

端到端自测：

```bash
npm test
```

---

## 7. 下一阶段迁移方向

等本地规则稳定后，再做：

1. 接 PostgreSQL；
2. 用 Prisma schema 生成正式 migration；
3. 把 `CommitService` 从 JSON 模拟提交改成 Prisma transaction；
4. 增加飞书审批回调边界；
5. 增加机器人正式 MCP Server；
6. 再部署云端。

当前阶段先保持本地可调、可改、可试运行。
