ObjectStackObjectStack

Expression schema — Shared Protocol reference

Canonical wire format for all "expression"-shaped metadata across ObjectStack.

Expression Protocol

Canonical wire format for all "expression"-shaped metadata across ObjectStack (formula fields, predicates, conditions, criteria, visibility rules, seed dynamic values, …).

The persisted form is { dialect, source } (and, after objectstack compile normalization, { dialect, ast }). String-only shorthand is accepted at input time for developer ergonomics; build emits the canonical envelope.

Dialects

dialectengineuse
cel@objectstack/formula (cel-js + ObjectStack stdlib)formulas, predicates, seed dynamic values
cronnone at parse time — croner fires it at schedule time, on the one wired slotjob schedules
templateplaceholder interpolation at evaluate time (same variable scope as CEL); canonically {{var}}, but the accepted spelling belongs to the renderer, not to this schema — see TemplateExpressionInputSchemanotification subjects/bodies, titleFormat, prompt templates

No cron syntax is judged at parse time: croner evaluates a cron slot only when CronSchedule.expression is scheduled (toBoundaryJobSchedule → CronJobAdapter, where an invalid pattern is refused); every other cron-typed slot is parsed and reaches no engine, and @objectstack/formula's registered cron engine has no caller outside that package.

A TYPED slot — one declared with CronExpressionInputSchema or TemplateExpressionInputSchema, or with the same input carrying its own refusal sentences (a notify node's title / message) — takes a bare, non-blank string (shorthand for its own dialect) or an envelope declaring that one dialect. An envelope naming any other dialect, and a blank string, are refused at the slot with one issue whose message names the dialect and the fix; a template slot's fix is written in the placeholder spelling its renderer reads. Only the untyped ExpressionInputSchema takes every declared dialect in envelope form.

Those three are the whole list — it is exactly the ExpressionDialect enum below. Procedural JavaScript is not a dialect: it is the L2 authoring surface, the sandboxed, capability-gated ScriptBody { language: 'js' } in hook/action bodies. A js row stood in this table long after the dialect was retired in #3278 (ADR-0058 addendum); ExpressionSchema rejects dialect: 'js'.

SQL fragments (analytics joins, partial indexes) are intentionally not routed through this schema — they stay driver-native because their security posture and portability story differ.

See also: content/docs/concepts/north-star.mdx §8 "No private expression DSL"

Source: packages/spec/src/shared/expression.zod.ts

TypeScript Usage

import { CronExpressionInputSchema, EvaluatedExpressionSchema, EvaluatedExpressionInputSchema, ExpressionSchema, ExpressionDialect, ExpressionInputSchema, ExpressionMetaSchema, PredicateSchema, PredicateInputSchema, TemplateExpressionInputSchema } from '@objectstack/spec/shared';
import type { CronExpressionInput, EvaluatedExpression, EvaluatedExpressionInput, Expression, ExpressionDialect, ExpressionInput, ExpressionMeta, Predicate, PredicateInput, TemplateExpressionInput } from '@objectstack/spec/shared';

// Validate data
const result = CronExpressionInputSchema.parse(data);

CronExpressionInput

Union Options

This schema accepts one of the following structures:

Option 1

Type: string


Option 2

Properties

PropertyTypeRequiredDescription
dialect'cron'✅
sourcestringoptional
astanyoptional
meta{ rationale?: string; generatedBy?: string }optional


EvaluatedExpression

Properties

PropertyTypeRequiredDescription
dialectEnum<'cel' | 'cron' | 'template'>✅
sourcestring✅
astanyoptional
meta{ rationale?: string; generatedBy?: string }optional

EvaluatedExpressionInput

Union Options

This schema accepts one of the following structures:

Option 1

Type: string


Option 2

Properties

PropertyTypeRequiredDescription
dialectEnum<'cel' | 'cron' | 'template'>✅
sourcestring✅
astanyoptional
meta{ rationale?: string; generatedBy?: string }optional


Expression

Properties

PropertyTypeRequiredDescription
dialectEnum<'cel' | 'cron' | 'template'>✅
sourcestringoptional
astanyoptional
meta{ rationale?: string; generatedBy?: string }optional

ExpressionDialect

Allowed Values

  • cel
  • cron
  • template

ExpressionInput

Union Options

This schema accepts one of the following structures:

Option 1

Type: string


Option 2

Properties

PropertyTypeRequiredDescription
dialectEnum<'cel' | 'cron' | 'template'>✅
sourcestringoptional
astanyoptional
meta{ rationale?: string; generatedBy?: string }optional


ExpressionMeta

Properties

PropertyTypeRequiredDescription
rationalestringoptional
generatedBystringoptional

Predicate

Properties

PropertyTypeRequiredDescription
dialectEnum<'cel' | 'cron' | 'template'>✅
sourcestringoptional
astanyoptional
meta{ rationale?: string; generatedBy?: string }optional

PredicateInput

Union Options

This schema accepts one of the following structures:

Option 1

Type: string


Option 2

Properties

PropertyTypeRequiredDescription
dialectEnum<'cel' | 'cron' | 'template'>✅
sourcestringoptional
astanyoptional
meta{ rationale?: string; generatedBy?: string }optional


TemplateExpressionInput

Union Options

This schema accepts one of the following structures:

Option 1

Type: string


Option 2

Properties

PropertyTypeRequiredDescription
dialect'template'✅
sourcestringoptional
astanyoptional
meta{ rationale?: string; generatedBy?: string }optional


On this page