# 需求文档：小程序数据库基础设施层（miniapp-db-foundation）

## 简介

P1 基础设施层是整个小程序系统的第一个 SPEC，无前置依赖，是所有后续 SPEC 的硬依赖。本 SPEC 负责在业务库 `test_zqyy_app` 中建立清晰的 Schema 划分（`auth` + `biz`），在 ETL 库 `test_etl_feiqiu` 中为数据依赖矩阵列出的所有 DWD/DWS 表创建 RLS 视图（按 `site_id` 隔离），并通过 `postgres_fdw` 将 RLS 视图映射为业务库的外部表，使后端无需直连 ETL 库即可读取汇总/维度数据。

## 术语表

- **Schema_Manager**：负责在 PostgreSQL 数据库中创建和管理 Schema、权限配置的迁移脚本系统
- **RLS_View_Layer**：在 `test_etl_feiqiu.app` Schema 中创建的一组视图，通过 `current_setting('app.current_site_id')` 按 `site_id` 过滤数据，实现行级安全隔离
- **FDW_Bridge**：通过 `postgres_fdw` 扩展在 `test_zqyy_app.fdw_etl` Schema 中创建的外部表集合，只读映射 ETL 库 `app` Schema 的 RLS 视图
- **Migration_Script**：存放在 `db/zqyy_app/migrations/` 或 `db/etl_feiqiu/migrations/` 中的纯 SQL 迁移脚本，以日期前缀命名
- **Validation_Script**：用于验证数据库对象是否正确创建、权限是否配置正确、数据是否可查询的 Python 脚本
- **site_id**：门店标识符，类型为 `BIGINT`，用于多门店数据隔离
- **app_reader**：ETL 库侧的只读角色，供 FDW 用户映射使用
- **app_user**：业务库侧的应用连接角色，通过 FDW 读取 ETL 数据

## 需求

### 需求 1：业务库 Schema 划分与权限配置

**用户故事：** 作为后端开发者，我需要 `test_zqyy_app` 中有清晰的 Schema 划分（`auth` + `biz`），以便按功能组织业务表。

#### 验收标准

1. WHEN Migration_Script 执行完成, THE Schema_Manager SHALL 在 `test_zqyy_app` 中创建 `auth` Schema
2. WHEN Migration_Script 执行完成, THE Schema_Manager SHALL 在 `test_zqyy_app` 中创建 `biz` Schema
3. WHEN `auth` Schema 创建完成, THE Schema_Manager SHALL 授予 `app_user` 角色对 `auth` Schema 的 USAGE 权限和对其中所有表的 SELECT、INSERT、UPDATE、DELETE 权限
4. WHEN `biz` Schema 创建完成, THE Schema_Manager SHALL 授予 `app_user` 角色对 `biz` Schema 的 USAGE 权限和对其中所有表的 SELECT、INSERT、UPDATE、DELETE 权限
5. WHEN 新表在 `auth` 或 `biz` Schema 中创建, THE Schema_Manager SHALL 通过 ALTER DEFAULT PRIVILEGES 自动授予 `app_user` 角色相应权限
6. THE Migration_Script SHALL 保留 `public` Schema 中现有的系统管理表（`admin_users`、`roles`、`permissions` 等）不受影响

### 需求 2：ETL 库 RLS 视图层创建

**用户故事：** 作为系统管理员，我需要 RLS 视图按 `site_id` 隔离数据，以便多门店数据安全。

#### 验收标准

1. WHEN Migration_Script 执行完成, THE Schema_Manager SHALL 在 `test_etl_feiqiu` 中创建 `app` Schema（如不存在）
2. WHEN `app` Schema 创建完成, THE RLS_View_Layer SHALL 为数据依赖矩阵中列出的每张 DWD 表创建对应的 RLS 视图（共 11 张：`dim_member`、`dim_assistant`、`dim_member_card_account`、`dim_table`、`dwd_settlement_head`、`dwd_table_fee_log`、`dwd_assistant_service_log`、`dwd_recharge_order`、`dwd_store_goods_sale`、`dim_staff`、`dim_staff_ex`）
3. WHEN `app` Schema 创建完成, THE RLS_View_Layer SHALL 为数据依赖矩阵中列出的每张 DWS 表创建对应的 RLS 视图（共 24 张，包含 `dws_*` 和 `cfg_*` 表）
4. THE RLS_View_Layer 中每个视图 SHALL 包含 `WHERE site_id = current_setting('app.current_site_id')::bigint` 过滤条件
5. WHEN 设置 `app.current_site_id` 为某门店 ID 后查询 RLS 视图, THE RLS_View_Layer SHALL 仅返回该门店的数据
6. WHEN 未设置 `app.current_site_id` 时查询 RLS 视图, THE RLS_View_Layer SHALL 抛出错误而非返回全部数据
7. THE Schema_Manager SHALL 授予 `app_reader` 角色对 `app` Schema 的 USAGE 权限和对其中所有视图的 SELECT 权限
8. THE RLS_View_Layer SHALL 为 P2 待建表（`dws_member_spending_power_index`、`dws_assistant_order_contribution`）在迁移脚本中以注释形式预留位置

### 需求 3：FDW 外部表映射

**用户故事：** 作为后端开发者，我需要通过 FDW 从 `test_zqyy_app` 读取 ETL 库的 DWS/DWD 数据，以便小程序页面展示 ETL 计算结果。

#### 验收标准

1. WHEN Migration_Script 执行完成, THE FDW_Bridge SHALL 在 `test_zqyy_app` 中安装 `postgres_fdw` 扩展
2. WHEN `postgres_fdw` 扩展安装完成, THE FDW_Bridge SHALL 创建指向 `test_etl_feiqiu` 的外部服务器 `test_etl_feiqiu_server`
3. WHEN 外部服务器创建完成, THE FDW_Bridge SHALL 创建 `app_user` 到 `app_reader` 的用户映射
4. WHEN 用户映射创建完成, THE FDW_Bridge SHALL 在 `fdw_etl` Schema 中通过 `IMPORT FOREIGN SCHEMA app` 导入所有外部表
5. WHEN 外部表导入完成, THE FDW_Bridge SHALL 对 `fdw_etl` Schema 中的每张外部表执行 `SELECT` 查询验证可读性
6. WHEN 外部表查询成功, THE FDW_Bridge 返回的数据 SHALL 与 ETL 库 `app` Schema 中对应 RLS 视图的数据一致
7. THE FDW_Bridge SHALL 授予 `app_user` 角色对 `fdw_etl` Schema 的 USAGE 权限和对其中所有外部表的 SELECT 权限

### 需求 4：迁移脚本管理

**用户故事：** 作为后端开发者，我需要所有数据库变更都有对应的迁移脚本，以便变更可追溯、可重放、可回滚。

#### 验收标准

1. THE Migration_Script SHALL 将 ETL 库变更（RLS 视图创建、`app` Schema 权限）存放在 `db/etl_feiqiu/migrations/` 目录中
2. THE Migration_Script SHALL 将业务库变更（Schema 创建、FDW 配置）存放在 `db/zqyy_app/migrations/` 目录中
3. THE Migration_Script SHALL 使用日期前缀命名（格式：`YYYY-MM-DD__<描述>.sql`）
4. THE Migration_Script SHALL 在每个脚本中包含回滚语句（以注释形式）
5. THE Migration_Script SHALL 使用 `IF NOT EXISTS` / `OR REPLACE` 等幂等语法，确保重复执行不会报错
6. THE Migration_Script SHALL 使用 UTF-8 编码，纯 SQL（非 ORM）

### 需求 5：端到端验证

**用户故事：** 作为后端开发者，我需要一个自动化验证脚本，确认所有数据库对象正确创建且数据可访问。

#### 验收标准

1. WHEN Validation_Script 执行时, THE Validation_Script SHALL 检查 `test_zqyy_app` 中 `auth` 和 `biz` Schema 是否存在
2. WHEN Validation_Script 执行时, THE Validation_Script SHALL 检查 `test_etl_feiqiu.app` Schema 中所有 RLS 视图是否存在
3. WHEN Validation_Script 执行时, THE Validation_Script SHALL 检查 `test_zqyy_app.fdw_etl` 中所有外部表是否存在
4. WHEN Validation_Script 执行时, THE Validation_Script SHALL 对每张外部表执行 `SELECT count(*)` 验证可查询性
5. WHEN Validation_Script 执行时, THE Validation_Script SHALL 设置 `app.current_site_id` 后验证 RLS 视图正确过滤数据
6. WHEN Validation_Script 执行时, THE Validation_Script SHALL 验证 `app_user` 和 `app_reader` 角色的权限配置正确
7. WHEN 验证发现异常, THE Validation_Script SHALL 输出具体的失败项和错误信息
8. THE Validation_Script SHALL 从 `.env` 加载数据库连接参数（`PG_DSN`、`APP_DB_DSN`），缺失时立即报错终止
