Skip to content

Statements

Statements are named, reusable boolean predicates stored on an entity definition. A statement captures one operational fact — overdue, blocked, eligible, needs review — as a single boolean expression, so screens, filters, and logic share one definition of that fact instead of repeating slightly different conditions in different places.

The expression is validated against the entity’s current schema when it is saved, then compiled to PostgreSQL. Runtime queries evaluate the compiled predicate on the server at query time; clients never evaluate statements themselves. Statements power two runtime surfaces: server-side filtering in the instance query model, and runtime predicate payloads used by grids, cards, and highlights.

Name is the stable technical key. It follows the same identifier rules as entity and field keys, and it is what query filters and runtime metadata bind to — rename it as deliberately as a field key. DisplayName is the human-facing label and can change freely.

A statement is one boolean expression — not a query. It can use:

  • root scalar fields, supported system fields, and first-level Reference scalar fields;
  • the shared operators — comparisons, AND/OR/NOT, text operators (CONTAINS, STARTS WITH, ENDS WITH), IN, NOT IN, BETWEEN, IS NULL, IS EMPTY;
  • variables: @today, @today+7d, @today-7d, @currentUserId;
  • direct child-table checks: EXISTS Table WHERE (…) and COUNT(Table) <comparison>;
  • Classifier categories through the portable CATEGORY(...) literal.

The supported system fields are Number, DisplayName, CreatedAt, CreatedByUserId, ModifiedAt, ModifiedByUserId, LastActivityDateTime, ArchivedAt, and ArchivedByUserId.

DueDate < @today AND Status != 'closed'
DueDate >= @today+7d AND OwnerUser = @currentUserId
EXISTS Items WHERE (Quantity > 0) AND COUNT(Items) BETWEEN 1 AND 3
Capability = CATEGORY('product-area', 'operations', 'platform')

Classifier fields support =, !=, IN, NOT IN, IS NULL, and IS NOT NULL. Exact and set comparisons do not match null, and field-to-field equality or inequality requires the same Classifier Catalog. A statement compares the stored category identity, not its display name or breadcrumb; changing a Classifier expression requires Catalog access, but the saved statement evaluates independently of the viewer. See Classifier category values.

  • raw SQL, joins, or direct table access;
  • references to other statements;
  • inverse-reference traversal;
  • Reference chains deeper than one step (Customer.Owner.Department);
  • child tables deeper than one direct level;
  • sorting — query results cannot be sorted by a statement.

ExposeInClient controls whether the statement’s boolean result is published to clients. When it is true, runtime list and detail payloads include the result in their Predicates map, keyed by statement id, where grids, cards, and highlights consume it.

Two properties make exposure a deliberate publication decision:

  • Only the boolean is published — for Classifier expressions the payload carries no Catalog or category identity — but a boolean can still reveal a derived business fact.
  • Field-level read masking does not suppress an exposed statement. If the expression depends on fields the caller cannot read, the caller still sees the boolean result. This is intentional: exposing a statement publishes the derived fact itself, independent of field-level access to its inputs.

Keep ExposeInClient = false for server-only statements that should not become part of the client-visible derived-information surface.

Statements are leaf conditions in the same filter tree as field conditions in the instance query endpoint. The field reference targets the statement by StatementId or StatementKey, and the condition compares against one boolean literal with Eq or Ne:

{
"Filter": {
"Operator": 0,
"Conditions": [
{ "Field": { "StatementKey": "Overdue" }, "Operator": 0,
"Values": [ { "Value": true } ] }
]
}
}

Filtering by an exposed statement is an allowed way to act on the derived fact even when the underlying fields are not directly readable.

Statements are managed through the statements operations of the Configuration API:

GET /api/workspace/admin/entity-definitions/{entityDefinitionId}/statements
POST /api/workspace/admin/entity-definitions/{entityDefinitionId}/statements
GET /api/workspace/admin/entity-statements/{statementId}
PUT /api/workspace/admin/entity-statements/{statementId}
DELETE /api/workspace/admin/entity-statements/{statementId}

Validate an expression before saving with the shared endpoint POST /api/workspace/admin/entity-definitions/{entityDefinitionId}/rule-expressions/validate using ContextType Statement and ExpressionType Condition. The response reports validity plus structured errors. Shared literal and operator rules are in Syntax and types; the other declarative surfaces are mapped on the rule expressions hub.