15 KiB
回复 ZSY:处置回执(v3)的核实与收尾
致:ZSY 被回复:
致qyqy_处置回执_v3.md被核实的分支:origin/ZSY_develop=f68b052我方基线:origin/qyqy_develop=ade5e0c(我方 7 个提交已推送) 结论:两处修正核实通过,handover:read那段历史说明逐字准确 —— 合并前没有别的待办了; 只剩一个数字更正(§1)和一件根治建议(§4),都不阻塞合并。
0. 核实结论
| 你的说法 | 我实测到的 | 结论 |
|---|---|---|
A034/A035 → A039/A040 |
f68b052 的 docs/05 里这两行正是 A039/A040,A034 只归 POST /auth/tokens、A035 只归 GET /admin/roles |
一致 |
| 全表端点编号无重复 | 我独立正则扫了一遍:重复 0 | 一致(数字见 §1) |
milvus-lite 移出主依赖 |
主 dependencies 已无该行;[project.optional-dependencies] dev 里有,且注释写明"刻意不进主 dependencies" |
一致,注释写得比我要求的清楚 |
requirements.txt 不再作为生效依赖 |
该行已改为注释,指向 pip install -e ".[dev]" |
一致 |
| 改动只涉及这两处 | git diff 9aaacc2..f68b052:3 文件 +11/−4,无夹带 |
一致 |
handover:read 是 ef098e6 加的、ef701c8 冲突时丢了 |
git show ef098e6:tools/seed_test_rbac.py 里有 (9018, "handover:read", "handover", "read", "all");ef701c8、9aaacc2、f68b052 里都只剩 handover:create |
逐字准确 |
handover:read 这一条我要特意说一句:你把一个"自己环境里有一条别人没有的权限"主动交代清楚了,
还顺手说明了它在你库里是残留、重跑种子会清掉。这种披露比"我这边是好的"有用得多 ——
否则我按"两边都没有"去建,反而可能在你库里撞上 id 唯一键。这条我按你说的办:9036/9037/9038 原样不动。
我方库现状也报给你对齐:sys_permission 38 条,handover:create 是 9008、没有 handover:read,
memory:candidate:* 两个都没有;customer=9001、admin=9003 都在。
1. 一处数字更正:不是 55 个,是 62 个
你的结论(无重复)是对的,但计数口径建议修一下 —— 我扫出来是 62:
A 40 个:A001 … A040(连续)
C 7 个:C001 … C007
K 4 个:K001 … K004
M 4 个:M001 … M004
O 3 个:O001 … O003
R 4 个:R001 … R004
—— 合计 62,唯一 62,重复 0
我的口径是匹配 §19 所有表格行的首列 ^\| ([A-Z]\d{3}) \|。两个旁证:
- 你合并前的我方基线
c4a73b7是 58 个; - 58 + 你新增的 4 个(
A039/A040/M003/M004)= 62 ✓ 与Compare-Object结果一致。
你的脚本漏扫了 7 个(大概是某个号段或某张子表没进正则)。这不影响这次结论,但下次就不一定:
漏掉的 7 个编号如果被新端点复用,脚本仍会报"重复 0",这处又会变成静默遗留 ——
和 check_authoritative_docs.py 不查 §19 是同一类盲区。建议按 62 的口径修一下,加一句
「这 6 个号段都在扫描范围内」的自检更好。
2. 你的更正我接受,而且它比你想的更值钱
我写"你的集成测试能过,说明环境里已手工插过" —— 你说这条只对 handover:read 成立,
两个 memory:candidate:* 从来没存在过,因为候选流程的集成测试调服务层、没走 HTTP + RBAC。
这个更正成立,我照收。
而且这条暴露的是一个通用盲区,比这一个缺陷重要:
凡是"环境数据缺失"造成的 403,服务层测试永远测不出来 —— 权限判定发生在
build_request_context→IdentityService.resolve之后,服务层测试通常直接构造RequestContext,权限字段是测试自己塞的。所以"权限码在库里不存在"这类问题, 单元/集成测试全绿也照样漏。
这个坑我们已经踩了 4 次(config_release、Milvus schema、投顾角色、这次的客服二期权限)。
所以我建议除了你补 RBAC 用例之外,再加一道真机冒烟:拿 admin 与 customer 的真实令牌,
按 docs/05 §19 把新增端点各打一次,把 403 当失败。
我这边可以先出一个只读冒烟脚本(不写数据、只发请求并归类 401/403/404/2xx),
两边都能跑,这样下一批接口进来时不必再靠人工核。要不要我出,你回一句即可。
3. 品牌名:走 (b),保持现状
按你建议的 (b):现在不动,等项目方拍板后出一笔单行 revert。
理由就是你说的那两条,我完全同意:
- (a) 要重写已经推送的共享历史(PR #7 上还有别人的评审轨迹),为一行常量付这个代价不值;
- 你补充的那点很关键:单回退
COMPANY会把我发现的那处内部矛盾重新引回来 (app/core/customer_service_rules.py:116/129本来就是「奶龙基金」),所以要动就得两边一起动。
你那个提交级溯源我也核了,结论与你一致:这个改动落在 ef701c8 的合并解决结果里,
不在任何功能提交里 —— 所以"单独成提交"这条路本来就不干净,(b) 是正解。
上报时请把 customer_service_rules.py 那两行一起写进去,项目方看到"当前代码自相矛盾"更容易拍。
4. 权限脚本能跑,但它不持久 —— 建议一次根治
你安排的顺序是对的:先 seed_test_rbac.py → 再跑 grant_customer_service_phase2_permissions.py。
我核实了 seed_test_rbac.py 第 116 行:
DELETE FROM sys_permission WHERE id BETWEEN 9001 AND 9099
这一行意味着 9036-9038 每次重建种子都会被清掉,而且投顾那 16 个(9020–9035)也一样。
所以"先种子再补脚本"能work,但它是一次性的:以后任何人再跑一次种子,客服二期这 5 个接口
又会变 403,而且不会有人立刻发现 —— 这正是 §2 说的那种盲区。
根治方案:把这两个权限集合并进 seed_test_rbac.py 的 PERMISSIONS 常量
(客服二期 3 个 + 投顾 16 个,共 19 个)。这样重建种子后权限是完整的,
grant_*.py 退化成"局部补齐",不再承担正确性。
更新(合并时已办):项目方已同意,这 6 个权限码已并入
seed_test_rbac.py的PERMISSIONS(id 9041-9046)—— 是 6 个不是 19 个:投顾那 13 个投顾线(bbf623a) 早已并进种子,只有 3 个治理类(product-governance:*)漏了,一并补上。 顺带查到库里一批9020-9035与种子的9020-9034id→code 映射冲突(我方环境的历史遗留), 已把号段整体上移到 9041-9046。 详见docs/36-PR7合并记录与权限号段修正.md。不需要你做任何事。
5. requirements-local.txt:不用建
你的处理方式(dev extra + requirements.txt 里留注释指向 pip install -e ".[dev]")就是我要的结果,
不必再建一个 requirements-local.txt —— 多一个依赖清单就多一处会漂移的地方。
milvus-lite 落 dev extra 是对的落点。
6. 结论:合并前没有别的待办
6.1 我方已跑的四项门禁(隔离 worktree 里,对「f68b052 + ade5e0c 合并后」的树跑)
| 门禁 | 结果 |
|---|---|
合并预演 git merge |
✅ 无冲突 |
ruff check app tests tools |
✅ 干净 |
mypy app |
✅ 244 文件 0 错(基线 228,+16 是你的新模块) |
python tools/check_authoritative_docs.py |
✅ 48 份文档无撞号 |
pytest tests/unit tests/contract |
⚠️ 见 §6.2 —— 修掉 2 行后 1275 passed / 2 skipped / 0 failed |
顺带两条你可能想知道的:
f68b052单独一棵树跑文档守卫会报21/22撞车 —— 那是我方基线的问题 (投顾那两份的改名提交在我方5018f11,不在你的基线上),你不背这个锅; 合到ade5e0c之后就消失了:21/22归风控与四大 Agent,投顾挪到30/31。- 我方门禁基线原是 1207 passed,现在是 1275(多出来的 68 个是你的新用例)。
6.2 ⚠️ 跑出一个真缺陷:test_security.py 有 2 处硬编码漏了 dev/
tests/unit/core/test_security.py 第 48、108 行:
private_key = Path("config/jwt/jwt-private.pem").read_text(encoding="utf-8")
但开发密钥实际在 config/jwt/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"),注释还写着 「路径只在这里定义一次:换密钥目录时改这一处,避免多处硬编码各自漂移」。
所以这 2 行正是那句注释要防的漂移。后果是在任何没有 config/jwt/jwt-private.pem 的环境里必然红 2 个
(我这边就是;你那边能过,大概是你本地直接在 config/jwt/ 下生成过一套 —— 全仓这种写法只有这 2 处,
其余 12 处引用都是 config/jwt/dev/)。
这 2 行我方合并时顺手改掉(改成 (DEV_KEY_DIR / "jwt-private.pem"),与你第 132 行写法一致),
不需要你再跑一趟。改完 pytest tests/unit tests/contract = 1275 passed, 2 skipped, 0 failed,
ruff 也干净。你下次改这个文件时按 DEV_KEY_DIR 写即可。
6.3 待办清单
| 项 | 状态 |
|---|---|
A034/A035 编号去重 |
✅ 已改并核实 |
milvus-lite 降为可选依赖 |
✅ 已改并核实 |
| 三个权限的种子脚本 | ✅ 我方已出(tools/grant_customer_service_phase2_permissions.py,dry-run 通过、ruff 通过) |
handover:read 的 id 对齐 |
✅ 按 9036/9037/9038 原样,无需避让 |
| 品牌名 | ✅ 走 (b),等项目方,不阻塞合并 |
| 四项门禁 | ✅ 已在本方预演树跑通(含 §6.2 的 2 行修正) |
test_security.py 那 2 行 |
🔧 我方合并时顺手改,不占你时间 |
| 测试盲区(环境数据类 403) | 📌 你补 RBAC 用例;我出一个只读冒烟(等你一句话) |
PR #7 我这边没有反对意见了,可以合。 合并时机由我方定,落在我这边的一串动作是
(docs/32-平台侧交接与联调准备.md §5):
alembic upgrade head
python tools/audit_schema.py
python tools/check_authoritative_docs.py
ruff / mypy / pytest(四项门禁)
python tools/grant_customer_service_phase2_permissions.py
真机冒烟:docs/05 §19 新增端点逐个打
前四项我会在合并后立刻跑,出结果同步给你;后两项在真机联调那一轮一起做。
辛苦了。
7. 附:可直接复制发送的微信版
ZSY 你好,v3 我核实完了,两处都过,可以合了。
f68b052 我逐行核过:docs/05 那两行确实是 A039/A040、A034/A035 现在只归登录和 RBAC;
milvus-lite 主 dependencies 里没了、落在 dev extra、requirements.txt 改成注释指向
pip install -e ".[dev]" —— 这个处理就是我要的结果,不必再建 requirements-local.txt。
整个提交 3 文件 +11/−4,没有夹带。
handover:read 那段我要专门说一句:你把"自己库里有条别人没有的权限"主动交代清楚了,
我核了 git 历史,ef098e6 确实有 (9018,"handover:read",...),ef701c8 起就没了 —— 逐字准确。
这条最有用的地方是:否则我按"两边都没有"去建,可能在你库里撞 id 唯一键。
所以就按 9036/9037/9038 原样,你不用为我避让任何号段。
一处数字更正:不是 55 个,是 62 个。分布是 A40(A001-A040 连续)+ C7 + K4 + M4 + O3 + R4。
我的口径是匹配 §19 所有表格行首列。旁证:你合并前的 c4a73b7 是 58 个,58+你新增的 4 个
(A039/A040/M003/M004)= 62,正好对上。结论(重复 0)是对的,但你的脚本漏扫了 7 个 ——
下次那 7 个如果被复用,脚本还是会报"重复 0",又变成静默遗留。建议按 62 修一下。
你那个更正我接受,而且它比你想的更值钱:凡是"环境数据缺失"造成的 403,服务层测试永远测不出来,
因为权限判定发生在身份解析之后,服务层测试是自己塞 RequestContext 的,权限字段天然是绿的。
这个坑我们已经踩了 4 次(config_release、Milvus schema、投顾角色、这次客服二期权限)。
所以你补 RBAC 用例之外,我再加一道真机冒烟:用 admin 和 customer 的真实令牌把新增端点各打一次,
403 当失败。只读冒烟脚本我可以出,两边都能跑,你说一声。
品牌名按你建议走 (b):现在不动,等项目方拍板后单行 revert,不重写已推送的历史。
上报时把 customer_service_rules.py 116/129 那两行一起写进去(本来就是"奶龙基金"),
项目方看到"当前代码自相矛盾"更容易拍。
最后提醒一个持久性问题:seed_test_rbac.py 第 116 行是
DELETE FROM sys_permission WHERE id BETWEEN 9001 AND 9099,
所以 9036-9038 每次重建种子都会被清掉,投顾那 16 个(9020-9035)也一样。你安排的
"先种子再补脚本"能work,但以后谁再跑一次种子,这 5 个接口又会 403 且没人立刻发现。
根治办法是把这 19 个并进 seed_test_rbac.py 的 PERMISSIONS 常量。这在我方公共文件里、
会影响另外几条线,我先跟项目方报备再动,不需要你做任何事。
PR #7 我这边没有别的反对意见了,可以合。合并后我立刻跑 alembic upgrade head、
audit_schema、文档守卫和四项门禁,出结果同步给你;权限脚本和真机冒烟放到联调那轮。
对了,我在隔离环境里把 f68b052 和我的 ade5e0c 合起来跑了四项门禁(合并无冲突、ruff 干净、
mypy 244 文件 0 错、文档守卫 48 份无撞号),跑出一个真缺陷跟你说一声:
tests/unit/core/test_security.py 第 48、108 行硬编码了 Path("config/jwt/jwt-private.pem"),
漏了 dev/ —— 密钥实际在 config/jwt/dev/ 下(generate_jwt_keys.py 默认 out-dir 就是它、
config.py 默认值也是它,你自己第 13 行还专门定义了 DEV_KEY_DIR 并注释"避免多处硬编码各自漂移")。
这 2 行就是那句注释要防的漂移,在没有 config/jwt/jwt-private.pem 的环境里必然红 2 个
(我这边就是;你那边能过估计是本地直接在 config/jwt/ 下生成过一套)。
这 2 行我合并时顺手改掉,不用你再跑一趟,改完 unit+contract 是 1275 passed / 2 skipped / 0 failed。
顺带说一句:f68b052 单独一棵树跑文档守卫会报 21/22 撞车,那是我方基线的问题(投顾那两份
还没改名),你不背这个锅,合到 ade5e0c 之后就没了。
辛苦了。