Skip to content

Follow-up to #514: remaining behaviour fixes, conventions, and the action-sandbox test gap #575

Description

@yinlianghui

延续 #514(已关闭,17 条里约 2/3 已完成)。本 issue 只收剩下的部分,每条都已对照 main3ed27b26)逐一核实,不再需要去 #514 里考古哪些做过了。

分两类:A 组可以直接开工B 组需要先定方案


A 组 — 可直接开工(4 条,彼此文件面不重叠,可并行)

A1. 真实 QuickJS action 执行器(原 #514 项 17,剩余部分中价值最高)

test/helpers/ 已有 flow-harness.tshook-harness.ts,但 action 侧仍是 test/global-actions.test.ts 里的简易执行器——不是真实 QuickJS 沙箱,所以「body-only、不得读取模块作用域」这类约束测不出来。

具体要守住的一条现存约束(目前只活在注释里):src/objects/_line-item-price-fill.ts 的共享工厂只在 handler body 从不读取工厂参数时才安全——一旦读取,会在编写期解析、进 QuickJS 后变成 undefined#570 的作者自己在 PR 里 flag 了这点)。

这条的价值不止于测试覆盖:2026-07-31 当天出现过三次「PR 各自绿、合并后 main 红」,只有一次被测试自动抓住,另外两次(#547 悬空授权、#439 锁文件)靠人工发现。

A2. disqualification_reason 承诺了必填却零强制(原项 4)

src/objects/lead.object.ts:246 的字段 description 写着 "Required when status is Unqualified",但仓库里没有任何校验或 hook 实现它,也没有写入方。种子数据里有 3 条 unqualified 线索。

仓库内已有现成的实现范式:case.object.tsP 校验实现了同样的「状态为 X 时必填」。

A3. fieldGroups 缺失(原项 13)

crm_campaigncrm_task 都是有完整详情页的对象,但 fieldGroups 计数为 0(其余业务对象都有)。两个 line-item 对象没有可以接受。

A4. priority_rank 默认值分歧(原项 14)

crm_case.priority_rank 默认 1crm_task.priority_rank 默认 2,且 rank 映射表在两个 hook 里各写了一份——未知优先级在两个对象上排序结果不同。注意 test/metadata-references.test.ts 已经钉住了这一带,改前先看。


B 组 — 需要先定方案(4 条,请勿直接派给 agent

B1. 转换后线索保护:两套实现,保哪套?

  • lead.object.ts:311 的 validation:只锁 4 个身份字段,可恢复错误
  • lead.hook.ts:164 的 beforeUpdate 守卫:白名单之外全锁,抛错

注意:#514 原文说 hook「没有 ctx.user?.id 守卫」——这一条已经不成立,守卫已补上,注释里也写明了两者的分工意图(validation 管身份字段的友好报错,hook 管其余字段的硬拦截)。所以现在是「要不要保留这个有意的双层设计」,而不是「修一个缺陷」。选项:(a) 保留双层并把分工写进文档;(b) 合并成一套。

B2. 两个无写入方的 readonly 字段

  • crm_opportunity.created_date —— 平台已自动注入 created_at建议直接删;代价是 opportunity.view.ts:149startDateField 要改指 created_at,并清掉 zh-CN 两处翻译
  • crm_case.first_response_date —— 属于 SLA 叙事的一部分。这条是业务决策:服务团队真要这个指标 → 去掉 readonly 并在 case.hook 里接写入方(首次对外活动时打戳);没人看 → 删

B3. 40 个 changeset 堆积,无人消费

.changeset/ 下有 40 个待发布条目,没有任何 workflow 跑 changeset version/publish。要么定发布流程(打 tag 时跑),要么手工折进 CHANGELOG 并移除机制。改错会影响版本号,建议先跟发布节奏对齐。

B4. state machine 覆盖不全(feature-shaped)

15 个业务对象里只有 3 个(lead / opportunity / case)声明了 type: 'state_machine' 转换表;quote / contract / campaign / task 都有状态字段但没有转换约束。补不补是产品决策,不是缺陷修复。


给接手者的约定(2026-07-31 踩出来的)

  1. 动手前先核实问题仍存在 —— 本 issue 已核实到 3ed27b26,但 main 移动很快
  2. 新守卫写进新建的测试文件,不要追加到 test/metadata-references.test.ts(当天的高频冲突文件)
  3. 提交信息用 Refs,不要用 Closes/Fixes —— 除非该 PR 完整解决本 issue。[CRM] 9 个孤儿 __search 列待清理(17.0 收紧搜索伴生列供给条件后遗留) #528 当天就是被提交信息里的 Closes 误关的,改 PR 描述拦不住
  4. 必须附 changeset,否则 CI 的 Check Changeset 会红
  5. 合并后在 main 上复跑一次 pnpm verify —— 当天三次「合并时绿、落 main 才红」

Metadata

Metadata

Assignees

No one assigned

    Labels

    backendbugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions