Skip to content

[Decision] Should the server-side required check read a form section visibleWhen predicate? (objectui#6237 semantic 1, cross-repo half) #13252

Description

@claude

Filed by the objectui domain:ui execution seat (PM session session_01CRJge11jso9TpXRWFt1Z49), file-at-destination: any fix lands in packages/objectql, so the card lives here rather than in objectui.

Source. The ruling on objectui#6237 (2026-08-29, option A — one grouping contract with a predicate slot) names three semantics. Semantic 1 says a hidden group's fields skip client-side validation, with the server as the loud floor. Implementing the tabbed arm (objectui PR #6791) raised the cross-repo half of that: does the server-side required check read the same predicate?

The measurement

Verified by this seat on objectstackorigin/main at 7404925, not relayed:

grep in packages/objectqlfiles
FormSection0
sections5 — all CHANGELOG or test fixtures passing view metadata through; none in src/validation/rule-validator.ts
visibleWhen8 — including src/validation/rule-validator.ts
control: validate53
control: required90
control: field255

The controls hit hard, so the FormSection zero is a real reading rather than a broken query.

⚠️Correcting the phrasing this came to me with. objectui PR #6791 reports it as "zero references to FormSection or sections". Exactly true for FormSection; loose for sections, which does appear — but only in CHANGELOG text and test fixtures, never in the rule validator. The substantive claim survives the correction intact.

And the visibleWhen that does live in the rule validator is per-option visibility (select / multiselect / radio / checkboxes), which this package's own CHANGELOG describes as gating written option values against each option's predicate. That is a different key on a different object from a form section's visibleWhen.

So: the server-side required check does not read a form section's predicate, and structurally cannot — the validator validates against the object's field definitions and never sees the form view.

The question

The ruled design is internally consistent as it stands: the client hides, the server rejects. The residual hazard is narrow and specific — a genuinely object-required field placed inside a predicate-hidden section. The author sees a form that cannot be completed and a server error that names a field they cannot see.

Do we close that, at the cost of a published validation-contract change in @objectstack/objectql?

做什么代价
A服务端保持现状,把这一条写成作者面的规则(对象必填字段不得放进带谓词的分组),由 objectui 侧的门禁或文档承担零服务端变更。风险:声明而不强制,正是这一族卡存在的原因
B让 objectui 侧在保存前就拒绝这种编排(表单校验读对象的 required 标志 + 分组谓词)不动已发布契约,把问题挡在作者面。但它是第二处判断,会与服务端漂移
C教服务端读表单谓词⛔ 已发布校验契约变更:验证器要开始消费 view metadata,而它今天完全看不到 form view。作用面远超本卡

四维分析

① 实际业务需求。⚠️零实测。 没有任何记录显示真有作者把对象必填字段放进了带谓词的分组。本卡描述的是一条推理出来的编排错误,不是一份事故报告。

② 平台长远合理性。 ⭐ 现状(客户端隐藏、服务端拒绝)是单一权威 + 纵深的正确形状:校验的唯一真相在服务端,表单只是绘制。C 反过来让服务端去消费一个表现层构件(form view),⇒ 那是把绘制语义灌进数据契约,方向是错的。A/B 都保住了「服务端是唯一底线」。

③ 防 AI 犯错。 ⭐ 分水岭。生成表单的 agent 完全可能把对象必填字段放进条件分组 —— 它看得见分组,看不见对象的 required 标志。⇒ 这一轴强烈指向 B(作者面早拒),而指向 C:AI 需要的是编排时的即时反馈,不是保存时来自服务端的、指向一个它看不见的字段的报错。

④ 创业阶段不扩散需求。 A 最省;B 有界,落在 objectui 一侧;C 是跨仓的已发布契约变更,压在一条零实测需求的路线上 —— 与 objectui#6780 拒绝 option C 是同一个理由。

本席意见:B,并且 ⛔ 明确不采 C。但本席是 objectui 侧,B 落在 objectui,⇒ 若裁 B,本卡的产出是一张 objectui 卡而不是本仓的代码改动。

⭐ 置信缺口

  1. ⚠️未清点:仓内(与 hotcrm)现有的表单里,有多少真的把对象必填字段放进了带谓词的分组。这个数字决定本卡值不值得做 —— 为 0 则 A 已经够。
  2. 未测:objectui 侧的表单校验今天能否看见对象的 required 标志。B 的可行性整个压在这一条上,本席没有验证它。
  3. 未测:服务端拒绝时的报错文本长什么样。若它已经点名了字段与原因,A 的代价比上表写的更低。

低摩擦裁决:回「A」「B」或「C」。

裁后执行:裁 A ⇒ 关本卡,把规则写进 objectui 的表单编排文档并指向本卡。裁 B ⇒ 关本卡,在 objectui 立执行卡(落点是表单校验层,不是 packages/objectql)。裁 C ⇒ 本卡转 pm:queue 留在本仓,⚠️ 需先补一份 view-metadata 消费面的设计。

Related

objectui#6237 (the ruling) · objectui PR #6791 (the tabbed arm, where this surfaced) · objectui#6619


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions