7.7 KiB
AI 合同平台 V2 Phase 3 旧 next_action alias 使用观测
背景
contracts.next_action / contracts.next_actions 已停止作为生产写路径使用,API 响应继续由 ContractActionContext 派生。
本片继续处理 cleanup migration 前的最后一段风险:确认是否仍有旧客户端在 PATCH 合同时提交:
next_actionnext_actions
当前结论仍是先观测,不删列、不移除响应字段、不移除旧写入口。
本次实现
新增轻量观测模块:
yuqei_contract_api.deprecated_alias_observability
合同 PATCH 入口现在会识别 ContractUpdateRequest.model_fields_set 中是否出现旧 alias 字段。
当请求包含旧字段时,系统会:
- 拒绝旧写入请求。
- 返回
422,提示改用action_hint。 - 不再将旧
next_action规范化为action_hint。 - 不再接受旧
next_actions输入。 - 写入一条结构化 warning 日志:
Deprecated contract update action alias used。 - 写入进程内观测窗口:
app.state.deprecated_alias_usages。
新增只读查询端点:
GET /api/v1/metrics/deprecated-aliases
GET /api/v1/metrics/deprecated-aliases?alias_group=contract_update_action
返回字段包括:
alias_groupfieldstarget_fieldcompatibility_statuscontract_idactor_name_presentendpointmethodtrace_idtenant_idtimestamp
隐私与安全边界
观测数据不记录旧字段的文本值。
例如旧请求:
{
"next_action": "legacy-next-action-value-should-not-be-logged",
"next_actions": ["ignored legacy button"]
}
观测记录只保留:
{
"fields": ["next_action", "next_actions"],
"target_field": "action_hint"
}
这样可以判断是否仍有旧客户端在使用 alias,同时避免把人工跟进提示、按钮文案等业务文本写入日志或指标。
cleanup migration 前置判断
后续进入删列或移除旧写入口前,建议至少满足:
- smoke / 准生产连续观测窗口内
contract_update_actionalias 使用量为 0。 - 日志采集侧没有
Deprecated contract update action alias used。 - 外部调用方确认不再提交
next_action / next_actions。 - 前端只提交
action_hint的 typecheck 和页面 smoke 仍通过。 - schema-check 继续明确旧动作列只是 retained compatibility fields。
观察窗口执行方式
新增只读观察脚本:
python yuqei-infra\scripts\watch-deprecated-alias-usage.py `
--base-url http://192.168.3.90:18100 `
--duration-seconds 1800 `
--interval-seconds 60
脚本会:
- 启动时读取一次
/api/v1/metrics/deprecated-aliases?alias_group=contract_update_action作为 baseline。 - 在观察窗口内持续轮询。
- 运行期间输出进度行:
CONNECT、START、每次POLL。 - 只判断窗口内新增的旧 alias 使用记录。
- 输出 JSON 报告。
- 默认把报告写入
project-docs/qa-artifacts/v2-deprecated-alias-observation/。
这样即使 smoke 环境里已经存在手工抽样记录,也不会影响后续观察窗口结论。
注意:--duration-seconds 1800 表示观察 30 分钟。脚本不会退出,直到窗口结束;正常情况下会先显示 baseline,然后每 60 秒显示一次类似:
DEPRECATED_ALIAS_OBSERVATION_POLL sample=2 elapsed_seconds=60.1 remaining_seconds=1739.9 baseline_total=1 final_total=1 observed_delta=0 relevant_new_count=0 max_allowed_new=0
如果要中止观察,可以按 Ctrl+C。
短窗口 smoke 可使用:
python yuqei-infra\scripts\watch-deprecated-alias-usage.py `
--base-url http://192.168.3.90:18100 `
--duration-seconds 5 `
--interval-seconds 2
验收口径:
status=passrelevant_new_count=0max_allowed_new=0DEPRECATED_ALIAS_OBSERVATION_PASS
如果需要在观察期间允许合成探针,可以用 trace 过滤:
python yuqei-infra\scripts\watch-deprecated-alias-usage.py `
--base-url http://192.168.3.90:18100 `
--duration-seconds 1800 `
--interval-seconds 60 `
--ignore-trace-prefix trace-deprecated-alias-smoke
注意:过滤只能用于明确标记的合成流量,不能用于隐藏真实客户端兼容调用。
验证
python -m pytest `
yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py::test_contract_update_accepts_action_hint_and_rejects_legacy_next_action `
yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py::test_contract_update_legacy_action_alias_usage_is_observable `
-q
结果:
- 旧 alias accepted 阶段:2 passed。
- Slice A 收紧后,测试名更新为:
python -m pytest `
yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py::test_contract_update_accepts_action_hint_and_rejects_legacy_next_action `
yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py::test_contract_update_legacy_action_alias_usage_is_observable `
-q
python yuqei-infra\scripts\watch-deprecated-alias-usage.py `
--base-url http://192.168.3.90:18100 `
--duration-seconds 5 `
--interval-seconds 2
结果:
DEPRECATED_ALIAS_OBSERVATION_PASS。baseline_total=1。final_total=1。observed_delta=0。relevant_new_count=0。- artifact:
project-docs/qa-artifacts/v2-deprecated-alias-observation/deprecated-alias-observation-2026-07-01T22-33-31.json。 - 脚本已兼容远端宿主机
Python 3.6.8,并可在192.168.3.90直接执行:baseline_total=1final_total=1observed_delta=0relevant_new_count=0DEPRECATED_ALIAS_OBSERVATION_PASS
- 脚本已改为默认显示观察进度,远端 3 秒 smoke 输出了
CONNECT、START、3 次POLL和最终PASS。
远端 smoke 验证
环境:
- 宿主机:
192.168.3.90 - compose project:
yuqei-contract-v2-smoke - Contract API:
http://127.0.0.1:18100
部署结果:
contract-api已重建并启动。contract-api容器状态:healthy。/api/v1/runtime/schema-check返回status=ok。display_cache_consistency.mismatch_count=0。display_cache_consistency.checked_rows=12022。display_cache_consistency.retained_compat_fields=next_action,next_actions。
旧 alias 抽样:
- smoke 合同:
contract-41ab55e94fe4 - 请求字段:
next_action=legacy-alias-observability-smoke-value - 请求字段:
next_actions=["ignored legacy button"] - 响应字段:
action_hint=legacy-alias-observability-smoke-value - 响应字段:
next_action=legacy-alias-observability-smoke-value - metrics 初始值:
total=0 - metrics 抽样后:
total=1 - metrics item:
alias_group=contract_update_actionfields=["next_action","next_actions"]target_field=action_hintcompatibility_status=acceptedcontract_id=contract-41ab55e94fe4trace_id=trace-deprecated-alias-smoketenant_id=tenant-deprecated-alias-smoke
- metrics 中未出现旧字段文本值
legacy-alias-observability-smoke-value。 - 最近 10 分钟
Deprecated contract update action alias used日志计数为 1。 - 最近 10 分钟
Contract display cache mismatch日志计数为 0。
当前结论
旧 alias 使用已经具备可观测性。
30 分钟 smoke 观察窗口已通过:
- 执行时间:
2026-07-01T23:31:51+08:00至2026-07-02T00:01:51+08:00。 samples=31。baseline_total=1。final_total=1。observed_delta=0。relevant_new_count=0。reset_detected=false。- artifact:
project-docs/qa-artifacts/v2-deprecated-alias-observation/deprecated-alias-observation-2026-07-02T00-01-51.json。
这说明本轮观察窗口内没有新增旧 next_action / next_actions alias 调用。可以进入 cleanup migration 设计评审,但仍不建议直接删列。