文件
hl-api-changelog/changelogs-v2/2026-09/23_8194_配置位守卫判据翻面字典角色被删回后不再静默放行-修改接口-管理后台.md
T
2026-09-23 16:36:44 +08:00

27 KiB
原始文件 Blame 文件历史

schema, ticket, title, consumer, author, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base
schema ticket title consumer author change_type backend_status gateway_status frontend_status frontend_owner frontend_ref target_release verified_at status_note updated_at base
hl-changelog/v2 8194 配置位守卫 582117 的触发集合扩大到「除 DRIVER / OTHER 以外的全部角色」 admin wx(GIT) 修改接口 deployed not_required not_required 工单 #8194 补的是 #8148 留下的残留缺口。角色↔人员类型的守卫 582117 判的是「该角色在配置位字典里查不到归属位」,而它的分流判据(GroupBatchStaffSlotResolver#participatesInSlotsByFallback)读的是编译期常量兜底名单,只认 GUIDE / LEADER / PHOTOGRAPHER。问题是 #7079 / #8148 立下的能力恰恰是「业务在字典页面加一行就能把某个人员类型配进配置位、不发版」——靠字典新增出来的角色永远不在这张常量名单里,于是「字典给某位加一行 → 有人按它配了人 → 那行又被删掉」这一形态仍走静默放行分支:接口 200、脏行落库、并异步扇出到团内全部活跃订单,该角色的 582114 当场失效,要到结算对账才发现人岗对不上。关键一点是撞上它不需要有人手搓请求——resolveStoredStaffRole 会把落库的 staff_role 改写成人员的真实类型(字典角色),前端回显后原样提交回来,系统自己就会产出那个落进缺口的 staffRole 值。修法(2026-09-23 定案 B,判据翻面):把「本该有位」的判据从「在不在兜底名单里」换成「不在结构性豁免闭集 STRUCTURALLY_SLOT_EXEMPT_ROLES(= DRIVER / OTHER)里」,豁免闭集落成显式常量集合并从 SettlementStaffRoleEnum 取值,方法名同步改为 requiresSlotMembership(改完它不再读 fallbackTypes(),名字与语义必须同批改)。行为变化:GUIDE_ASSISTANT / STUDY_TEACHER / LIFE_TEACHER 三个「只可能靠字典纳入配置位」的角色,在「字典里查不到归属位」时由静默 200 落库变为返回 582117;DRIVER / OTHER 照旧放行(OTHER 的常态就是不属于任何配置位,保护它会拒掉每一次正常的杂项人员配置,那是删功能不是补洞)。已知边界(按 #8194 决策点 4 有意保留、不在本单修):OTHER 在 VALID_STAFF_TYPES 里,业务能把 OTHER 写进某个位的字典再删掉,那一形态仍走静默放行。生产代码由 PR #8259 合入 dev-v3(squash 提交 f6d21648b)。2026-09-23 测试服已实测:PUT /v3/admin/group-batch/2102640646949105666/staff 提交 staffRole=GUIDE_ASSISTANT 返回 code=582117(HTTP 200,文案完整),读回确认零写入;同端点 staffRole=DRIVER 与 staffRole=OTHER 均返回 code=200 成功;探测插入的两行已用 scopeRoles=[DRIVER,OTHER] + staffList=[] 还原,读回与探测前逐字段一致。契约(路径 / 方法 / 权限 / 入参字段与取值域 / 成功响应结构)零变更——BatchStaffConfigReqVO 只加了 javadoc(含该表)。前端结论(2026-09-23):5821xx 全族在 hl-ui v2.1 无专门分支,统一由拦截器按 code 非成功 toast 后端 message;582117 文案已点名角色并指向配置位字典页,完整直出即可。命中后正确动作是去字典页补行,重试仍被拒不会误操作——与 #8123/#8148 既定拍板一致,维持通用 toast,不做专门引导,零改动闭环。后端订正三处(降级态字典角色同拒 582117/示例 payload 纠错/补缓存窗口与存量脏行边界)前端已审阅:均为后端行为澄清,契约零变化,文案仍拦截器直出,前端 not_required 结论不变。 2026-09-23 dev-v3

团期人员配置: 配置位缺失守卫 582117 的触发集合扩大到全部非豁免角色(管理后台)

服务: hl-order-service-v3(端口 8086/8186) PR: #8259(squash 提交 f6d21648b) Issue: #8194(前置 #8148 / #8122 / #7079) 日期: 2026-09-23 影响范围: 管理后台团期详情页的「配导游 / 配摄影」弹窗保存动作


⚠️ 关键变化

这个端点返回 582117 的角色集合变大了,路径、入参、成功响应结构一律不变。

以前只有 GUIDE / LEADER / PHOTOGRAPHER 三个内置角色在「字典里查不到归属位」时会被 582117 拒掉;现在除 DRIVER 与 OTHER 以外的任何角色都会被拒,其中就包括业务自己通过配置位字典启用过的 GUIDE_ASSISTANT / STUDY_TEACHER / LIFE_TEACHER。

调用方以前以为的是:staffRole=GUIDE_ASSISTANT 这类「字典角色」提交时不会触发 582117(它压根不在守卫的名单里)。 实际现在是:它同样会触发 582117,而且这批请求本来就是脏数据(角色没有任何人员类型校验背书)。

DRIVER / OTHER 的行为不变,仍放行。


一、背景

配置位成员集合自 #7079 起由数据字典决定(group_batch_staff_slot_guide / group_batch_staff_slot_photographer),业务在字典管理页面加一行就能把某个人员类型配进这个位,不发版。GroupBatchStaffSlotResolver 的类 javadoc 原文就是这句:「业务在字典管理页面给 group_batch_staff_slot_guide 加一行 STUDY_TEACHER,研学老师就能配进导游位,不发版」。

#8148 把「角色 → 允许的人员类型」这半边也迁到了字典,并引入 582117:当某角色在字典里查不到归属位时,本该有位的角色要被拒,而不是沿袭改前的「一律不校验」。但 #8148 的分流判据读的是编译期常量兜底名单(GUIDE / LEADER / PHOTOGRAPHER),它恰恰不包含任何「靠字典新增出来的角色」——那正是这个新能力的产物。结果是:

「查不到归属位」的成因 #8148 之后的行为 是否正确
DRIVER / OTHER 这类结构性不参与配置位的角色 放行 ✅ 正确
内置角色(GUIDE / LEADER / PHOTOGRAPHER)被从仍非空的字典里删掉 拒绝 582117 ✅ 正确
字典启用过的角色(GUIDE_ASSISTANT / STUDY_TEACHER / LIFE_TEACHER)被删回 静默放行 ❌ 缺口

第三种形态的失败后果与加 582117 之前逐字相同:HTTP 200、Result.success、前端看不到任何异常;落库成功并异步扇出到团内全部活跃订单;静默放行分支一行日志都不打。

而撞上它不需要有人手搓请求:

  1. 业务给导游位字典加一行 GUIDE_ASSISTANT;
  2. 前端按导游位提交 staffRole=GUIDE、该人真实 staffType=GUIDE_ASSISTANT → 校验通过 → resolveStoredStaffRole 把落库的 staff_role 改写成 GUIDE_ASSISTANT;
  3. 下次打开弹窗,回显的既有行角色就是 GUIDE_ASSISTANT,提交回来 staffRole=GUIDE_ASSISTANT;
  4. 此后运维把那行字典删掉 ⇒ 第 3 步那种请求走进静默分支,且此时 staffRole=GUIDE_ASSISTANT 配任何 staffType 都能过。

修法(#8194 决策点 5 定案 B:判据翻面):把「本该有位」的判据从「在不在兜底名单里」换成「不在结构性豁免闭集里」。豁免闭集 = {DRIVER, OTHER}(#8194 决策点 4 定案),落成 GroupBatchStaffSlotResolver#STRUCTURALLY_SLOT_EXEMPT_ROLES 这一个显式常量集合。方法随之改名 participatesInSlotsByFallback → requiresSlotMembership——改完它不再读 fallbackTypes(),名字与语义必须同批改,否则留下「命名断言别处行为」的静默漂移点。


二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 保存团期人员配置 PUT /v3/admin/group-batch/{productBatchId}/staff 修改接口 582117 的触发角色集合扩大;路径 / 入参 / 权限 / 成功响应结构不变

网关无改动(没有新增 /admin/ Controller,路由不动)。


三、接口详情

1. 保存团期人员配置 PUT /v3/admin/group-batch/{productBatchId}/staff

VO: BatchStaffConfigReqVO

使用场景

团期详情页「配导游 / 配摄影」弹窗点保存。按 scopeRoles(不传即整期)软删旧配置、写入新配置、异步扇出到各活跃子订单,并按配置结果回填 guide_ready / photographer_ready。

🔴 路径参数是产品侧排期 ID,不是团期聚合主键。端点名叫 group-batch,但 {productBatchId} 吃的是 group_tour_batch.batch_id。响应体里另有一个 groupBatchId,那才是订单侧 order_group_batch 的主键,两者不是同一个值。

入参

字段 位置 类型 必填 约束 说明
productBatchId path Long 是 正整数,产品侧排期 ID 团期所属班期;未建团返 589553
scopeRoles body List<String> 否 传了就不能是空数组;元素非空白且须在员工角色取值域内 限定本次覆盖的角色范围,不传则整期覆盖
staffList body List<Item> 是(可在服务层为空数组) @NotNull;[] 表示清空覆盖范围内的配置 覆盖范围内的最终状态
staffList[].staffId body Long 是 须命中候选人员 人员 ID
staffList[].staffRole body String 是 @NotBlank + @Pattern,须与人员类型相符,否则 582114 角色取值域见「六.5」
staffList[].sortOrder body Integer 否 — 展示排序,默认 0
staffList[].remark body String 否 @Size(max=500) 备注

出参 Result<BatchStaffConfigRespVO>

字段 类型 说明
productBatchId Long 回显路径参数
groupBatchId Long 团期聚合主键,与路径参数不是同一个值
staffList List 保存后的整期最终状态(含 staffRoleName / reporterRankName 等中文 Label)
affectedOrderCount Integer 本次扇出触及的活跃子订单数

请求示例

PUT /v3/admin/group-batch/2102640646949105666/staff HTTP/1.1
Host: api.test.1814.love:9443
Authorization: Bearer <admin token>
Content-Type: application/json

{"staffList":[{"staffId":1002,"staffRole":"GUIDE","sortOrder":0,"remark":"hl8194-ok"}]}

⚠️ 把上面的 staffRole 换成 GUIDE_ASSISTANT(或其他字典角色)在修复后会返回 582117,不再是 200——见「错误响应」。这正是本单的行为变化。

响应示例

成功时:

{
  "code": 200,
  "message": "成功",
  "data": {
    "productBatchId": "2102640646949105666",
    "groupBatchId": "2102640736900116481",
    "affectedOrderCount": 1,
    "staffList": [
      {"id": "2102640914386284545", "staffId": 1002, "staffRole": "GUIDE", "staffRoleName": "导游", "staffName": "李雪梅", "reporterRank": "NONE"}
    ]
  },
  "success": true
}

空数据 / 降级响应

staffList 传空数组即清空覆盖范围内的配置,返回 200,staffList 为空数组、affectedOrderCount 为实际扇出订单数。

配置位字典读挂 / 读空时,typesOf 回落内置默认值(导游位 GUIDE+LEADER、摄影位 PHOTOGRAPHER):内置角色(GUIDE / LEADER / PHOTOGRAPHER)的保存照常成功,这条降级保证本单未动。

⚠️ 但内置名单之外的角色不是这样:GUIDE_ASSISTANT / STUDY_TEACHER / LIFE_TEACHER 不在兜底名单里,字典服务不可用期间它们依然「查不到归属位」⇒ 同样返回 582117。也就是说 582117 现在有两种成因:①字典可读、但该角色不在任何配置位里(修复动作是补回那一行字典);②字典服务不可用、且该角色不是内置兜底成员(修复动作是恢复字典服务)。文案当前不区分两者,排查时请先确认字典服务可用性。

错误响应

新增会命中的情境:字典里查不到该角色的归属位,且该角色不在豁免闭集里({0} 由运行期填入角色名):

{"code": 582117, "message": "角色 GUIDE_ASSISTANT 未归属任何人员配置位,无法校验人员类型;请检查配置位字典是否被误删", "data": null, "success": false}

本端点此前已有、本次不改动的其余业务码(一并列出便于对照):

{"code": 582114, "message": "所选人员的角色与其人员类型不符,请重新选择", "data": null, "success": false}
{"code": 582115, "message": "提交的人员角色超出本次保存声明的范围", "data": null, "success": false}
{"code": 582116, "message": "本次保存声明的角色范围(GUIDE)只覆盖了配置位的一部分,还缺少 LEADER;同一配置位的角色必须一起声明,否则位内其余人员会被留在库里", "data": null, "success": false}
{"code": 100503, "message": "资源被占用,请稍后重试", "data": null, "success": false}

全部走 HTTP 200,不是 5xx。

业务边界

  • 582117 有两种成因,排查顺序是先服务后内容:①字典可读、但该角色不在任何配置位里(被删掉,或从来没配过);②字典服务(hl-user-service)不可用而该角色又不是内置兜底成员(GUIDE / LEADER / PHOTOGRAPHER)。此时文案说的「字典是否被误删」会指错方向——先去字典页面看会发现那行可能压根没删过。
  • 被判定的不是「你这个角色对不对」,而是「这个角色的归属位是不是丢了」。角色本身合法(在 @Pattern 取值域内)但字典里没有它的位 → 582117;位找得到但人岗不符 → 582114。两者互补。
  • 修复动作在配置位字典页面,不在这个弹窗里,所以文案点名角色并指向字典,适合原样透出给运营。
  • 豁免闭集是 DRIVER 与 OTHER,两者在任何字典状态下都不做角色↔人员类型校验,582117 与 582114 都不触发。
  • 被 582114 / 582115 / 582116 / 582117 任一码拒绝时零写入——所有校验闸都在写库之前,且发生在注册 afterCommit 扇出回调之前,回读会看到与提交前逐字相同的配置。
  • 导游位并收 GUIDE 与 LEADER:只传 ["GUIDE"] 却选了领队会命中 582115,只传 ["GUIDE"] 而位内还有 LEADER 会命中 582116。

四、契约约束与正确调用方式

本节只写后端接受/拒绝 payload 的规则,不写 UI 渲染建议。

契约面零变化,行为面有变化

面 是否变化 依据
路径 / HTTP 方法 / 权限码 不变 Controller 未动
入参字段、类型、必填性、@Pattern 取值域 不变 BatchStaffConfigReqVO 只加了 javadoc
成功响应结构 不变 BatchStaffConfigRespVO 未动
582117 的触发角色集合 变化 Service 的分流判据翻面

✅ 正确 / ❌ 错误 payload 对照

场景 payload 结果
✅ 内置角色、字典正常 {"staffList":[{"staffId":1002,"staffRole":"GUIDE"}]} 200,落库 staffRole=GUIDE
✅ 结构性豁免角色 {"scopeRoles":["DRIVER"],"staffList":[{"staffId":1002,"staffRole":"DRIVER"}]} 200,落库 staffRole=DRIVER
✅ 结构性豁免角色 {"scopeRoles":["OTHER"],"staffList":[{"staffId":1002,"staffRole":"OTHER"}]} 200,落库 staffRole=OTHER
✅ 字典已收录该角色 字典里 group_batch_staff_slot_guide 含 GUIDE_ASSISTANT,提交 staffRole=GUIDE 且该人 staffType=GUIDE_ASSISTANT 200,落库 staffRole=GUIDE_ASSISTANT
❌ 字典角色但字典里已查不到位 {"staffList":[{"staffId":1002,"staffRole":"GUIDE_ASSISTANT"}]} 200 + code=582117,零写入
❌ 提交越界的人 {"scopeRoles":["GUIDE"],"staffList":[{"staffId":1002,"staffRole":"LEADER"}]} 200 + code=582115,零写入

调用方的正确动作

  • 命中 582117 时不要重试,也不要自动改写 staffRole——正确动作是去配置位字典页面把缺的那一行补回来(或确认为什么它被删了),再重试保存。文案里的角色名就是缺的那一个。
  • 判成败一律看 code,不要看 HTTP status:本端点的业务失败全是 HTTP 200。
  • 保存成功后若调用方缓存了 guide_ready / photographer_ready,需重新拉取团期详情。

五、数据库行为

  • 保存:按 scopeRoles 范围(不传即整期)软删旧配置行 → 写入新配置行 → 注册 afterCommit → 异步扇出到各活跃子订单(order_staff_assignment 中 source=GROUP_BATCH 的行整删整插)→ 回填团期行的两个 ready 标志。
  • 本次改动不改变任何一步的写内容,只改变「哪些请求会被挡在写库之前」。
  • 被 582114 / 582115 / 582116 / 582117 任一码拒绝时零写入:校验发生在 buildToInsert 与 doSaveInTransaction 之前,且 afterCommit 扇出回调尚未注册(注册动作在事务段内部、软删与插入之后)。

六、边界行为

  • DRIVER / OTHER 不受本单影响:两者在任何字典状态下都放行,与改前一致。
  • 字典读挂 / 读空不降级成拒绝:typesOf 回落内置默认值,内置角色(GUIDE / LEADER / PHOTOGRAPHER)照常保存。
  • 将来往 @Pattern 里加第 9 个取值而忘了判断它属不属于豁免闭集时,新角色默认落进「本该有位」侧 ⇒ 那一侧是拒绝(响亮失败、当场被发现),不是静默放行。失败方向正确。
  • 已知边界,不在本单修:OTHER 在 VALID_STAFF_TYPES 里,业务能把 OTHER 写进某个位的字典再删掉,那一形态仍走静默放行。判据是:OTHER 的常态化就是不属于任何配置位,把它移出豁免闭集会拒掉每一次正常的杂项人员配置;而「把『其他』纳入『导游位』」本身是配置位语义的误用(等于宣告「其他类型的人算导游」),错的是那行字典。
  • 存量脏行的连带影响(本单不修,但必须知道):字典行被删之后库里已有的 staff_role='GUIDE_ASSISTANT' 行不再属于任何配置位,整位守卫 582116 也判不到它,这些行不会被 scopeRoles 的删除窗口覆盖或重建。⚠️ 更要紧的是:这类存量行会被前端原样回显提交,而校验是逐行做的——只要该团期的保存请求里带上这样一行且 staffRole 仍在缺口集合内,整次保存(含不传 scopeRoles 的整期覆盖)都会返回 582117。是否已有这类存量行未在本次取证中统计(生产库只读盘点属独立动作)。治理另立工单。
  • 缓存窗口:typesOf 是固定 5 分钟 TTL 的实例本地缓存(@VettedLocalCache)。字典改完到全部实例生效之间,同一请求可能一台放行、一台返回 582117。所以「删回后不再静默放行」是有界结论:最长 5 分钟、按实例收敛。
  • 判据不认识「历史」:requiresSlotMembership 只看字典当前内容。因此「从没在任何配置位字典里出现过」与「加过又被删回」走同一条拒绝分支,而文案一律写成「是否被误删」。首次配置某类人员(业务还没往字典加那一行)时会看到这句——正确动作是去对应配置位字典加一行,不是去查删除记录。

六.5、枚举 / 数据字典

staffRole(取值域来自 BatchStaffConfigReqVO.STAFF_ROLE_PATTERN)

所属字段: staffList[].staffRole / scopeRoles[] | 类型: String

下表说的是「该角色在配置位字典里查不到归属位时」修复后走哪条分支。分母就是从 @Pattern 常量抄下来的这 8 个(并有单测 GroupBatchStaffRoleSlotGuardTest#patternValueDomain_classifiedOneByOne 机械守住:常量改了而表没跟,用例先红)。

取值 分支 理由
GUIDE 拒绝 582117 导游位内置成员;默认字典下查得到位,查不到说明那一行被删了
LEADER 拒绝 582117 同上(导游位并收导游与领队)
PHOTOGRAPHER 拒绝 582117 摄影位内置成员;查不到说明那一行被删了
GUIDE_ASSISTANT 拒绝 582117(本单新增覆盖) 只可能靠字典被纳入配置位;「加过再删回」正是本单修的形态
STUDY_TEACHER 拒绝 582117(本单新增覆盖) 同上
LIFE_TEACHER 拒绝 582117(本单新增覆盖) 同上
DRIVER 放行 结构性豁免:车务派车投影产生,资源域没有这个人员类型,也配不进任何位的字典
OTHER 放行 + 已知边界 结构性豁免:常态就是不属于任何配置位,保护它会拒掉正常的杂项人员配置。代价是「OTHER 被某位字典纳入后再删掉」仍静默放行,本单不修

六.6、修改前后对比

行为级对比

行为 改前 改后
staffRole=GUIDE_ASSISTANT(字典里查不到归属位) 静默 200 + 落库 + 异步扇出,582114 当场失效 582117,零写入
staffRole=STUDY_TEACHER / LIFE_TEACHER(同上) 同上 582117,零写入
staffRole=LEADER 被从非空字典删掉 582117(#8148 已建立) 不变
staffRole=DRIVER / OTHER 放行 不变
字典读挂 / 读空(内置角色) 回落内置默认值,放行 不变
字典读挂 / 读空(字典角色 GUIDE_ASSISTANT 等) 静默 200 582117,零写入(降级态无法区分「被删掉」与「读不到」,见「六、边界行为」)
判据实现 participatesInSlotsByFallback 读编译期常量 fallbackTypes() requiresSlotMembership 判「不在结构性豁免闭集 {DRIVER, OTHER} 里」
路径 / 入参 / 权限 / 成功响应结构 — 零变化

字段级对比

无字段变化(BatchStaffConfigReqVO 只增加 javadoc,BatchStaffConfigRespVO 未动)。


六.7、影响评估

  • 是否破坏向后兼容: 否(契约零变化)。但存在面向管理后台的行为变化:原本能保存成功的几个角色的请求会开始被 582117 拒——那批请求本就是脏数据(角色没有任何人员类型校验背书)。
  • 前端是否必须同步上线: 否。5821xx 这一族在 hl-ui v2.1 上没有专门分支,统一由 src/utils/request.js 的响应拦截器按「code 非成功值」toast 后端 message,故 582117 在这几个角色上出现时前端零改动即有基本行为(文案本身已是可直接展示的完整句子,并指向修复动作所在处)。
  • 前端可选优化:命中 582117 时提示语可引导运营去「配置位字典」页面,并保留用户已填表单;不引导也不会误操作(重试仍会被拒)。
  • 前端 workaround 清理点: 无。

七、不影响范围

  • 零影响:
    • 路径、HTTP 方法、权限码、网关配置
    • 入参字段、类型、必填性、@Pattern 取值域
    • 成功响应结构与字段
    • 候选人查询(/staff/candidates、/staff/candidates/page)与配置列表查询(GET /staff)
    • 报账人等级设置口 PUT /v3/admin/group-batch/{productBatchId}/staff/{staffId}/reporter-rank
    • 子订单自己单独派的人员(order_staff_assignment 中 source 非 GROUP_BATCH 的行)
    • 582114 / 582115 / 582116 / 100503 四个既有码的触发条件与文案
    • assertScopeCoversWholeSlots(582116)与 scopeRoles 的任何判定逻辑
    • DRIVER / OTHER 的放行口径
    • 数据库表结构与 Flyway(本单无表变更、无迁移脚本)
    • 小程序端(团期人员配置无小程序写口)

八、测试环境已验证

2026-09-23,api.test.1814.love:9443(网关),分支 dev-v3,order-v3 活体 f6d21648b(双实例 8086 / 8186,滚动部署后均 UP)。

取证批次: productBatchId=2102640646949105666(#8123 / #8148 同一条取证批次),人员 staffId=1002(资源域真实 staffType=GUIDE)。

项 请求 结果
探测前快照 GET /v3/admin/group-batch/2102640646949105666/staff 200,1 行(staffId=1002, staffRole=GUIDE)
本单核心(修复后) PUT 同端点,{"staffList":[{"staffId":1002,"staffRole":"GUIDE_ASSISTANT"}]} HTTP 200,code=582117,message「角色 GUIDE_ASSISTANT 未归属任何人员配置位,无法校验人员类型;请检查配置位字典是否被误删」
零写入 上一步之后 GET 同端点读回 与探测前快照逐字段一致(拒绝路径未注册 afterCommit 扇出回调,未进事务段)
阴性对照(DRIVER) PUT {"scopeRoles":["DRIVER"],"staffList":[{"staffId":1002,"staffRole":"DRIVER"}]} HTTP 200,code=200 成功
阴性对照(OTHER) PUT {"scopeRoles":["OTHER"],"staffList":[{"staffId":1002,"staffRole":"OTHER"}]} HTTP 200,code=200 成功
现场还原 PUT {"scopeRoles":["DRIVER","OTHER"],"staffList":[]} 200;读回与探测前快照逐字段一致

测试环境上无法构造、因此未取活体样本的两项(原因是环境性的、与实现无关):

  • AC-3「字典读挂回落内置默认值」:需要让测试服的 DictFeignClient 整体失败,属环境级故障注入,会波及同环境其他使用者。该行为由真库用例 GroupBatchStaffSaveConfigSlotCompletenessMysqlTest#saveConfig_dictFeignFails_fallbackKeepsSlotRolesAccepted 与单元用例 GroupBatchStaffRoleSlotGuardTest#dictUnavailable_fallbackKeepsBuiltInRolesAccepted 覆盖(真实解析器 + 打桩 Feign,回落链路真跑)。
  • AC-4 的测试服活体样本(把内置角色从仍非空的配置位字典里删掉):字典是全站共享数据,删行的副作用会落到所有人的角色下拉框上,未构造。该行为由真库用例 #saveConfig_dictDropsLeaderFromGuideSlot_mismatchedStaffTypeRejectedNotSilentlySkipped 覆盖。

证据文件(脱敏、非空,已登记进 task capsule 的 evidence manifest):D:/work2/.tmp/issue8194/evidence/(gateway-verification.json / gateway-8194.log / gw-1-before.json … gw-5-after-cleanup.json / gw-summary.json)。


十、相关文档

  • Issue #8194(本单)、#8148(582117 的引入与残留缺口)、#8122(582116 整位覆盖守卫)、#7079(配置位字典化)
  • PR #8259(squash 提交 f6d21648b)
  • 同端点上一版条目:changelogs-v2/2026-09/23_8123_团期staff保存新增并发抢锁与配置位字典守卫错误码-修改接口-管理后台.md
  • 错误码定义:hl-order-service-v3/src/main/java/com/hulalv/order/assignment/errorcode/AssignmentErrorCode.java(582117)
  • 判据与豁免闭集:hl-order-service-v3/src/main/java/com/hulalv/order/assignment/service/GroupBatchStaffSlotResolver.java(STRUCTURALLY_SLOT_EXEMPT_ROLES / requiresSlotMembership)

关联 / 联系人

链接

  • Issue: #8194
  • PR: #8259
  • Merge commit: f6d21648bada5d0d465cd454390ba6bad923869a

联系人

  • 后端负责人: @wx
  • 前端: mmg(582117 提示语可引导至配置位字典页面,非必须)