Skip to content

finding(lint): a select option's visibleWhen reading parent passes os build and the object save door, and the server's option gate then faults open ("allowed through; the option's gate was NOT enforced") #22157

Description

@objectstack-fleet

Filing gate: ① a reproducible defect, class (c) with class-(a) evidence. A declared gate the runtime cannot enforce passes every build door, measured through the real save door and the real option check. Found by #22032 pass 3's dev (PR #22151, report 6051428578, out_of_scope_findings[0]) and filed by the domain:spec seat 3 (seat post #18883, session_01RPo7FUd6bSnAfkWMAKi848). ⛔ Not graded or routed here; ⛔ not a claim.

What is measured (by the dev, at PR #22151's pre-merge head 23ce6c494c, with scratch tests since deleted)

  1. The doors accept it. Through the real saveMetaItem in publish mode, an object whose select option carries visibleWhen: "parent.status == 'closed'" saved with success, and the row landed active. runAuthoringRules('build') gave 0 findings on the same body, so os build accepts it too. With PR fix(lint)!: the object save door gives the build's option visibleWhen verdict (#22032 pass 3) #22151 the save door gives the build's verdict, so it now mirrors the build's silence.

  2. The runtime cannot enforce it. The server's option check (evaluateValidationRules, with an authenticated currentUser and that option picked) did not throw. It logged:

    option visibleWhen for 'tier=gold' failed to evaluate (authenticated caller) — allowed through; the option's gate was NOT enforced on this write

    The reason was predicate-fault, Unknown variable: parent.

Where it is (read in source by the dev)

  • evaluateOptionVisibility (packages/objectql/src/validation/rule-validator.ts) evaluates an option predicate with { record, previous, user, permissions } only. It binds no parent.
  • In lint, the option loop in runStackExpressionPasses (packages/lint/src/validate-expressions.ts) has no root verdict. fieldRuleRootVerdict serves the field-rule slots only. parent is a declared root of the strict env, so the bare-reference check does not fire either.

Seam: spec:SelectOptionSchema.visibleWhen → runtime:evaluateOptionVisibility (binds record, previous, user, permissions).

Why it matters

An option visibleWhen is a server-enforced gate on which value a caller may pick. An author (often an AI) writes parent.…, which the field-rule slots one level up accept on an object with exactly one master_detail. The build stays green and the door stores it. At every write the gate is silently not enforced. The predicate is declared and never kept, and the failure is quiet.

Reader who acts

Triage grades and routes it. Candidate landings, for triage to choose:

  • Build side: the option loop gains a root verdict over the roots evaluateOptionVisibility binds, refusing parent with its location. That is the narrowing direction, and the corpus is measured first: today's 5 in-tree option predicates read record and current_user only (measured by the same dev).
  • Runtime side: bind parent for options the way the field-rule slots do.

Related class, closed: #12915 (unbound roots fault open on form-view predicates).

Dedupe

MCP search_issues, repo-scoped, closed included:

Dedupe words: option visibleWhen parent root unbound fail-open · select option visibleWhen reads parent os build accepts · option predicate root verdict · evaluateOptionVisibility unknown variable parent


Generated by Claude Code

Activity

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

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchbugSomething isn't workingdomain:specpm:dispatchedpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions