# H2 修复：FDW → 直连 ETL 架构统一

| 维度 | 内容 |
|------|------|
| 日期 | 2026-03-20 |
| 关联问题 | RNS1 审计报告 H2（AI 自主决策架构级修改） |
| 决策方式 | 用户确认方案 A（全部统一直连 ETL）后执行 |

## 背景

RNS1.1 期间，AI 自行将 `fdw_queries.py`（47 个函数）从 FDW 外部表改为直连 ETL 库，
但其他 4 个文件仍使用旧 FDW 模式（`fdw_etl.*`），造成架构不一致。

核心技术问题：`postgres_fdw` 不传递自定义 GUC 参数（`app.current_site_id`），
旧 FDW 模式下 RLS 视图的门店隔离实际失效。

## 改造范围

| 文件 | 改造点 | 风险等级 |
|------|--------|----------|
| `matching.py` | `fdw_etl.v_dim_assistant/v_dim_staff/v_dim_staff_ex` → `app.v_*`；`scd2_is_current = TRUE` → `= 1`；连接改为 `_fdw_context(None, site_id)` | 低 |
| `task_generator.py` | 3 处 `fdw_etl.v_dws_member_winback/newconv/relation_index` → `app.v_*`；WBI/NCI 全表扫描，RLS 是唯一门店过滤 | 高 |
| `recall_detector.py` | `fdw_etl.v_dwd_assistant_service_log` → `app.v_*`；列名映射：`assistant_id→site_assistant_id`、`member_id→tenant_member_id`、`service_time→create_time` | 低 |
| `task_manager.py` | 4 处：`v_dim_member`（`member_name→nickname`、`member_phone→mobile`）+ 3 处 RS 指数 | 中 |

## 列名映射速查

| FDW 外部表列名 | RLS 视图实际列名 | 涉及视图 |
|---|---|---|
| `assistant_id` | `site_assistant_id` | `v_dwd_assistant_service_log` |
| `member_id` | `tenant_member_id` | `v_dwd_assistant_service_log` |
| `service_time` | `create_time` | `v_dwd_assistant_service_log` |
| `member_name` | `nickname` | `v_dim_member` |
| `member_phone` | `mobile` | `v_dim_member` |
| `scd2_is_current = TRUE` | `scd2_is_current = 1` | `v_dim_assistant`、`v_dim_staff`、`v_dim_staff_ex` |

## 验证结果

- MCP 验证 ✅：7 个改造后的 SQL 查询在 `test_etl_feiqiu` 上执行成功
- 语法检查 ✅：4 个文件零 diagnostics
- E2E 测试 ✅：`test_e2e_board.py` 25 passed in 121.26s
- `performance_service.py` 确认无需改造（已使用 `_fdw_context`）

## 未变更项

- FDW 外部表 DDL 暂不清理（用户确认保留）
- `fdw_queries.py` 无需改动（已在 RNS1.1 中完成改造）

## 回滚方案

将 4 个文件中的 `_fdw_context` 调用改回 `get_connection()` + `fdw_etl.*` 查询，
恢复 FDW 外部表列名。注意：回滚后 RLS 门店隔离将再次失效。
