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
A field-level requiredWhen / readonlyWhen that reads through a lookup (record.account.tier) is accepted at authoring, but the runtime never hydrates it, so since ADR-0137 D2 every write that reaches it is refused #20078
Filing gate: ① a product defect with a named landing site (a metadata-authoring trap: the authoring doors accept a predicate the runtime can only refuse). It was measured by the #19727 dev (os-dev-report 5821543547, out_of_scope_findings[0], class c). The domain:spec seat 4 (session_019c3Hi6ZMU1p6m6aA6Bz45d) re-read it at origin/main66960564d9, after PR #20028 landed as 5dba7f3bd0. Filed unassigned and unlabelled: routing and grading are triage's. Routing suggestion: domain:spec (the landing is packages/lint and/or packages/objectql). ⛔ Not a claim.
Hand that acts: the lane triage routes this to, in one claim.
Dedupe (including closed): the semantic query field-level requiredWhen readonlyWhen reads through lookup reference not hydrated refused at write returns 10 hits. None covers this. The nearest are #20007 (an optional lookup in a traversing validation rule, closed) and #19911 (readonlyWhen ordering, closed).
The defect (at origin/main66960564d9)
Authoring accepts it.
FieldSchema.readonlyWhen / requiredWhen are EvaluatedExpressionInputSchema (packages/spec/src/data/field.zod.ts:1733-1734), so a CEL source such as record.account.tier == 'gold' parses.
The lint pass serves a relationship traversal only for validation-rule conditions: packages/lint/src/validate-expressions.ts:1538-1541, "traversalHydration is passed here and NOWHERE else".
Per the dev's measurement, a field-level predicate that reads through a reference passes objectstack validate.
The runtime can only refuse it.packages/objectql/src/validation/rule-validator.ts:496-504 says so in as many words: the field-level requiredWhen / readonlyWhen / option visibleWhen predicates are not hydrated at all. So a field predicate that reads through a reference faults, and since ADR-0137 D2 (PR fix(objectql)!: a field-level requiredWhen / readonlyWhen that cannot be evaluated refuses the write (ADR-0137 D2) #20028) that fault refuses the write, with a sentence naming the reference (pinned in engine-field-predicate-fault.test.ts, lookup case).
So an author, or an AI, writes a predicate every authoring door accepts, deploys it, and then every write that reaches it gets refused. Fail-closed and loud is the right runtime direction (ADR-0137 D2). The defect is that authoring does not say so first.
In-repo census (the dev's): 0 such predicates in examples/** and the platform objects. Deployed metadata: NOT MEASURED.
Remedy shape (a choice for the implementing round or triage; not ruled here)
(A) Refuse at authoring. The lint pass, and ideally the same shared check the runtime uses, refuses a field-level predicate that reads through a reference, with a prescription (move the condition to a validations[]script rule, which is hydrated). That keeps "declared ⇒ enforced".
(B) Hydrate the field level, as checkPredicate already does for validation rules. rule-validator.ts:503-504 calls this "a capability of its own, not a consequence of D2", so it is a larger change.
Filing gate: ① a product defect with a named landing site (a metadata-authoring trap: the authoring doors accept a predicate the runtime can only refuse). It was measured by the #19727 dev (os-dev-report
5821543547,out_of_scope_findings[0], class c). Thedomain:specseat 4 (session_019c3Hi6ZMU1p6m6aA6Bz45d) re-read it atorigin/main66960564d9, after PR #20028 landed as5dba7f3bd0. Filed unassigned and unlabelled: routing and grading are triage's. Routing suggestion:domain:spec(the landing ispackages/lintand/orpackages/objectql). ⛔ Not a claim.Hand that acts: the lane triage routes this to, in one claim.
Dedupe (including closed): the semantic query
field-level requiredWhen readonlyWhen reads through lookup reference not hydrated refused at writereturns 10 hits. None covers this. The nearest are #20007 (an optional lookup in a traversing validation rule, closed) and #19911 (readonlyWhen ordering, closed).The defect (at
origin/main66960564d9)FieldSchema.readonlyWhen/requiredWhenareEvaluatedExpressionInputSchema(packages/spec/src/data/field.zod.ts:1733-1734), so a CEL source such asrecord.account.tier == 'gold'parses.packages/lint/src/validate-expressions.ts:1538-1541, "traversalHydrationis passed here and NOWHERE else".objectstack validate.packages/objectql/src/validation/rule-validator.ts:496-504says so in as many words: the field-levelrequiredWhen/readonlyWhen/ optionvisibleWhenpredicates are not hydrated at all. So a field predicate that reads through a reference faults, and since ADR-0137 D2 (PR fix(objectql)!: a field-level requiredWhen / readonlyWhen that cannot be evaluated refuses the write (ADR-0137 D2) #20028) that fault refuses the write, with a sentence naming the reference (pinned inengine-field-predicate-fault.test.ts, lookup case).requiredWhen) or let the change through (non-rootreadonlyWhen). After it, every write that reaches the predicate is refused.So an author, or an AI, writes a predicate every authoring door accepts, deploys it, and then every write that reaches it gets refused. Fail-closed and loud is the right runtime direction (ADR-0137 D2). The defect is that authoring does not say so first.
In-repo census (the dev's): 0 such predicates in
examples/**and the platform objects. Deployed metadata: NOT MEASURED.Remedy shape (a choice for the implementing round or triage; not ruled here)
validations[]scriptrule, which is hydrated). That keeps "declared ⇒ enforced".checkPredicatealready does for validation rules.rule-validator.ts:503-504calls this "a capability of its own, not a consequence of D2", so it is a larger change.Seam: spec
FieldSchema.requiredWhen/readonlyWhen→ runtimerule-validator.tsevaluateValidationRules/isReadonlyWhenLocked| lintvalidate-expressions.tstraversalHydration.Dedupe words:
requiredWhen lookup traversal authoring·field-level predicate reads through reference·readonlyWhen record.fk.field not hydrated·traversalHydration field ruleGenerated by Claude Code