Skip to content

flow designer: the Start node's Entry condition is raw-CEL-only — ConditionBuilder ships in five other inspectors but not the one condition most users meet #11940

Description

@yinlianghui

What

ConditionBuilder — the row-based visual condition editor that compiles to CEL (field · operator · value rows joined by && / ||, with a raw-expression editor as the fallback mode) — is wired into five inspectors:

  • views/studio-design/ObjectValidationsPanel.tsx (validation rules)
  • views/metadata-admin/inspectors/PageBlockInspector.tsx (visible-when)
  • views/metadata-admin/inspectors/HookDefaultInspector.tsx (hook condition)
  • views/metadata-admin/inspectors/ActionDefaultInspector.tsx (visible-when / disabled-when)
  • views/metadata-admin/widgets.tsx

It is not wired into the flow designer. inspectors/flow-node-config.ts declares the Start node's gate as

cfg('condition', 'Entry condition', 'expression', {
  placeholder: 'status == "qualifying" && previous.status != "qualifying"',
  help: 'CEL predicate — the flow runs only when this is true …',
})

and FlowNodeConfigField.tsx renders kind: 'expression' through the same branch as plain text — a single-line mono VariableTextInput. So authoring a record-change flow's entry gate means hand-writing CEL into a narrow one-line box, with no row builder, while authoring a validation rule two panels over gets the visual builder.

Why it matters

The flow entry condition is arguably the most user-facing predicate in the product — it is the thing a business admin sets when they build an approval or automation in Studio, and the flow designer is sold as the visual authoring surface. Today that surface's central decision is the one place that demands raw CEL.

Practical consequences observed while authoring contract_term_review in Studio (real run, HotCRM demo org):

  • A realistic create-or-update gate is long enough to be truncated in the one-line fieldcontract_term_months > 24 && (previous == null || previous.contract_term_months <= 24) is unreadable in place, so you cannot review what the flow gates on without selecting the text or reading the metadata.
  • The previous == null create-path idiom (documented only in the field's help) is exactly the kind of thing a row builder would offer as a choice instead of requiring recall.
  • The inconsistency is visible to a single user in a single session: same product, two condition fields, two entirely different authoring experiences.

Suggested fix

Wire the flow node inspector's expression fields (at minimum the Start node's condition; decision branch conditions have the same shape) to ConditionBuilder, keeping its raw-expression mode as the escape hatch for predicates the row builder cannot express. That yields one condition-authoring experience across validations, hooks, actions, page blocks and flows — and the compiled output is the same CEL the runtime already evaluates, so nothing downstream changes.

Provenance

Found while fact-checking a promo video's on-screen claims against the running product (video-studio #4): the film demonstrates a business admin drawing an approval flow in the designer, and the threshold-change beat had to be rendered as a magnified code card because the product's own field shows a truncated CEL string. The product owner asked whether presenting the condition as code was the right thing to show — this issue is the answer: it is accurate today, and it is the gap worth closing.

Filing as a finding — unassigned, not claimed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions