From e0468a9d9fc9369ad7d37c77a7cdea1bf8dbdb64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=BF=E4=BA=91=E7=A7=8B=E6=9C=88?= <15273589815@163.com> Date: Sat, 12 Sep 2026 12:10:03 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E8=AE=B0=E5=BD=95=20PR=20#7=20?= =?UTF-8?q?=E5=90=88=E5=B9=B6=E9=97=A8=E7=A6=81=E7=BB=93=E6=9E=9C=E3=80=81?= =?UTF-8?q?=E4=B8=A4=E5=A4=84=E9=A1=BA=E6=89=8B=E4=BF=AE=E6=AD=A3=E4=B8=8E?= =?UTF-8?q?=E6=9D=83=E9=99=90=E5=8F=B7=E6=AE=B5=E5=86=B2=E7=AA=81=E7=9A=84?= =?UTF-8?q?=E6=9D=A5=E9=BE=99=E5=8E=BB=E8=84=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/35-ZSY处置回执v3-核实与收尾.md | 9 +- docs/36-PR7合并记录与权限号段修正.md | 145 +++++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 3 deletions(-) create mode 100644 docs/36-PR7合并记录与权限号段修正.md diff --git a/docs/35-ZSY处置回执v3-核实与收尾.md b/docs/35-ZSY处置回执v3-核实与收尾.md index 49fdcb6..2979415 100644 --- a/docs/35-ZSY处置回执v3-核实与收尾.md +++ b/docs/35-ZSY处置回执v3-核实与收尾.md @@ -111,9 +111,12 @@ DELETE FROM sys_permission WHERE id BETWEEN 9001 AND 9099 (客服二期 3 个 + 投顾 16 个,共 19 个)。这样重建种子后权限是**完整**的, `grant_*.py` 退化成"局部补齐",不再承担正确性。 -这件事在**我方公共文件**里,会影响另外几条线(跑种子的队友会多拿到 19 个权限 —— 方向是纯增益, -但毕竟动了环境基线),所以我先跟项目方报备再动,**不需要你做任何事**; -你若在自己环境把两个 `memory:candidate:*` 并进了种子,告我一声避免两边定义不一致。 +> **更新(合并时已办)**:项目方已同意,这 6 个权限码已并入 `seed_test_rbac.py` 的 +> `PERMISSIONS`(id **9041-9046**)—— 是 6 个不是 19 个:投顾那 13 个投顾线(`bbf623a`) +> 早已并进种子,只有 3 个治理类(`product-governance:*`)漏了,一并补上。 +> 顺带查到库里一批 `9020-9035` 与种子的 `9020-9034` **id→code 映射冲突**(我方环境的历史遗留), +> 已把号段整体上移到 9041-9046。 +> 详见 `docs/36-PR7合并记录与权限号段修正.md`。**不需要你做任何事。** --- diff --git a/docs/36-PR7合并记录与权限号段修正.md b/docs/36-PR7合并记录与权限号段修正.md new file mode 100644 index 0000000..8697ecd --- /dev/null +++ b/docs/36-PR7合并记录与权限号段修正.md @@ -0,0 +1,145 @@ +# PR #7 合并记录与权限号段修正 + +> **合并时间**:2026-09-12 +> **合并提交**:`4413644`(`merge: 合并 ZSY 的客服 Agent 接入(访客身份、画像候选、转人工工单)—— PR #7`) +> **来源**:`origin/ZSY_develop` = `f68b052` → `qyqy_develop` +> **规模**:90 文件、+7897 / −73 +> **门禁**:全部通过(见 §2),数据库侧无迁移、表结构未变 + +--- + +## 1. 合并内容 + +ZSY 的客服 Agent 接入线,含三块新能力与一次合规清理: + +| 块 | 内容 | +|---|---| +| 访客身份 | `VisitorTokenIssuer`(`/api/v1/auth/visitor-tokens`)、`security.py` 的 `visitor:true` 分支、`auth.py` 跳过 `IdentityService.resolve()` | +| 画像候选(二期) | 候选生成 Worker、用户确认 / 管理员审核四个端点、Milvus + Neo4j 投影适配器、`memory_sync_outbox` 消费者 | +| 转人工工单 | 工单只读管理端点、转接上下文构造、会话凭据最小化(`conversation_privacy.py`) | +| 合规清理(`9aaacc2`) | 删除生产死代码 `knowledge_tool_service.py` 与硬编码 Milvus 字段名的 `milvus_knowledge_adapter.py`(9 文件 +189/−483) | + +评审往返见 `docs/33`(v1 回复)、`docs/34`(v2 回复)、`docs/35`(v3 回执核实)。 + +--- + +## 2. 合并后门禁实测 + +| 项 | 结果 | +|---|---| +| `git merge f68b052 --no-ff` | ✅ 无冲突 | +| `ruff check app tests tools` | ✅ 干净 | +| `mypy app` | ✅ **244 文件 0 错**(基线 228,+16 为新模块) | +| `python tools/check_authoritative_docs.py` | ✅ **49 份文档无撞号** | +| `pytest tests/unit tests/contract` | ✅ **1275 passed, 2 skipped, 0 failed**(基线 1207,+68 为新用例) | +| `alembic current` | ✅ 已在 `20260911_merge_adv_risk_heads`(head),`upgrade head` 无操作 → **无新迁移** | +| `python tools/audit_schema.py` | ✅ **89 business tables, no missing or unexpected tables** | + +> 说明:`f68b052` **单独一棵树**跑文档守卫会报 `21`/`22` 撞车 —— 那是**我方基线**的问题 +> (投顾那两份的改名在我方 `5018f11`,不在 ZSY 的基线上)。合并后消失:`21`/`22` 归 +> 风控与四大 Agent,投顾挪到 `30`/`31`。**不是 ZSY 引入的。** + +--- + +## 3. 合并时顺手修掉的两处 + +### 3.1 `tests/unit/core/test_security.py` 的密钥路径漂移(2 行) + +第 48、108 行原本硬编码 `Path("config/jwt/jwt-private.pem")`,**漏了 `dev/`**: + +- `tools/generate_jwt_keys.py:107` 的默认 `--out-dir` 是 `config/jwt/dev`; +- `app/core/config.py:26-27` 的默认值也是 `config/jwt/dev/...`; +- 同一个文件第 13 行已定义 `DEV_KEY_DIR = Path("config/jwt/dev")`,注释写着 + 「路径只在这里定义一次……避免多处硬编码各自漂移」。 + +后果:在**没有** `config/jwt/jwt-private.pem` 的环境里必红 2 个用例(本机即如此)。 +已改为 `(DEV_KEY_DIR / "jwt-private.pem")`,与第 132 行写法一致。全仓这种写法只此 2 处, +其余 12 处引用都是 `config/jwt/dev/`。 + +### 3.2 权限号段冲突(**我方环境的历史遗留,ZSY 不受影响**) + +**问题**:库里有一批 `9020-9035`,是本方 `tools/grant_advisor_role.py` 用**旧号段**建的; +而投顾线(`bbf623a`)后来把 `9020-9034`(15 个)写进了公共种子 `seed_test_rbac.py`。 +两套 **id→code 映射不同**: + +| id | 种子(投顾线) | 库里(旧 `grant_advisor_role.py`) | +|---|---|---| +| 9020 | `investment-goal:write:self` | `asset-allocation:generate:self` | +| 9023 | `product-recommendation:generate:self` | `investment-goal:review` | +| 9031 | `product-recommendation:review` | `product-governance:read` | + +**后果**:种子的清理是 `DELETE FROM sys_permission WHERE id BETWEEN 9001 AND 9099`, +但角色绑定只清 `role_id IN (9001,9002,9003)` —— **`advisor`(9004) 的绑定不在清理范围内**。 +所以跑一次种子会把 `9020-9034` 换成种子的语义,而 advisor 的绑定仍指向这些 id ⇒ +**advisor 会拿到错误的权限组合**,且不会报错。 + +**处置**(已改代码,见下):权限号段整体上移到 **9041-9046**,与种子的 `9001-9034` 和 +库里的旧数据都不冲突;并把"权限码的定义以种子为准"写进了三个文件的文档字符串。 + +> ZSY 侧不受影响:他的库只有 `9001-9018`,没有这批旧数据。 + +--- + +## 4. 代码改动清单 + +| 文件 | 改动 | +|---|---| +| `tests/unit/core/test_security.py` | 2 行改用 `DEV_KEY_DIR`(§3.1) | +| `tools/seed_test_rbac.py` | `PERMISSIONS` 增 `9041-9046`(投顾治理类 3 个 + 客服二期 3 个);`CUSTOMER_PERMISSIONS` 增 `9044`;文档字符串写清「DELETE 重建」的两个后果 | +| `tools/grant_advisor_role.py` | `ADVISOR_PERMISSIONS` 由 16 个收敛为**种子里缺的 3 个**(`9041-9043`);文档字符串记录号段冲突与处置顺序 | +| `tools/grant_customer_service_phase2_permissions.py` | 权限 id `9036-9038` → `9044-9046`;文档字符串改为「已并入种子,本脚本仅作幂等补齐」 | + +新增的 6 个权限码: + +| id | 权限码 | 授给 | +|---|---|---| +| 9041 | `product-governance:read` | admin(治理类) | +| 9042 | `product-governance:review` | admin | +| 9043 | `product-governance:sync` | admin | +| 9044 | `memory:candidate:confirm` | **customer**(确认自己的候选)+ admin | +| 9045 | `memory:candidate:review` | admin | +| 9046 | `handover:read` | admin | + +一致性自检(只读):种子 40 条权限、id 唯一、无重复;两个 `grant_*.py` 的每一条 +`(id, code)` 都与种子逐字一致;`CUSTOMER_PERMISSIONS` 引用的 id 全部存在。 + +--- + +## 5. 我方环境待执行(写库,需确认后跑) + +代码侧已就绪,但**本机数据库还没对齐**,按顺序跑(顺序不能颠倒,原因见 §3.2): + +```powershell +# 1) 对齐 9001-9034 到种子版本(会清掉库里 9020-9035 的旧映射) +D:\conda\envs\jr_py313\python.exe tools\seed_test_rbac.py + +# 2) 补投顾治理类 3 个权限 + 建 advisor 角色 + 重建绑定 +D:\conda\envs\jr_py313\python.exe tools\grant_advisor_role.py --dry-run +D:\conda\envs\jr_py313\python.exe tools\grant_advisor_role.py + +# 3) 客服二期 3 个权限(已并入种子,跑过第 1 步后这步通常只做授权) +D:\conda\envs\jr_py313\python.exe tools\grant_customer_service_phase2_permissions.py --dry-run +D:\conda\envs\jr_py313\python.exe tools\grant_customer_service_phase2_permissions.py +``` + +⚠️ 第 1 步是 **DELETE 重建**,会重置 `customer`/`risk_operator`/`admin` 三个角色及其 +`sys_user_role` 绑定(`cust_t`/`risk_t`/`admin_t` 会被重建,密码哈希是占位 `'x'`, +**需要重新用 `tools/set_user_password.py` 设密码**)。所以它不适合在有真实数据的环境跑。 + +### 已知的既有环境缺口(本次顺带发现) + +本机库里 **`9018 knowledge:query` 与 `9019 knowledge:manage` 都不存在** —— 本机的 RBAC +数据比种子旧。`knowledge:query` 是 `search_knowledge` 工具的必需权限,缺它会让客服 Agent +调检索工具时被拒。跑上面第 1 步即可补齐。**与 ZSY 的合并无关**,是我方环境的账。 + +--- + +## 6. 遗留事项 + +| 项 | 归属 | 状态 | +|---|---|---| +| 品牌名(`COMPANY` 南方科技 → 奶龙基金责任有限公司) | ZSY 上报项目方 | 走 (b):保持现状,定后单行 revert,须与 `customer_service_rules.py:116/129` 一起处理 | +| 候选流程缺走 RBAC 的集成用例(服务层测试测不出"权限码不存在") | ZSY | 他认账,承诺补 | +| 只读真机冒烟(用真实令牌打 §19 新增端点,403 当失败) | 待 ZSY 回话 | 已提议 | +| 环境数据不可跨环境 | 全员 | 第 4 次踩坑,已写进种子文档字符串 | +| `docs/05` §19 端点编号 | 已解决 | `A039`/`A040`,全表 62 个编号唯一 |