Skip to content

userFilters.allowAddTab 是 objectui 真读、spec 从未声明的活能力 —— promote 还是 reject?(挡住 #4001 批 18 的 UserFiltersSchema 收紧) #5073

Description

@xuyushun441-sys

发现于 #4001 批 18。这条挡住 UserFiltersSchema 的收紧,而那是批 6e 点名留开、批 18 被指派去验证的那个形状。批 18 已把 6e 的验证做完(结论见下),卡点不是 strictness,是一条能力声明问题。

事实(实测,非阅读推断)

objectui 的 plugin-list 渲染器真读allowAddTab:

  • packages/plugin-list/src/UserFilters.tsx:182 —— allowAddTab={config.allowAddTab}
  • 同文件 :742 —— {allowAddTab && ( … )},渲染「新增 tab」控件
  • objectui 自己的 UserFiltersSchema(packages/types/src/zod/objectql.zod.ts:265)声明了这个键

spec 的 UserFiltersSchema(packages/spec/src/ui/view.zod.ts)没有声明它。两边差集恰好就这一个键。

为什么它今天是「工作的」而不是「已经被吃掉的」

这一点是本条的关键,也是它与战役常规目标形状的区别:

saveMetaItemsafeParse 校验,然后原样存原始 body —— parsed.data 被丢弃。packages/metadata-protocol/src/protocol.ts 的 "Validation policy" 写得很明确:

We do NOT replace the persisted document with parsed.data; the original payload is stored verbatim so Studio-only auxiliary fields (e.g. isPinned, isDefault, sortOrder) survive the round-trip.

所以作者写的 allowAddTab 被 strip 掉的只是那份被丢弃的解析结果;存储里键还在,objectui 读到它,控件真的渲染出来

结论:收紧 UserFiltersSchema 不是「把静默失效变响亮」,是把一个已发布、今天能用的能力变成 422。 这与战役的授权(#4001 正文:杀掉静默剥离造成的虚假完成)方向相反,所以批 18 停手立案,没有猜。

需要裁定

allowAddTab 应当:

  • A. Promote 进 spec 的 UserFiltersSchema(additive,非破坏),然后收紧。
  • B. 判为 objectui-only 扩展,记进 objectui 的 SANCTIONED_LOCAL 并加理由,spec 收紧后明确拒绝它(需要同时决定 objectui 侧怎么继续支持存量配置)。

⚠️ 这不是我们发明的分叉。objectui 自己的漂移闸门把这个选择原样交给人:

When one of these fails, do NOT just edit the sets to make it green — decide whether the field belongs upstream in @objectstack/spec (promote it) or is a genuine objectui-only extension (add it to SANCTIONED_LOCAL with a rationale). See #2231.
—— objectui/packages/types/src/__tests__/list-view-spec-parity.test.ts

两轴分析

长期健全性(本项目 / 北极星):A 更对。这是 metadata-driven 框架,packages/spec 是生产者与渲染器之间唯一的契约(Prime Directive #12)。一个渲染器读、契约不声明的键,正是 PD#10 说的「declared ≠ enforced」的镜像面 —— 能力存在但契约装作没有。B 把这个分歧固化成第二套事实来源(spec 一份、objectui 一份),而 #2231 当初做 derive-by-reference 统一,就是为了消掉这类分叉。

让 AI 写的元数据难写错:也偏 A,但要看怎么做。A 之后 allowAddTab声明的,JSON Schema 会带上它,Studio 的 SchemaForm 能渲染它,AI 作者从 schema 就能发现这个能力 —— 而今天它只存在于一个 React 文件里,只有读过 objectui 源码的人知道。B 的风险是:strict 拒绝一个渲染器明明支持的键,作者照错误提示删掉它、能力消失,而拒绝信息本身是「正确」的 —— 这正是本战役 finding 7 反复踩的「平台权威把作者引向坏结果」。

两轴不冲突,我推荐 A。 但它是 additive protocol 变更(新增可授权键),按战役自己在 #5022 之后立的规矩,能力声明问题立案不猜,所以由维护者定。

补充:A 是 additive,不占 v17 破坏性窗口,理论上任何时候都能做;但 UserFiltersSchema 的收紧破坏性的,若希望它进 v17,A 需要先落地。

顺带:批 6e 的验证结论(已完成,不必重做)

6e 留开时问的是「是否有人靠这个 strip 来收窄 page 形状的块」。有,而且就在同一个文件里:ObjectUserFiltersSchema = UserFiltersSchema.omit({ tabs: true, showAllRecords: true }),.omit() 继承基类姿态,所以关掉基类会把 object-list-view.test.ts 那条钉从「drops the page-only keys」翻成「rejects」。

那个翻转是想要的:packages/lint/src/validate-list-view-mode.ts 早就在报 object view 上带 tabsuserFilters,所以今天两扇门互相矛盾 —— 兄弟守卫在警告,schema 在静默丢弃。收紧让两扇门一致。这条不构成阻塞,阻塞的只有 allowAddTab

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions