You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Filed from objectui#6958 while working that card. Central triage asked for it explicitly and declined to open it itself, because it needs this lane to confirm whether each default is deliberate (objectui#6958 comment 5547207212):
visibleWhenfails OPEN (an unevaluable predicate renders the field visible) while requiredWhenfails CLOSED (an unevaluable predicate demands nothing). Both defaults are individually defensible; together they mean a typo in a predicate silently produces a more permissive form in both directions.
⛔ Not fixed on #6958 — different mechanism, and #6958's change deliberately leans on the fail-open half (a broken predicate must never silently null a stored column).
Measured on main
packages/core/src/evaluator/fieldRules.ts, resolveFieldRuleState — the third argument of evalFieldPredicate is the fallback used when the predicate cannot be evaluated:
visibleWhen → fallback true ⇒ the field is SHOWN
readonlyWhen → fallback false ⇒ the field is EDITABLE
requiredWhen → fallback false ⇒ the field demands NOTHING
⇒ It is not one asymmetry between two keys; it is that all three fallbacks point the same way — the permissive one. A single unbound root or misspelled column in one authored predicate therefore produces a form that shows more, locks less and demands less, all from the same fault, and the three faults compose rather than cancel.
Why it is worth a card and not a shrug
The failure is per-predicate, so an author who mistypes one column name gets a form that still renders and still submits. There is no state in which the form says "this rule did not run".
The server does not backstop two of the three. requiredWhen is re-enforced by @objectstack/objectql's rule validator, so a fail-closed client is merely annoying there; visibleWhen is not a server concept at all (stated in that file's own header), so its fallback is the only verdict there is.
What this card wants decided
Per-key, in this lane, with the reasoning recorded:
Is each fallback deliberate, or is at least one of them an accident of the shared helper's signature?
If deliberate, do they belong in the authored contract (@objectstack/spec / ADR-0089) rather than only in this function's argument list, so a producer can read what a broken predicate does before shipping one?
Is there a case for a loud-but-safe middle — e.g. a faulted visibleWhen keeps failing open (a hidden field an author cannot reach is worse) while a faulted requiredWhen fails to "required", where the cost is a blocked submit the user can see rather than a row that quietly skipped a rule?
Deliberately no recommendation here: this is the confirmation step triage asked for, not a proposal.
Dedup
Searched this repo before filing; one related card, and it is closed and narrower: objectui#4051 (visibleWhen/visibleOn fail open and silently — the silence half is fixed). A control query in the same session returned objectui#6958 itself, so the search channel was answering.
Filed from objectui#6958 while working that card. Central triage asked for it explicitly and declined to open it itself, because it needs this lane to confirm whether each default is deliberate (objectui#6958 comment 5547207212):
⛔ Not fixed on #6958 — different mechanism, and #6958's change deliberately leans on the fail-open half (a broken predicate must never silently null a stored column).
Measured on
mainpackages/core/src/evaluator/fieldRules.ts,resolveFieldRuleState— the third argument ofevalFieldPredicateis the fallback used when the predicate cannot be evaluated:visibleWhen→ fallbacktrue⇒ the field is SHOWNreadonlyWhen→ fallbackfalse⇒ the field is EDITABLErequiredWhen→ fallbackfalse⇒ the field demands NOTHING⇒ It is not one asymmetry between two keys; it is that all three fallbacks point the same way — the permissive one. A single unbound root or misspelled column in one authored predicate therefore produces a form that shows more, locks less and demands less, all from the same fault, and the three faults compose rather than cancel.
Why it is worth a card and not a shrug
warnPredicateFailure, governance: agent-instruction files are human-merge only — AGENTS.md carries the governed-surface rule #5149). It did not touch the DIRECTION, and it only ever consideredvisibleWhen/visibleOn.requiredWhenis re-enforced by@objectstack/objectql's rule validator, so a fail-closed client is merely annoying there;visibleWhenis not a server concept at all (stated in that file's own header), so its fallback is the only verdict there is.What this card wants decided
Per-key, in this lane, with the reasoning recorded:
@objectstack/spec/ ADR-0089) rather than only in this function's argument list, so a producer can read what a broken predicate does before shipping one?visibleWhenkeeps failing open (a hidden field an author cannot reach is worse) while a faultedrequiredWhenfails to "required", where the cost is a blocked submit the user can see rather than a row that quietly skipped a rule?Deliberately no recommendation here: this is the confirmation step triage asked for, not a proposal.
Dedup
Searched this repo before filing; one related card, and it is closed and narrower: objectui#4051 (
visibleWhen/visibleOnfail open and silently — the silence half is fixed). A control query in the same session returned objectui#6958 itself, so the search channel was answering.