Skip to content

docs: three visibleWhen binding claims are now wrong in the other direction — objectui bound current_user on form section/field predicates (objectui#6010) #11740

Description

@yinlianghui

Filed unassigned, no domain:* — triage owns grading and routing.

Blocked-by: ✅ discharged — objectstack-ai/objectui#6010 landed as objectui PR #6037 (fix(components): bind current_user on form section/field visibleWhen, merged 2026-08-24). This card is the documentation half that card's own dispatch reserved for the accepting seat, filed at landing time as instructed and deliberately not carried as a rider on the objectui PR.

Filed by the objectui domain:ui PM seat (session session_01CSoz9uGhaaSgiq3hshtN7L, R38).

What changed upstream

Until objectui#6010, form section/field visibleWhen predicates bound only record and previouscurrent_user was unbound, so a predicate naming it faulted open and showed the field to everyone. Page components, app/nav visible, and per-option visibleWhen all bound it. #11034 split this repo's binding table precisely to document that asymmetry, which was the honest thing to do at the time.

objectui#6010 removed the asymmetry. All five authored-predicate call sites in the form renderer now receive the predicate scope — the three resolveFieldRuleState calls plus the two visibleOn evalFieldPredicate calls (ADR-0089 D2 folds visibleOn into visibleWhen at parse, so binding one and not the other would have reproduced the defect one spelling over). It was graded a declared≠enforced restoration against ADR-0089 D1, which rules verbatim: "runtime record surfaces bind record + current_user; metadata-editing forms bind data."

⚠️ So the rows added by #11034 are now wrong in the opposite direction: they document an asymmetry that no longer exists.

Three corrections, in two files

The objectui dev who implemented #6010 searched this repo and found the claim in two places, not one. ⚠️ A card naming only layout-dsl.mdx would leave the second live — which is the same half-fix problem, one layer up.

1. content/docs/protocol/objectui/layout-dsl.mdx — the binding table at :831-832 and the prose at :866. These are the rows #11034 split. Form section/field predicates now bind current_user like every other runtime record surface.

2. content/docs/ui/views.mdx:433 carries the same claim independently, verbatim:

"runtime forms bind record (+ previous, parent) — not current_user, which is unbound at field level and would fault the predicate open"

⚠️ This one is not a cross-reference to (1); it is a second copy that has to be corrected on its own.

3. content/docs/protocol/objectui/layout-dsl.mdx:862-863 — a bare-string authoring trap, adjacent but distinct. This is not about the binding; it is about the dialect, and it is worth fixing while the page is open because the example on it is the exact shape that breaks:

  • the objectui form renderer treats a bare string predicate as CEL (fieldRules.ts toExpression defaults dialect to 'cel');
  • SchemaRenderer.evaluateCondition routes bare strings to the legacy JS evaluator, which has no in operator and rejects it — measured verbatim: Unexpected token "i" at position 16 — and then fails open;
  • this is deliberate and documented (objectui#2661: "Bare strings and template forms stay on the legacy path (back-compat deprecation window); only an explicit { dialect: cel } envelope is rerouted"), and spec parse emits the CEL envelope for authored metadata, so production is unaffected;
  • ⚠️ but layout-dsl.mdx:862-863 shows exactly that bare string, carrying the CEL membership operator, on a PageComponent / app-nav entry. A reader copying it authors a predicate that is not portable across surfaces.

✅ The residual is therefore a docs problem, not a code one — recorded as measured behaviour rather than filed as a defect. It caught the objectui dev's first pin run, which is how it surfaced.

Suggested scope

Correct (1) and (2) to state the current binding, and re-author the example in (3) into the canonical { dialect: 'cel' } envelope (or drop the membership operator from the bare-string example). ⛔ Do not re-merge the table rows #11034 split without checking whether any other asymmetry it documents is still live — the split may still be earning its keep for a different pair.

Pointers

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions