Files
group_fqcd_jr/docs/28-场外与推广域数据表登记.md
T
lzf_0626 36c7a9d8d2 文档:审查报告入库 + 全量校对补注
## 新入库(`docs/演示用/`)

- `代码库全面审查报告-2026-09-14.md`
- `代码修改方案-2026-09-14.md`
- `记忆系统排查报告-2026-09-14.md`
- `记忆系统修复文档-2026-09-14.md`
- `文档一致性审计报告-2026-09-14.md`
- `多Worker接入方案-2026-09-14.md`

## 全量校对(32 个既有文档 + `AGENTS.md`)

跨 39 个文件、**1125 insertions / 148 deletions**。

⚠️ **这批改动同样不是本次会话写的**。我抽样核对过性质:是**实质内容补充**而不是
格式/换行转换。例如 `docs/44-演示流程.md` 新增两条"2026-09-14 补注":

- `启动金融Agent平台.bat` 只在**桌面**上,仓库里只有 `启动平台.bat` 这一份
  (两份由同一个 `tools/make_launcher_bat.py` 产出,改完 `start.ps1` 重跑它一起更新);
- `advisor_t`(9020) 与 `offsite_t`(9006) **不在 `tools/seed_test_rbac.py` 的演示用户里**
  (那里只有 `cust_t`/`risk_t`/`admin_t`/`review_t` 四个),由 `grant_*.py` 系列创建,
  **重跑种子不会重建它们** —— 换机器时这两个账号登录失败,要先查 `sys_user` 有没有这两行,
  而不是查密码。

这两条都是对的地方,与我这一路踩到的现象一致(我确实用到了 `advisor_t`/`offsite_t`)。

**我没有逐字审阅全部 39 个文件**,只抽样确认了改动性质与规模。若其中有需要复核的段落,
请指明文件,我逐处核对。
2026-09-14 20:36:00 +08:00

159 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 场外与推广域数据表登记(`docs/00` 基线的域外补充)
> **用途**:`docs/00-新数据库基线设计.md` 冻结的是**场内基金模拟交易域**的基线(不可变,规则 1)。
> 同事那条线(袁聪)合并进来的 **17 张表属场外基金运营域与推广域**,**不进 `docs/00`**,
> 由本文单独登记,避免"基线"这个概念因为塞入独立域而失效。
>
> **维护约定**:新增/删除这两个域的表时**必须同步本文**;本文是「**场外/推广这 17 张**从哪来」的唯一答案。
>
> ⚠️ **表数口径(2026-09-14 更正)**:本文此前写作
> `场内 51 + 场外/推广 17 = 68(共 69 张含 alembic_version)`,
> 那是**投顾域尚未并入时**的口径。当前全库已为:
>
> ```
> 场内 51(docs/00) + 场外/推广 17(本文) + 投顾 21(登记文档待补) = 89 张业务表
> (另加 alembic_version,库内共 90 张)
> ```
>
> **本文只负责场外/推广那 17 张**(10 张 `offsite_*` + 7 张 `promotion_*`),
> 逐表登记内容本身**未变、无缺陷**;投顾 21 张不在本文范围,其登记文档待补。
> 核验一律以 `python tools/audit_schema.py` 的实时输出为准。
---
## 1. 为什么另立文档(架构师裁决,2026-09-11)
依据 `AGENTS.md` 规则 8:
> 当前系统业务功能只针对场内基金模拟交易;**场外基金运营流程独立,不得写入场内交易表**。
⇒ 场外与推广是**独立域**。把它们塞进 `docs/00` 会让"基线"从"场内交易域的冻结定义"
变成"当前全部表",下次有人拿 `docs/00` 当依据时会错。因此:
| 文档 | 职责 |
|---|---|
| `docs/00-新数据库基线设计.md` | **场内交易域**基线(不可变,51 张) |
| **本文** | 场外/推广域(17 张)的登记与来源 |
| `docs/08-数据库结构审计基线.md` | 审计口径:场内 51 + 场外/推广 17 = 68 |
| `tools/audit_schema.py` | 期望值同为 68(已生效,见 §4) |
---
## 2. 17 张表逐表登记
### 2.1 场外基金运营域(`offsite_*`,10 张)
| 表名 | 来源迁移 | 建立它的提交意图 |
|---|---|---|
| `offsite_fund_mail` | `20260910_offsite_fund` | 场外申购邮件记录(运营入口) |
| `offsite_fund_attachment` | `20260910_offsite_fund` | 邮件附件(**该域唯一有数据的表,见 §3**) |
| `offsite_fund_document` | `20260910_offsite_fund` | 识别后的业务单据 |
| `offsite_execution_plan_task` | `20260910_offsite_fund` | 执行计划任务 |
| `offsite_rule_result` | `20260910_offsite_fund` | 规则校验结果 |
| `offsite_query_record` | `20260910_offsite_fund` | NL2SQL 查询记录 |
| `offsite_notification` | `20260910_offsite_fund` | 对外通知 |
| `offsite_mail_cursor` | `20260910_offsite_worker` | 邮件 Worker 的游标状态 |
| `offsite_recognition_attempt` | `20260910_offsite_recognition_attempt` | 识别尝试追踪(OCR/LLM 各一次尝试) |
| `offsite_field_correction` | `20260911_offsite_field_correction` | 人工字段纠正记录 |
### 2.2 推广域(`promotion_*`,7 张)
| 表名 | 来源迁移 | 用途 |
|---|---|---|
| `promotion_material_task` | `20260910_promotion_material` | 推广素材任务(主表) |
| `promotion_material_version` | `20260910_promotion_material` | 素材版本 |
| `promotion_input_snapshot` | `20260910_promotion_material` | 生成输入快照(可复现) |
| `promotion_attachment` | `20260910_promotion_material` | 素材附件(海报/PPT) |
| `promotion_compliance_check` | `20260910_promotion_material` | 合规校验结果 |
| `promotion_review_record` | `20260910_promotion_material` | 审核记录 |
| `promotion_delivery_record` | `20260910_promotion_material` | 投递记录 |
### 2.3 迁移文件清单(11 个,含 6 个 merge/辅助)
```
建表相关:20260910_offsite_fund / _offsite_worker / _offsite_recognition_attempt /
_promotion_material / _promotion_poster / 20260911_offsite_field_correction
合并链: 20260910_merge_heads / 20260911_merge_review_separation /
20260911_merge_risk_heads(当前 head)
其他: 20260910_offsite_worker_identity / 20260911_drop_review_separation
```
> ⚠️ **两个环境都踩过的坑**:本库曾处于"`alembic_version` 已指向同事的 revision,
> 但 `offsite_*`/`promotion_*` 表一张都没有"的状态(**版本号跑了、表没建**);
> 架构师那边则是"表没建、版本号也没跑"。**两种坏状态都靠 `alembic upgrade heads` 收敛。**
---
## 3. 当前数据量(2026-09-11 实测)
| 表 | 行数 |
|---|---|
`offsite_fund_attachment` | **60** |
其余 16 张 | **0** |
> 说明:只有附件表有数据(同事调试/演示时落盘的附件)。**这不是"该域已在生产运行"的证据**,
> 也不代表其它表可以删——**禁止删表**(规则 3)。
---
## 4. 跨域边界核对(规则 8 的两向检查)
### 4.1 场内代码是否引用这 17 张表 → **否** ✅
`app/` 下搜 `offsite_|promotion_` 只有 12 处命中,**全部是 `app/core/config.py` 里的环境变量名**
(`offsite_mailbox`、`offsite_allowed_senders` 等),**没有任何 SQL/ORM 级引用**。
场内模型(`app/model/fund.py` 等)与只读契约(`FUND_TABLES`)都只覆盖 `fin_*`。
### 4.2 场外代码是否写场内交易表 → **否** ✅
在 `app/service/offsite*.py` 与 `app/model/offsite*.py` 里搜
`fin_sim_order|fin_capital_flow|fin_cash_ledger|fin_transaction|fin_holding` —— **零命中**。
场外域只读写自己的 `offsite_*` 表。
⇒ **两个方向都不越界**,符合规则 8。这一点在合并评审时是要点,故在此留档。
---
## 5. 对审计工具的影响(**不是"有人偷偷建表"**)
```
$ .\.venv\Scripts\python.exe tools\audit_schema.py
schema audit passed: 68 business tables, no missing or unexpected tables
```
**表数从 51 跳到 68 是同事那 11 个迁移的**预期结果**,不是有人绕过基线偷偷建表。**
机制要说清楚(否则会被误读成"期望值被手工改过"):`tools/audit_schema.py` 的期望表集合
是**动态推导**的,不是一份手写清单:
```python
def expected_tables() -> set[str]:
tables = <从 alembic/baseline_generated.sql 正则提取 CREATE TABLE>
for path in (alembic/versions/*.py):
tables |= <从每份迁移里正则提取 CREATE TABLE> # ← 17 张新表由此自动进入
return tables
```
⇒ **期望值随迁移自动增长**,没有人手工改过它。优点是不会漏;**代价**是它只增不减 ——
若将来有迁移 **DROP** 掉某张表,期望集合仍会包含它,审计会报 `missing` 的假失败。
真要删表时(记得规则 3:**禁止删除已有表**)需同步调整该工具。
> ⚠️ 若你那边 `audit_schema.py` 报 `unexpected`,先确认是"库里多表"还是"迁移没进来"——
> 前者是绕过基线的违规,后者只是迁移没合。两者处置完全不同。
---
## 6. 与 `docs/00` 的关系(一句话)
**`docs/00` 一个字段、一张表都没动**(规则 1)。本文是它的**域外补充登记**,
两者合起来才是"当前库里的全部表":
```
docs/00(场内 51) + 本文(场外/推广 17) = 68 张业务表
```
---
*登记时点:2026-09-11 登记依据:现库 `information_schema` 实测 + `alembic/versions` 逐文件核对 +
`tools/audit_schema.py` 的期望值推导机制核对。*