Skip to content

Commit efc0b4a

Browse files
committed
fix(spec): root the remaining validation.zod.ts example predicates at record. and un-invert the cross_field describe example
Example 2 (`discount > (amount * 0.40)`) and the header script example (`discount_percent > 0.40`) named bare fields, which the evaluator does not bind. The CrossFieldValidationSchema.condition description gave `record.end_date > record.start_date`, which under TRUE-is-violation refuses every valid end-after-start range; it now gives the violation, `record.end_date < record.start_date`, and says a TRUE condition fails validation. Documentation text only. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QcAS3qiYYZNezaxZxaUdMV
1 parent ec694f0 commit efc0b4a

2 files changed

Lines changed: 8 additions & 5 deletions

File tree

‎.changeset/20252-cross-field-salesforce-examples-cel.md‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22
"@objectstack/spec": patch
33
---
44

5-
The two `cross_field` "Salesforce Examples" in the `CrossFieldValidationSchema` TSDoc (`packages/spec/src/data/validation.zod.ts`) now show a `condition` the evaluator accepts, so an author or agent who copies the documented "ObjectStack Equivalent" gets a rule that evaluates, and Example 1's rule fires on the records it names as invalid (#20252).
5+
Every example predicate in `packages/spec/src/data/validation.zod.ts` now reads fields through the `record.` root and describes the violation, so an author or agent who copies one gets a rule that evaluates and fires on the records it names as invalid. The fix covers the three `cross_field` "Salesforce Examples" in the `CrossFieldValidationSchema` TSDoc, the header `script` example, and the `.describe()` example on `CrossFieldValidationSchema.condition` (#20252).
66

77
Clause-②: no
88

99
- Example 1, "Close Date Must Be In Current or Future Month": `MONTH(close_date) >= MONTH(TODAY()) AND YEAR(close_date) >= YEAR(TODAY())` becomes `date(record.close_date) < addDays(today(), 1 - today().getDate())`. The old string did not parse (`AND` is not CEL, and `close_date` had no `record.` root). It was also inverted: a `cross_field` condition that evaluates TRUE is the violation, and the old condition was TRUE on the records the rule should accept. The new condition is TRUE when the close date falls before the first day of the current month. It uses only the formula stdlib's `date()`, `today()` and `addDays()` plus CEL's built-in `getDate()` timestamp accessor.
10+
- Example 2, "Discount Validation": `discount > (amount * 0.40)` becomes `record.discount > (record.amount * 0.40)`. The bare fields were unknown variables. The direction is unchanged.
1011
- Example 3, "Opportunity Must Have Products": `products = null AND stage = "closed_won"` becomes `isBlank(record.products) && record.stage == "closed_won"`. A lone `=` is a CEL parse error and `AND` is not CEL. The direction is unchanged.
12+
- The header `script` example: `discount_percent > 0.40` becomes `record.discount_percent > 0.40`. The bare field was an unknown variable. The direction is unchanged.
13+
- The `CrossFieldValidationSchema.condition` description: its example `record.end_date > record.start_date` refused every valid end-after-start range, because a TRUE condition is the violation. It becomes `record.end_date < record.start_date`, and the description now says that a TRUE condition fails validation.
1114

12-
The Salesforce-formula side of each example is unchanged. This is TSDoc text only, with no schema, behaviour or export change.
15+
The Salesforce-formula side of each example is unchanged. This changes documentation text only (TSDoc and one `.describe()` string, with the generated reference page regenerated to match). There is no schema, behaviour or export change.

‎packages/spec/src/data/validation.zod.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ import { MetadataProtectionFields } from '../kernel/metadata-protection.zod';
9797
* {
9898
* type: 'script',
9999
* name: 'discount_cannot_exceed_40_percent',
100-
* condition: 'discount_percent > 0.40',
100+
* condition: 'record.discount_percent > 0.40',
101101
* message: 'Discount cannot exceed 40%',
102102
* severity: 'error'
103103
* }
@@ -254,7 +254,7 @@ export const FormatValidationSchema = lazySchema(() => strictObject({
254254
* {
255255
* type: 'cross_field',
256256
* name: 'discount_limit',
257-
* condition: 'discount > (amount * 0.40)',
257+
* condition: 'record.discount > (record.amount * 0.40)',
258258
* fields: ['discount', 'amount'],
259259
* message: 'Discount cannot exceed 40% of the amount'
260260
* }
@@ -291,7 +291,7 @@ export const CrossFieldValidationSchema = lazySchema(() => strictObject({
291291
}, {
292292
...BASE_VALIDATION_SHAPE,
293293
type: z.literal('cross_field'),
294-
condition: EvaluatedExpressionInputSchema.describe('Predicate (CEL) comparing fields. e.g. P`record.end_date > record.start_date`'),
294+
condition: EvaluatedExpressionInputSchema.describe('Predicate (CEL) comparing fields. If TRUE, validation fails — the condition describes the violation. e.g. P`record.end_date < record.start_date` refuses an end date before the start date.'),
295295
fields: z.array(z.string()).describe('Fields involved. Only fields[0] is read (labels which field the violation attaches to); the rest are advisory. Shares script’s evaluation path.'),
296296
}));
297297

0 commit comments

Comments
 (0)