Blog

Release announcements, helpful tips, and community discussion

10.3

Cerb (10.3) is a feature upgrade released on September 28, 2022. It includes more than 98 new features and improvements from community feedback.

To check if you qualify for this release as a free update, view Setup » Configure » License. If your software updates expire on or after December 31, 2021 then you can upgrade without renewing your license. Cerb Cloud subscribers will be upgraded automatically.

Important Release Notes

Changelog

Added

  • [Automations/Changesets] In the automation editor, a new ‘Change History’ tab shows the differences between the current version of the code and any previously saved version. This makes it possible to keep track of changed lines in the current version, as well as rollback to a previous version. The historical changesets are timestamped and are attributed to the worker who made them. [#1619]

  • [Automations/Policies/Changesets] In the automation editor, the ‘Policy’ tab now includes a ‘Change History’ button in the toolbar. This opens a popup to visually compare changes between the current policy and any past save. Changes have a timestamp and an author. Changes can be reverted individually or rolled back entirely.

  • [Automations/Events/Changesets] The automation event editor has a new ‘Change History’ button. This opens a popup to visually compare changes between the current event bindings and any past save. Changes have a timestamp and an author. Changes can be reverted individually or rolled back entirely.

  • [Toolbars/Changesets] The toolbar editor has a new ‘Change History’ button. This opens a popup to visually compare changes between the current toolbar and any past save. Changes have a timestamp and an author. Changes can be reverted individually or rolled back entirely.

  • [Metrics/Changesets] The metric editor has a new ‘Change History’ button for dimensions. This opens a popup to visually compare changes between the current Dimensions KATA and any past save. Changes have a timestamp and an author. Changes can be reverted individually or rolled back entirely.

  • [Workspaces/Charts] On workspace dashboards, a new Chart KATA widget allows complex charts to be created from multiple datasources. Datasets can be any combination of manual data, data returned from a data query, or data returned from an automation (of type ui.chart.data). Datasets can be rendered as: area, area-spline, area-step, bar, donut, gauge, line (default), pie, scatter, spline, or step. Supported x/y axis types are: category, timeseries, linear (default). Each dataset can specify a separate chart type (for instance, rendering a line series on top of a bar series). An independent left and right y-axis are supported. Axis ranges/domains are normalized across multiple datasets. Trend lines are also supported for each axis (e.g. average/median), and the value for these markers can be generated dynamically by an automation. Thanks to 1Password for the feature request!

  • [Workspaces/Charts/Changesets] ‘Charts KATA’ workspace widgets now keep track of the changeset history for the datasets and chart. A ‘Change History’ button is available in the editor toolbars.

  • [Automations] In automations, added a file.write: command for creating temporary automation resource files to hold various kinds of data. The inputs:content: can define either bytes:, text:, or zip:. Using content:zip: will create a ZIP archive with a list of one or more zip:files:, each with a path and URI to an attachment or automation resource. An optional zip:password: encrypts the ZIP. An optional expiration date for the file can be provided with inputs:expires@date:. The output: includes keys for: uri, mime_type, expires_at, size, and id. [#1637]

  • [Automations/Files] In automations, the file.read: command now accepts an optional inputs:password: for decrypting password-protected ZIP archives.

  • [Automations/Editor] In the automation editor, a new ‘export’ button is available in the toolbar. This generates a package for sharing the record (name, description, trigger, policy, and code).

  • [Records/Search/Links] In record search queries, links.(type).(field): filters now exist for all custom fields that link to the current record type (record link, record links, worker). These are deep search filters that can filter the other side of the link. For instance, on a workers worklist, the query links.ticket.testFieldset_worker:(status:o) would return all workers linked to by the testFieldset_worker custom field, where the field’s ticket is in the open status. [#1215]

  • [Interactions/Worker] In worker interactions, added a query: element to form continuations. This builds a search query with autocompletion for the given record type. This is particularly useful for user-level filtering above a sheet of records.

  • [Worklists/Export] When exporting records from a worklist, a new ‘Build’ option uses KATA to provide full customization of the exported columns and values, including transformations using scripting filters. For instance, from a ticket worklist, a single exported ‘Content’ column can now combine mask, subject, and the first 2500 characters of the initial message content, while excluding quoted content. This makes it much easier to export content from Cerb directly into other services (e.g. Huggingface for building machine learning models). This is supported in all export formats: CSV, JSON, JSON Lines, and XML. Previously, only individual fields could be exported without any transformations, which often required a custom script to further format the data.

  • [Worklists/Export] When exporting from a worklist, a new ‘JSON Lines (.jsonl)’ format is available. This exports one JSON object per line. The format is used by services like Huggingface.

  • [Queues/Schedule] In queues, messages can now be pushed into a queue with delivery at a future date. This makes it much easier to implement scheduled automations. For instance, an escalation workflow can push a message into a queue with delivery in 2 hours. An automation timer could drain the queue at regular intervals. When processing those future messages, they could escalate an associated ticket if it didn’t have any action in the meantime. The same process could also handle workflows like auto-closing tickets that wait longer than a certain deadline, etc.

  • [Automations/Log] Automations now automatically log scripting syntax errors when they are encountered. Previously, scripting errors failed silently.

  • [Data Queries/Subtotals] In worklist.subtotals data queries, date fields can now be grouped by @hourofdayofweek for categories like ‘Wednesday 16:00’. This is useful for computing a baseline average week based on any date range. Thanks to 1Password for the feature request.

  • [Automations/HTTP] In automations, the http.request: action can now set the key inputs:response:resource: to always receive an automation resource as the response. Previously, an automation response was only returned for content over 1MB. This is useful when sending an automation resource URI to another function for processing, where passing the raw bytes would be inefficient.

  • [Platform/VObject] Added a VObject service to the Devblocks platform for parsing the vCard and iCalendar formats in attachments. This enables automation worklists like synchronizing calendar events from Google Calendar.

  • [Automations/Scripting] In automation scripting, added a vobject_parse(string) function for processing vCard (VCF) and iCalendar (.ics) files in automation workflows. The function takes a block of text in VObject format as input, and returns a parent/child data structure. [#318]

  • [Worklists/Usability] On record worklists, a range of rows can be quickly selected (or deselected) by holding <SHIFT> while clicking the beginning and end of the range.

  • [Automations/Scripting] In automation scripting, added a new date_lerp(date_range,unit,step,limit) function for interpolating the timestamps between two dates with the given unit (minute, day, week, month) and step (1, 5, 10).

  • [Interactions/Worker] Worker interactions can now return:alert: to display a time-limited message at the top of a worker’s browser. This is particularly useful to confirm non-interactive actions (e.g. “Copied!”).

  • [Interactions/Worker] Worker interactions can now return:clipboard: to copy arbitrary text to the worker’s clipboard. Due to browser security rules, this feature only works for any interaction that starts from a user gesture (mouse click, screen tap). For instance, a toolbar on a ticket profile page can include a button like ‘Copy ticket mask’ or ‘Copy ticket URL’. Editor toolbars can also implement a ‘Copy’ shortcut. Thanks to 1Password for the feature request. [#1387] [#1572]

  • [Interactions/Worker] Worker interactions can now return:open_link: to open an arbitrary URL as a new tab in a worker’s browser. This is useful for automations and integrations with third-party services. For instance, opening a page on a billing service to generate an invoice. Thanks to @mryanb for the feature request. [#1503]

  • [KATA/Platform/Developers] When parsing or emitting KATA, an option is now available to preserve # comments. Previously, comments were always discarded. This is particularly useful in functionality that updates an existing KATA document by parsing it, modifying the tree, and re-emitting it.

  • [Platform/Records/Changesets] Implemented a ‘record changesets’ service in the platform. This can provide any record type with authored and timestamped change management for arbitrary fields (e.g. automation policy and script). SHA-1 hashes are used for change detection. Infinite history is supported with archival to long-term storage objects.

  • [Automations] Added the scripting.function automation event. These automations can be by invoked using the cerb_automation(uri,inputs) function in any feature that supports scripting. The function returns keys for exit_state (exit, return, error) and return (an arbitrary dictionary). This brings the full functionality of automations to email signatures, snippets, legacy bot behaviors, automation event bindings, toolbars bindings, etc. For instance, a snippet could use an automation to dynamically generate content based on the target record or current worker. This solves many feature requests. [#1522]

  • [Data Queries/Subtotals] In worklist.subtotals data queries, date-based fields can now be grouped by @minute. This makes it easier to review trends over shorter timeframes (e.g. trailing 1-4 hours). With @hour grouping, it’s unclear if activity is concentrated at the beginning or end of an hourly period.

  • [Automations/Charts] Added the ui.chart.data automation event. This can use custom logic and/or external resources to generate data for Chart KATA widgets on cards, profiles, or workspaces. The automation should return:data: with one or more keys each containing an array of series data. For instance, return:data:series0@csv: 1,2,3,4,5.

  • [Data Queries/Subtotals] In worklist.subtotals, date fields can now be grouped by @quarter (e.g. 2022-Q4). Thanks to @mryanb for the feature request. [#1410]

  • [Data Queries/Subtotals] In worklist.subtotals, date fields can now be grouped by @quarterofyear (e.g. Q3). Thanks to @mryanb for the feature request.

  • [Data Queries/Subtotals] In worklist.subtotals, date fields can now be grouped in 5-minute blocks with @minutes/5 (e.g. 2025-01-09 04:25:00). Thanks to 1Password for the feature request.

  • [Data Queries/Subtotals] In worklist.subtotals, date fields can now be grouped in 15-minute blocks with @minutes/15.

  • [Data Queries/Subtotals] In worklist.subtotals, date fields can now be grouped in 30-minute blocks with @minutes/30.

  • [Sheets/Interactions] In worker interactions, sheet: form elements now support a new interaction: column type. This renders a label with a link. Clicking the link starts an interaction with the given inputs:. For instance, a sheet of IP addresses could use an interaction column to make the IPs clickable, and then show a map with location and hostname details. [#1630]

  • [Worker Interactions/Toolbars] In worker interactions, editor: form elements can now define a custom toolbar:. This receives caller_params: for selected_text, cursor_row, cursor_column, and value (full text). Interactions can return:snippet: with text to paste into the editor at the cursor.

  • [Interactions/Worker] In worker interactions, added a fileDownload: element to form continuations. This displays a form button that downloads an attachment or automation resource file when clicked. This is particularly useful for interactions that generate large or binary output, like a dynamic image, a CSV/JSON export, or a ZIP archive.

  • [Automations/Files] In automations, the file.read: command has a new filters: option to modify the stream output from an attachment or automation resource. Using filters:gzip.decompress: will decompress a gzipped file before returning the contents. For instance, this can be used to read a compressed .xml.gz DMARC delivery report from a file attachment.

  • [Metrics] The cerb.automation.invocations metric now records the exit_state of the automation as a dimension. This makes it possible use a metrics.timeseries data query to monitor automation errors system-wide.

  • [Automations/UX] In automation validation, a new “unknown input” error helps catch typos on input names.

  • [Platform/Database] In the framework.config.php configuration file, the database connection port may now be configured with the APP_DB_PORT option. The default remains sockets for localhost and port 3306 for everything else. This simplifies development and testing with Docker containers.

  • [Automation Resources/Records] Automation resource records may now optionally store file names in a new name field. Previously, automation resources were only identified by their UUID. This change makes it easier to handle customer-facing file uploads with automation resources since the UUID can be safely shared and used to look up the file name and size.

  • [Data Queries/Series] In worklist.series data queries, results can now be returned with format:dictionaries. For instance, this makes it possible to display the results as a customizable table using a sheet widget. Thanks to @mryanb for the feature request!

  • [Resources/Font] Resource records have a new font type. This allows TrueType fonts to be uploaded for use in automations (e.g. image generation).

  • [Interactions/Website] In website.interaction automations, an await:form: continuation may now include fileUpload: form elements. This allows a user to upload one or more files as automation resource records. Thanks to 1Password for the feature request!

  • [Records/Search/Workspaces] On workspace tab records, a new workspace: deep search filter is available for filtering by properties of the linked workspace page.

  • [Records/Search/Workspaces] On workspace list records, a new tab: deep search filter is available for filtering by properties of the parent workspace tab.

  • [Records/Search/Workspaces] On workspace widget records, a new tab: deep search filter is available for filtering by properties of the parent workspace tab.

  • [Toolbars/Widgets] On ‘Interaction Toolbar’ widgets on cards, profiles, and workspaces, it’s now possible to configure interactions to start within the widget container (default) or as a popup. Previously, these interactions always started within the widget. Thanks to @mryanb for the feature request!

Changed

  • [Updater/UI] Improved the page displayed when a software update is currently in progress. This now uses a stylesheet and shows the Cerb logo. An HTTP 503 status code (temporarily unavailable) is now used so third-party integrations (like webhooks) can be retried. Previously this returned a ‘200 OK’ response which silently discarded requests like webhook listeners.

  • [UX/Editors] All popups with editable fields now display an “Are you sure?” confirmation when using the ESC shortcut to close them without saving. Previously this functionality was only implemented for specific popups. This also fixes an issue with confirmation popups in recent versions of Safari.

  • [Performance/Records] Improved the performance of many ticket record searches. These queries now return only an ID (and optionally the sort field) and each page of results has its fields expanded when displayed. This allows more searches to be resolved entirely from an index. It also uses less memory which can lead to more efficient join strategies.

  • [Automation/Editor] In the automation editor, starting bot scripting with {{ now properly provides autocompletion suggestions for functions.

  • [Platform/Dependencies] Updated the Horde IMAP library to version 2.30.4.

  • [Platform/Dependencies] Updated the jQuery dependency from 1.11.2 to 3.4.0. [#480]

  • [Platform/Dependencies] Upgraded the jQuery UI dependency from 1.11.2 to 1.13.1.

  • [Platform/Dependencies] Updated the jQuery caret plugin to 1.3.7.

  • [Platform/Dependencies] Updated the jQuery hoverIntent plugin from 1.8.1 to 1.10.2.

  • [Platform/Dependencies] Updated the Ace Editor library from 1.4.7 to 1.4.14. [#1437]

  • [Platform/Dependencies] Updated the AWS S3 library to 0.5.1. Removed the IAM role token patch. Added AWS Signature V4 support. Fixed PHP 8.1 deprecation warnings.

  • [Tour] Updated the tour to match the latest UI and functionality.

  • [Automations/Behaviors] Bot behaviors on the deprecated events ‘Mail assigned in group’, ‘Mail moved to group’, and ‘Mail closed in group’ have been moved to the record.changed automation event. This also ensures custom fields are set on ticket records before the behaviors start. These behaviors should be migrated to automations since we plan on retiring behaviors after version 11.0.

  • [Records/Avatars] Record profile images may now be up to 256x256 pixels. Previously they were resized to a maximum of 100x100. While still displayed in smaller sizes most of the time, the extra resolution keeps images sharp on high-definition displays. [#1047]

  • [Metrics] Metric descriptions may now be up to 255 characters (from 128).

  • [Platform/Cache] When Cerb’s filesystem path changes, the classloader cache automatically rebuilds itself. Previously, this caused an error that had to be corrected manually by clearing the cache. If caching to Redis or Memcached this was particularly tedious.

  • [Mail/Compose/UX] On ticket worklists, clicking the (+) icon to compose a new ticket will now set the default ‘Organization:’ based on the current org.id: filter of the worklist. If currently filtering by orgs, this will automatically suggest recipients from that organization and reduce extra steps for workers. This is particularly useful for a ticket worklist widget on organization profiles.

  • [Interactions/Website] In interaction.website automations, await:form: elements may now refer to their placeholders in a validation: option. For instance, a fileUpload/prompt_file: form element provides placeholders for the filename, MIME type, and size. These may now be used in validation rules.

Removed

  • [Search/Sphinx] Removed Sphinx search engine support.

  • [Platform/Dependencies] Removed the qTip library.

  • [Platform/Dependencies] Removed the jQuery autosize plugin.

  • [Platform/Dependencies] Removed the jQuery cookie plugin.

  • [Platform/Dependencies] Removed the jQuery validate plugin.

Fixed

  • [Platform/Database] Fixed an issue with the database service when connecting to a server that answers a connection but doesn’t respond quickly to commands. This scenario avoided the connection timeout, and could backlog until available connections became exhausted.

  • [Data Queries/Subtotals] In worklist.subtotals data queries, fixed an issue that prevented the same field from being used multiple times in the by: option. For instance, by:[created@dayofweek,created@hourofday]. [#1372]

  • [Devblocks/Routing] Fixed an issue in Devblocks request routing when friendly URLs are disabled. Depending on webserver configuration, it was possible to use any prefix in place of /index.php/ as long as it had the same length.

  • [Scheduler/Storage] In the cron.storage scheduler job, optimized the query used to determine when objects can be archived. Previously, this could log slow queries in large databases due to table scans.

  • [Interactions/Workers/Drafts] On worker interactions in an await:draft: continuation, aborting the draft popup now properly continues the interaction.

  • [Mail/Automations/Validation] When composing or replying to mail and a validation interaction has an error, it will now be logged and ignored rather than preventing workers from sending the message.

  • [Records/Validation] Fixed an issue with the ‘max length’ and ‘truncation’ options on validation when text contained multibyte characters. Text was being truncated on bytes, and in certain situations it was possible to truncate in the middle of a Unicode character, resulting in an invalid string. Truncation no longer splits multibyte characters. Thanks to 1Password for the bug report!

  • [Automations/Files] In automations, improved error checking in the file.read: command. This could previously open non-ZIP archive attachments and throw an error.

  • [Installer] Fixed an issue in the installer with MySQL 8.x where invalid database connection details returned a white screen.

  • [Records/Workers] In automations and bot behaviors, fixed an issue with the worker_groups placeholder. This was always returning all groups rather than the memberships of the given worker. Thanks to 1Password for the bug report!

  • [Data Queries/Subtotals/Currencies] Fixed an issue with worklist.subtotals data queries when using a currency field for aggregate functions. This wasn’t formatting calculations (e.g. avg, sum, min, max) to the configured decimal place. For instance, on a dollar-based currency field all results were in cents. Thanks to @mryanb for the bug report.

  • [Automations/Resources] Fixed a concurrency issue when creating many automation resource records at the same time. The UUIDs are time-based so the initial prefixes can be common. The database index only used the first 6 bytes, which isn’t guaranteed to be unique. Additionally, the unique index on ‘token’ prevented multiple processes from inserting a record at the same time, since the initial field values were blank.

  • [Updater] Fixed several issues with updating from versions earlier than 7.0 (circa 2016) to the latest schema.

  • [Automation Resources/Maint] Fixed an issue with automation resources where maintenance deleted expired records but didn’t clean up the associated storage objects. In most cases you can delete the ./storage/automation_resources/ directory to reclaim the space.

  • [Automations] Fixed an issue with mail.filter automations using the return:set:headers: key. Duplicate headers were being added if the header names has a different case (e.g. subject and Subject). Headers being set to a blank value are now properly removed.

  • [Records/Workers] When deleting worker records, their message history is now properly unassigned. This fixes an issue in reports where IDs were shown for previously deleted workers.

  • [Records/Orgs] Fixed an issue when deleting organization records. The org is now properly removed from any ticket records.

Security

  • [Security/Dependencies] Updated the twig template engine to 3.4.3 due to a security advisory.

  • [Security/Dependencies] Updated the Smarty template engine to version 4.2.1 based on a security advisory.

  • [Security] Cerb no longer responds to unsupported HTTP verbs: HEAD, OPTIONS, etc. Excluding the API, we only respond to GET and POST.

  • [Security/Links] When special characters are found in a URL route (e.g. /profiles~~~/ticket/1), a ‘Not found’ error is now displayed. Previously, these characters were silently removed and the request continued normally.

  • [Security/Sessions] Improved cookie security by using an explicit path and setting the ‘SameSite’ directive.

  • [Security/CSP] Added a default Content-Security-Policy HTTP header. This prohibits potentially malicious cross-origin references to content like images, scripts, and stylesheets. External images in HTML email still work because they proxy through the server on the same origin.

  • [Security/CSP] Removed the built-in Gravatar integration from the profile image editor. This can be reimplemented with automations where desirable.

  • [Security/CSP] Additional trusted origins can be added to the Content-Security-Policy from the framework.config.php file using the APP_SECURITY_CSP_*_SRC constants (e.g. DEFAULT, FRAME, IMG, OBJECT, SCRIPT, STYLE).