# 为什么仍然需要 Bridge 适配层

## 1. 结论先行

即使当前项目已经确认：

- 后续应使用 `leaudit` 原生 `AuditCtx`
- 后续不应继续由平台自己手写主流程编排
- 正式执行入口应收敛到 `AuditService.audit(ctx)`

**也仍然需要保留 Bridge / 适配层。**

原因不是因为不用原生 CTX，而恰恰是因为：

> **要正确使用原生 CTX，就更应该把它封装在 Bridge 里。**

也就是说，正确架构不是：

```text
平台层 -> 直接调用 leaudit AuditCtx / AuditService
```

而是：

```text
平台层 -> Bridge 适配层 -> leaudit AuditCtx / AuditService
```

---

## 2. 误区澄清

一个很容易出现的误区是：

- 既然 `leaudit` 已经有原生 `AuditCtx`
- 那平台直接调用它就好了
- Bridge 似乎没有必要

这个判断看起来简化了结构，但实际上会把平台和 `leaudit` 深度耦合起来，后续维护成本更高。

**真正应该取消的是：**

- 平台自己重写 7 阶段编排

**不应该取消的是：**

- 平台和 `leaudit` 之间的正式边界层

所以：

- **不要自己编排**
- **但要保留适配层**

---

## 3. 适配层到底在适配什么

Bridge 的本质，是把“平台世界”翻译成“引擎世界”，再把“引擎结果”翻译回“平台世界”。

## 3.1 平台世界

平台里实际关心的是这些对象：

- `document_id`
- `document_file_id`
- `rule_set_id`
- `rule_version_id`
- `oss_url`
- `run_id`
- 用户触发信息
- 权限信息
- 数据库记录
- 前端 DTO / VO

## 3.2 引擎世界

`leaudit` 原生执行关心的是这些对象：

- `file_path`
- `rules_file`
- `AuditServices`
- `AuditConfig`
- `AuditCtx`
- `AuditService.audit(ctx)`

这两套概念体系并不相同，因此天然需要一层转换。

---

## 4. 为什么不能让平台层直接碰 leaudit 原生对象

## 4.1 会导致架构边界失守

如果 Controller / Service / Model 层直接构造 `AuditCtx`，那就意味着：

- 平台业务代码开始直接依赖 `leaudit`
- `leaudit` 的内部概念会渗透到整个项目
- 后面任何原生字段调整都会扩散到平台层

这会破坏当前项目一直强调的边界原则：

- 平台层不直接感知 `leaudit` 内核细节
- `leaudit_bridge/` 是唯一正式桥接层

---

## 4.2 会让平台逻辑和引擎逻辑搅在一起

平台侧还必须处理这些事情：

- 文档文件从哪里取
- OSS 文件如何下载
- 规则版本从哪里查
- run 如何创建
- run 如何更新状态
- 结果如何写回 `leaudit_*` 表
- 前端如何查询结果

这些都不是 `leaudit` 原生 CTX 的职责。

如果平台层直接碰 `AuditCtx`，这些平台职责和引擎职责就会混在同一个 service 里，结构会越来越乱。

---

## 4.3 会让未来升级风险更大

如果以后 `leaudit` 升级：

- `AuditCtx` 字段变更
- `AuditService` 签名调整
- `AuditServices` 装配方式变化
- `AuditConfig` 配置项增加

那么：

- 如果只有 bridge 感知这些对象，改动范围很小
- 如果平台层很多地方直接依赖这些对象，改动会扩散全项目

因此，适配层的价值就在于：

> 把 `leaudit` 变化锁死在边界层里。

---

## 5. Bridge 的正确职责

确认使用原生 CTX 后，Bridge 的职责应该重新定义为：

## 5.1 输入适配

- 根据 `document_id` 找到待执行文档
- 根据 `document_file_id` 找到文件真源
- 如有需要，从 OSS 下载文档到本地临时路径
- 根据 `type_id` / `rule_type_binding` 找到本次评查规则版本
- 从 OSS 下载规则 YAML
- 解析出 `RulesFile`

## 5.2 运行装配

- 创建 `AuditServices`
- 创建 `AuditConfig`
- 创建原生 `AuditCtx`
- 调用 `AuditService.audit(ctx)`

## 5.3 输出适配

- 从最终 `ctx` 读取：
  - `normalized_doc`
  - `extraction`
  - `phase`
  - `evaluation`
  - `fallback_tasks`
  - `timing`
- 写入：
  - `leaudit_audit_runs`
  - `leaudit_rule_results`
  - `leaudit_field_results`
  - `leaudit_artifacts`
  - `leaudit_run_metrics`
  - `leaudit_run_errors`

## 5.4 边界保护

- 平台 Controller / Service 不直接 import `leaudit.services.*`
- 只有 `leaudit_bridge/` 感知原生 `AuditCtx`、`AuditService`、`AuditServices`

---

## 6. 三层结构图

推荐的结构应该是三层，而不是两层：

```text
┌────────────────────────────────────────────┐
│                平台层                      │
│ Controller / Service / Model / API / DB    │
│ 文档、规则、权限、任务、结果查询           │
└──────────────────┬─────────────────────────┘
                   │
                   ▼
┌────────────────────────────────────────────┐
│             Bridge 适配层                  │
│ file resolve / rules resolve / ctx build    │
│ AuditServices / AuditConfig / AuditCtx      │
│ persist ctx outputs to leaudit_*            │
└──────────────────┬─────────────────────────┘
                   │
                   ▼
┌────────────────────────────────────────────┐
│             leaudit 原生内核层             │
│ AuditCtx / AuditService / Evaluation /      │
│ Extraction / Rescue / DSL loader            │
└────────────────────────────────────────────┘
```

这个结构的关键点是：

- 平台层不直接碰 `leaudit` 细节
- `leaudit` 不直接感知平台数据库和 OSS
- 所有翻译工作都集中在 Bridge

---

## 7. 为什么这比“平台直接调原生 CTX”更稳

### 优势 1：边界清晰

- 平台只管业务
- `leaudit` 只管评查
- Bridge 只管适配

### 优势 2：变化可控

- `leaudit` 升级时改 Bridge
- 平台结构基本不动

### 优势 3：便于替换

将来如果评查引擎变化：

- 平台不需要全面改造
- 只需替换适配层实现

### 优势 4：测试更容易

Bridge 可以单独测试：

- 是否正确组装 `AuditCtx`
- 是否正确调用 `AuditService.audit(ctx)`
- 是否正确写回平台结果表

---

## 8. 对当前项目的直接要求

既然已经确认：

- 必须使用原生 `AuditCtx`
- 不能继续自己编排主流程

那么当前项目应该同步修正为：

### 不再推荐的方向

- 在 `fastapi_modules/fastapi_leaudit/leaudit_bridge/pipeline.py` 中继续手写 7 阶段流程
- 在平台侧继续直接串联：
  - OCR
  - Extract
  - Phase
  - Evaluate
  - Rescue

### 推荐的方向

- `pipeline.py` 改造成薄包装器
- 新增 `audit_ctx_builder.py`
- 新增 `audit_service_factory.py`
- 由 bridge 统一：
  - build ctx
  - run audit
  - persist result

---

## 9. 最终结论

确认使用原生 `AuditCtx` 之后，不是 Bridge 就没用了，反而说明：

> **Bridge 不该负责重写编排，但必须负责原生编排的接入适配。**

所以最终应该坚持这条原则：

- **主流程执行：交给 `leaudit` 原生 `AuditService.audit(ctx)`**
- **平台边界控制：交给 `leaudit_bridge/`**

这才是当前项目最稳妥、最可维护的长期方案。
