WIP-363④ · WIP-368 验收复核判据(预置 v1)

用途:小齐修 WIP-368①② 期间预置验收判据——修复一落地即可按本文件复跑,不必临时定判据。
复核人:波波(验收检测岗,不写后端代码、不代执行)|时间:2026-09-16 12:1x
触发条件:小齐交付 368①(F-1 requested=None 静默忽略)/368②(F-2 POI 整域未接线)后。
四态:PASS / PASS-附条件 / BLOCKED / FAIL|四态不冒充:证据不足判 BLOCKED。

一、🔑 「同族路径」的定义(本次复核的核心)

用户指令要求「复核修复是否覆盖矩阵 10 例试点的同族路径」。本岗把「同族」从形容词变成可机械判定的定义:

同族 = 「声明点 vs 消费点」失衡:函数内出现了 resolve_destination(声明了目的地解析),
但请求侧的目的地参数没有被消费(requested=None 硬编码 或 不传参且签名默认 None)。

机械判定式(可脚本化,已具备条件):

同族缺陷 ⟺ (函数体内出现 resolve_destination) AND (调用中 requested ∈ {None, 未传})

已知同族清单(11/23 写端点,48%)——修复后这 11 个必须逐个有交代,否则视为未覆盖:

类型数量端点
requested=None 硬编码5admin_distribution.risk_ruling、admin_distribution.admin_generate_bills、admin_ops.admin_create_merchant、admin_ops.admin_create_temple、admin_ops.admin_delete_temple
不传参(签名默认 None ⇒ 等价)6miniapp_pay.prepay、miniapp_workbench_redeem.redeem_arrival、safety.trigger_sos、safety.cancel_sos、safety.submit_assessment、safety.submit_health_check
正常传参(对照组)12admin_backend 全部 12 个

⚠️ 「不传参」不是豁免理由:resolve_destination(user, requested=None) 的默认值就是 None,不传 ≡ 硬编码 None,效果完全相同。

二、10 例试点 → 修复后复跑清单(判据即用)

基线(2026-09-16 11:36,staging 100.64.1.230:8089,受限 JWT 锚定 dest=1):

#端点用例期望修复前实测修复后判据
A1/api/miniapp/admin/merchants跨=3/自=1403/200403/200 ✅保持,不得回归
A2/api/admin/cms/posts跨=3/自=1403/200403/200 ✅保持
A3/api/miniapp/admin/content/pois跨=3/自=1403/200🔴 200/200368② 修复后须 403/200
A4/api/admin/stats/overview跨=3/自=1403/200403/200 ✅保持
A5/api/miniapp/admin/orders——⚪ 用例错(404)替换端点(本岗自纠,非缺陷)
B1POST /api/admin/cms/posts跨=3403 + 零变更403 ✅保持
B2POST /api/miniapp/admin/merchants跨=3403 + 零变更🔴 200(落库)368① 修复后须 403 且 DB 零变更
B3POST /api/miniapp/admin/content/pois跨=3403 + 零变更🔴 200(落库)368② 修复后须 403 且 DB 零变更
B4POST /api/admin/products跨=3403 + 零变更403 ✅保持

复跑安全纪律(本岗踩过的坑,必须执行):

  1. 跑前先按 363regression-probe 查残留(目前 merchants id=30 / pois id=9 仍在库,请小齐清理);
  2. W-1 组先跑 B1/B4(已知 403 的安全组)确认环境正常,再跑 B2/B3;
  3. 一旦出现 2xx 立即停跑并报残留(W-1 的安全依据是「拒绝侧零变更」,隔离失效就会真落库);
  4. 每组前后取 DB 计数快照(cms_posts / merchants / pois)。

三、368① 修复的验收判据(F-1 参数静默忽略)

判合格(三条全满足):

  1. 10 例复跑:B2/B3 由 200 → 403 且 DB 零变更;
  2. 同族覆盖:§一 表中 11 个端点逐个有交代——要么改传 requested=destination_id,要么显式登记豁免;
  3. 无回归:A1/A2/A4/B1/B4 保持原判,且 admin 主 token 多 active 场景仍 409(我在 357 复核中补测过的那条,不得被修坏)。

判不合格的两种典型:

四、368② 修复的验收判据(F-2 POI 整域未接线)

判合格:

  1. dest=1 / dest=3 / 不带参 三种参数返回条数不再完全相同;
  2. 跨目的地(受限 JWT dest=1 请求 dest=3)读 403、写 403 且零变更;
  3. pois 表有 destination_id 列 ⇒ 属漏接不是无列,不得以「表结构不支持」为由申请豁免。

附带:content.py 整域不在 resolve_destination 消费清单 ⇒ 需确认同文件其它端点是否同样未接(如其它 content 资源),避免「只修 POI 一个端点」。

五、23 写端点分诊结果的复核判据(用户指令第 3 项)

小齐分诊后,本岗按三类复核。分类本身要有证据,不接受口头归类:

分类必须附的证据复核动作
真缺口 → 修修复 commit + 复跑实测(HTTP 码 + DB 快照)按 §三 判据复跑
语义安全 → 豁免登记书面语义说明:为何该端点按凭证锚定是产品本意(如「支付下单必属当前商户」)+ 登记位(文档/注释)逐条读说明,说不清的打回重分诊
未定性—判 BLOCKED,列入下轮派工窗

🔴 高敏端点不享受「默认豁免」:miniapp_pay.prepay、safety.*(4 个含 SOS)必须显式裁定——

六、门禁化建议(治本)

同族缺陷已第 4 次发作(352 Q2 批2 → R5 → POI 未接线 → requested=None)。机制立规已定但未落脚本 ⇒ 建议把 §一 的机械判定式写成静态检查,判据=退出码:

扫描 backend/app/routers/*.py
  对每个出现 resolve_destination 的函数:
    若 requested ∈ {None, 未传} 且 无豁免登记 → ERROR

本岗可接此脚本(纯读操作,零风险),待 R1 派单或并入 WIP-368 后段。

署名:波波 2026-09-16 12:1x(WIP-363④ · 验收复核判据预置)

附录 A · v1.1(2026-09-16 12:3x):判定式已脚本化(义父令:按本岗建议处理)

产出:scripts/check_destination_consumption.py(纯读、零风险、退出码即判据)。

A.1 用法

PY=/Users/lean/.workbuddy/binaries/python/versions/3.13.12/bin/python3

$PY scripts/check_destination_consumption.py                 # 写端点同族 ⇒ exit 1
$PY scripts/check_destination_consumption.py --baseline 11   # 冻结当前基线,只降不升
$PY scripts/check_destination_consumption.py --all           # 连读端点同族也计入 FAIL
$PY scripts/check_destination_consumption.py --json          # 机器可读

退出码:0 达标|1 未达标|2 脚本自身异常/解析失败(不静默通过)。

必须 py3.12+(AST PEP 701;py3.9 会把 f-string 误报语法错——本岗踩过)。

A.2 首跑真值(基线冻结,建议 --baseline 11 只降不升)

指标实测
扫描 router 文件64
声明点(resolve_destination/_default_destination 调用)57
同族 · 写端点11(与本判据 §一 清单完全吻合:硬编码 None 5 + 不传参 6)
同族 · 读端点1(safety.py:149 GET get_health_records,跨目的地读全量风险,与 POI 同类)
其中高敏(prepay/safety/sos)3
独立观察:user 传空 dict3(miniapp_merchants:99、packages:89、quotes:22)
有声明点的文件22 / 64

⇒ 交叉印证成立:脚本机器结果与本岗 11:3x 人工盘点的 11 个同族逐条一致(含 prepay、safety×4),说明原判据无遗漏、脚本判定式实现无误。

A.3 🔴 新增第二维度:疑似「整域未接线」候选(原判据的盲区)

盲区说明:A.2 那套判定式只能抓「声明了但不消费」(requested=None/不传参),

抓不到 POI 那种「整域压根没声明」——content.py 函数体内根本没有 resolve_destination,

因此不进同族清单,却是更严重的漏接。故补第二维度:

候选 ⟺ (该 router 文件 write_fns > 0) AND (声明点 == 0) AND (无 TenantContext 依赖注入痕迹)

实测:28 个文件命中,涉及写端点合计 94 个。Top:admin_content.py(10)、docs.py(8)、scenes.py(7)、agent.py(6)、demand.py(6)、workbench.py(6)、kora_routes.py(5)、miniapp_user.py(5)、review_center.py(5)、miniapp_merchant_applications.py(4)。

⚠️ 三不原则(防止本岗重蹈 P3 台账覆辙):

  1. 不代判——候选 ≠ 缺陷。其中 auth.py(登录)、docs.py(文档)、agent.py 等很可能语义上本就不需要目的地隔离;
  2. 不夸大——不得表述为「28 个域全部漏接」,那会制造假警报;
  3. 不豁免——须走 §二 三分类逐域定性(真缺口/语义安全须书面说明+登记位/未定性=BLOCKED)。

🔴 admin_content.py(写端点 10 个、零声明点)与本岗 363② 实测的 POI 未接线同域,

直接印证该维度不是误报 ⇒ 建议列为该维度首个定性对象。

A.4 五项反证(证明脚本有鉴别力,非「形同虚设」)

#反证期望实测
1人类模式退出码(重定向取,不走管道)1✅ 1
2--baseline 11(等于当前值)0✅ 0
3--baseline 10(低于当前值)1✅ 1
4临时探针:requested=destination_id 不计/None 计/未传计/_default_destination 计2 写 + 1 读✅ 一致
5探针目录放语法坏文件exit 2(不静默通过)✅ 2
反证文件建在 /tmp,未触碰任何业务代码(本岗不写后端)。

A.5 门禁化建议

署名:波波 2026-09-16 12:3x(WIP-363④ v1.1 · 判定式脚本化)