v37.0

charmbracelet/crushv37.0Aug 6, 2026by pierre-b

AI Summary

Adds negation capabilities to goal conditions and allows filtering by event properties. Improves the segment editor with real-time contact counting. Fixes a critical SQL injection vulnerability in segment/automation conditions.

Key Highlights

  • Goal conditions can now be negated (e.g., 'not purchased')
  • Goal conditions can filter on event name, goal name, and properties
  • Contact datetime properties gain 'not in the last X days' operator
  • Segment editor counts matching contacts in real-time
  • Security fix for SQL injection in segment/automation conditions

New Features

  • Negated goal conditions
  • Property filtering in goal conditions
  • Real-time segment counting

Full Release Notes

- **Feature**: Goal conditions can be negated. A segment or automation filter can now say "has **not** purchased in the last 30 days", which also matches contacts with no matching events at all. This was previously inexpressible: the condition compiles to an aggregate grouped by contact, so a contact with zero events produced no group and could never satisfy it — meaning a "count is 0" condition silently matched nobody, and comparisons like `sum ≤ 1000` silently excluded everyone who had never converted (#399).
- **Feature**: Goal conditions can filter on the event name, the goal name and the event's own `properties` payload, instead of only the seven goal types. The goal-name filter was already supported by the API but had no input in the console (#399).
- **Feature**: Contact datetime properties gain a "not in the last X days" operator. It deliberately includes contacts whose date was never set — someone who never converted has not converted in the last 30 days either — where a plain negation would silently drop them (#399).
- **Feature**: The segment editor counts matching contacts while a condition is still open in its form, instead of only once it has been confirmed. The count refreshes on its own as the condition's inputs change, and keeps the last valid number on screen — dimmed — while a condition is too incomplete to be counted.
- **Security**: Segment and automation conditions that filter contact-timeline events by a field value built their SQL by splicing the field name straight into the query text. A crafted `field_name` could close the quote and append arbitrary SQL, and the segment preview count turned that into a boolean oracle — any workspace member could read any table in their workspace database. JSONB keys are now bound as query parameters, and workspace migration v37 recompiles stored segment queries so already-saved segments are repaired without being re-saved.