10.2
Cerb (10.2) is a feature upgrade released on February 23, 2022. It includes more than 186 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 April 30, 2021 then you can upgrade without renewing your license. Cerb Cloud subscribers will be upgraded automatically.
Important Release Notes
-
Cerb 10.2 requires PHP 7.4+ and MySQL 5.6+ (or MariaDB 10.2+).
-
To upgrade your installation, follow these instructions.
-
NOTE: The branches in the
cerb/cerb-release
repository have changed. Themaster
branch has been removed, and new branches exist for each major version (e.g.v10.1
,v10.2
). -
Visit the community forums for tutorials and guides on new 10.x features.
Changelog
Added
-
[Metrics] Added a new time-based Metrics service to the platform. [#656]
Metrics have a unique name like
cerb.workers.active
and store statistics in multiple resolutions: 5 mins, 1 hour, and 1 day. Samples collected within the same period are aggregated into a statistic set with the number of samples, sum, min value, max value, and average.By default, 5 minute samples are retained for 1 day, 1 hour samples for 2 weeks, and daily samples are stored indefinitely.
A metric is either a
counter
(increments over time) or agauge
(direct reading of a value at a given time).Metrics may be further partitioned with optional key/value pairs called “dimensions”. For example, the
cerb.automation.invocations
metric has dimensions for theautomation
andevent
; which allows for reporting across all automations, specific automations, specific events, or any combination thereof.Dimensions may have the following types:
extension
,number
,record
, ortext
.Metric samples are buffered until the end of the current request and then are efficiently enqueued for asynchronous processing by a new scheduler job. This means new metric samples may not show up on charts for a few minutes.
Metrics statistics can be retrieved with data queries.
These new metrics are managed automatically by Cerb:
Metric Description cerb.automation.duration
How long automations are executed. Dimensions: automation_id
andtrigger
.cerb.automation.invocations
How often automations are executed. Dimensions: automation_id
andtrigger
.cerb.behavior.duration
How long behaviors are executed. Dimensions: behavior_id
andevent
.cerb.behavior.invocations
How often behaviors are executed. Dimensions: behavior_id
andevent
.cerb.mail.transport.deliveries
How many successful messages are sent through a mail transport. Dimensions: transport_id
andsender_id
(email address).cerb.mail.transport.failures
How many unsuccessful messages are attempted through a mail transport. Dimensions: transport_id
andsender_id
(email address).cerb.record.search
How often each worker searches for a given record type. Dimensions: record_type
andworker_id
.cerb.snippet.uses
Snippet usage over time by worker. Dimensions: snippet_id
andworker_id
. This replaces thesnippet_use_history
table but imports its data.cerb.tickets.open
Open ticket counts over time by group and bucket. Dimensions: group_id
andbucket_id
. The metric is sampled every 15 minutes.cerb.tickets.open.elapsed
How long tickets spent in the open status by group and bucket. Dimensions: group_id
andbucket_id
. The metric is sampled when an open ticket is moved to a new group/bucket, or an open ticket transitions to a non-open status.cerb.webhook.invocations
How often webhooks are executed. Dimensions: webhook_id
andclient_ip
.cerb.workers.active
Seat usage by workers. Dimensions: worker_id
. -
[UI/Themes/Dark] Added a toggle for dark/light mode in the top right of every page, after the worker name. This instantly switches between themes and updates the worker preference.
-
[UI/Themes/Dark] In dark mode, all HTML-based email messages are now displayed with a darker theme by reducing their colorization. A new ‘Bright mode’ button is available in the message toolbar to view the original colorization on a white background.
-
[Tickets] Added a ‘Last opened at’ field to ticket records. This timestamp is updated when a ticket transitions into the ‘open’ status. For instance, when a new conversation is first opened, or when a ticket re-opens from the ‘waiting’ status. Unlike the ‘Updated’ field, this timestamp is not updated when a ticket is assigned, moved, commented upon, or otherwise modified. Sorting on ‘Last opened at’ in descending order is a more effective way to handle tickets first that have been waiting for the longest.
-
[Tickets/Records/Reporting] On ticket records, added a new ‘Time Spent Open’ field (
elapsed_status_open
). This contains the total time spent in the open status for each ticket over its lifetime. The total excludes the most recent time elapsed for currently open tickets, which is tracked with thelast_opened_at
field until the ticket transitions to a non-open status. The sortable ‘Time Spent Open’ column can be added to ticket worklists, and records can be queried with a new filter (e.g. (timeSpentOpen:"> 1 week"
). This field is particularly useful for efficient reporting on closed tickets. The ‘time spent open’ broken down by group and bucket is tracked by thecerb.tickets.open.elapsed
metric. -
[Charts/Worklists] Added a
set.timezone:
filter to worklists. This is used by features like chart widgets to synchronize ‘click-to-search’ results with the timezone of the underlying data query. If timezone data is properly initialized in MySQL, the generated search queries should now match the chart exactly. Otherwise, a timezone offset is used as a fallback; which could be slightly off due to Daylight Savings Time, but is more accurate than not specifying a timezone before. [#1394] -
[Calendars] On calendars, busy events can now partially block availability. This already happened in availability widgets, but on normal calendars an available event was only hidden if it was completely occulted by one or more busy events. Now busy events partially overlapping an available event will split it into multiple events with different start/end times.
-
[Queues] Added a new Queues service to the platform for distributing units of asynchronous work. Queues are identified with a unique name. Messages with arbitrary payloads can be pushed into a queue. Concurrent consumers can pop messages from the queue to process them. A message is always in one of four states: available, in flight, failed, or complete. For instance, every historical ticket can be reviewed by pushing sets of IDs into a queue as messages. The number of queue consumers can be scaled up to the desired throughput. [#481]
-
[Calendars/Localization] Added a ‘Timezone’ field to Calendar records. This simplifies calendar event inheritance. For instance, a ‘Company Holidays’ calendar with no timezone can define recurring events with patterns like ‘Dec 25’. Worker calendars in various timezones can inherit the company events and generate localized events. Previously, all-day recurring events like Christmas had a specific timezone, which tediously necessitated a separate shared calendar for each timezone. Thanks to 1Password for the feature request.
-
[Profiles/Comments] On profiles, one or more comments can now be pinned to the top of the conversation. This makes it easier to share a summary or todo list for tickets and tasks. Thanks to Advance Local for the feature request. [#1592]
-
[Automations/Metrics] In automations, a new metric.increment: command adds samples to statistics for a metric. This has
inputs:
formetric_name:
,dimensions:
,values:
,timestamp:
, andis_realtime:
. All inputs are optional except formetric_name:
. By default, samples are queued for efficient background processing. Theis_realtime@bool: yes
option instantly records the metric at a slight performance penalty. For instance, this is used when generating the global search menu based on recent search activity, since this would be less useful to have delayed by several minutes. -
[Automations/Queues] In automations, added queue.push: and queue.pop: commands for adding and processing messages in queues.
-
[Automations] In automations, a new file.read: command can read chunks of bytes from an attachment or automation resource. For
inputs:
, the resource is provided as auri:
and the starting byte isoffset:
, with an optionallength:
. This allows automations to process large attachments without exhausting memory. Theoutput:
is a dictionary with keys:bytes
,uri
,name
,offset_from
,offset_to
,mime_type
, andsize
. Ifbytes
contains binary it is base64-encoded and returned as adata:
URI string. The command enables many new workflows, like automatically processing DMARC reports, bounces, iCal/ICS invites, etc. [#152] [#766] [#1477] -
[Data Queries/Attachments] Added a new
attachment.manifest
data query type. This iterates and filters the manifest of attachment archives (e.g. ZIP). This can be combined withfile.read:
in automations to extract specific files from an archive. -
[Metrics/Data Queries] Added a new metrics.timeseries type to data queries for fetching metric statistics over a date range. This can retrieve multiple series each with a different metric and function (avg, sum, min, max, count). A series can also be aggregated or filtered by any combination of metric dimensions.
-
[Portals/Interactions] In website interaction portals,
say:
form elements can specifyreferences:
to generate secure URLs for ‘portal image’ resource records. Eachreferences:resource:uri:
should point to acerb:resource:{name}
. Theresource/name:
should be used in place of the URL as a fragment. For instance,references:resource/logo:
would generate the URL for![Logo](#logo)
. This format will generate a secure (signed) URL for the image request that doesn’t require external hosts. -
[Portals/Interactions] In website interaction portals, the layout can now be customized. This includes a logo image, logo text, page title, favicon, navigation links, and the floating badge interaction. The layout is defined in KATA when configuring the portal. Logo and favicon images are provided as URIs to resource records.
-
[Portals/Interactions] On website interaction portals with a
say:
form element, inline Markdown images can contain a preferred width and height. Images are specified like![Alt](url)
. To specify a width and/or height, use![Alt =500x500](url)
, where the numbers after the space and equals are the width and height. The width or height can be omitted, like500x
orx500
. -
[Portals/Interactions] On website interaction portals with a
say:
form element, links can be relative and will be rewritten using the full URL and path prefix. This is useful when custom domain names and paths aren’t knowable in advance. For instance,[label](/path)
might link tohttps://example.com/prefix/path
depending on the portal configuration. -
[Portals/Interactions] Website interaction portals can directly serve ‘portal image’ resource records from the
/assets/image/
endpoint. For simple use cases, this removes the need for an external content delivery network (CDN) to store image content. AContent-Security-Policy:
only needs to allow the portal host. Generated URLs for image requests are signed with a secret key to ensure only the resourced used by the portal are accessible. This secret can be configured and rotated fromsecurity:imageRequests:secret:
in the portal schema. -
[Resources/Images] Added a new ‘Image’ resource type for logos, icons, and other artwork in the worker interface. This supports PNG, JPEG, GIF, and SVG images. SVG images are sanitized.
-
[Search/Interactions/Toolbars/Usability] Added a new
global.search
toolbar that adds interactions to the global search menu in the top right of every page. The most recently searched record types per worker are now automatically added to the menu as shortcuts. The existing ‘record type’ search favorites (from worker settings) are always pinned to the menu as shortcuts. The ‘show all record types’ menu item is now an interaction with a searchable list. -
[UI/Logo] SVG images can now be used for the UI logo.
-
[UI/Styles/Dark] In Setup->Branding, separate logos may be uploaded for light mode and dark mode. Logo images are now stored as ‘Resource’ records rather than in the storage filesystem. The 10.2 update will convert existing logos to a resource. The default Cerb logos now use SVG sources for sharper display on high-resolution screens.
-
[Automations/Attachments] In automations, the
file.read:
command has a newextract:
option for extracting an individual file from a ZIP archive. This is used in conjunction with the newattachment.manifest
data query type that lists the contents of an archive. -
[Automations/Events/Mail] Added the
mail.reply.validate
automation event. This enables interactive validators when a worker starts replying to a message on a ticket. Validations are interactions that can optionally abort the reply before a draft is created. If not aborted, the reply editor opens like normal. For instance, this can detect a duplication of effort when another worker starts a reply between the time the current worker viewed the ticket and started replying. This feature was previously built-in, but is now fully customizable as an automation. [#1500] [#1529] -
[Automations/Events/Records] Added the
record.profile.viewed
automation event. This can trigger actions when a worker views a record profile. For instance, metrics on ticket profile views. [#1550] -
[Automations/Events] Added a new
worker.authenticate.failed
automation event that triggers after a worker fails to authenticate a new session. This receives inputs for theworker_*
record,client_ip
,client_browser_name
,client_browser_version
, andclient_browser_platform
. -
[Automations/Events] Added a new
worker.authenticated
automation event that triggers after a worker successfully authenticates a new session. This receives inputs for theworker_*
record,client_ip
,client_browser_name
,client_browser_version
, andclient_browser_platform
. If an automation returns adeny:
key, the login is denied with a custom error message. This event enables new workflows like: security audits on new sessions (compare historical browser, IP, location), worker browser metrics, deny old browser versions, IP-based firewalls per worker, etc. -
[Automations/Usability] When creating a new automation in the editor, new default content for the script and policy offers helpful tips about what to do next.
-
[Dashboards/Time Blocks] Added a new ‘Chart: Time Blocks’ card widget for visualizing the intensity of hourly coverage over a range of days. This uses a data query (usually
calendar.availability
) withformat:timeblocks
. For instance, aggregating the availability calendars of a group’s members to display shift coverage for the current month. -
[Dashboards/Time Blocks] Added a new ‘Chart: Time Blocks’ profile widget for visualizing the intensity of hourly coverage over a range of days.
-
[Dashboards/Time Blocks] Added a new ‘Chart: Time Blocks’ workspace widget for visualizing the intensity of hourly coverage over a range of days.
-
[Resources/Portals] Added a new ‘Portal Image’ resource type for logos, icons, and artwork in portals. This improves security by avoiding using attachment records for this purpose.
-
[Automations/Logs] In Setup » Developers, a new Automation Logs page allows administrators to view and purge logs from all automations in one place. Thanks to @mryanb for the request!
-
[Automations/Resources] Added Automation Resource records for efficient handling of large binary objects within automations. For instance, the http.request command can stream a GET request for a large video download directly into a temporary resource file and return its Cerb record URI rather than 100MB of bytes. This also protects the privacy of files that are uploaded in automations (e.g. interactions) which should never be treated like attachments.
-
[Behaviors/Automations] In bot behaviors, added a new ‘Execute automation’ action which passes inputs to a
behavior.action
automation and returns the results. This helps with the gradual transition from behaviors to automations, and enables behaviors to use all the functionality from automations. Thanks to 1Password for the feature request! -
[Data Queries/Availability] Added a new calendar.availability data query type. This aggregates any number of matching calenders to display availability over a date range by hour or day. For instance, this can be used to visualize when a group is most or least available for shift planning. The output formats are
dictionaries
andtimeblocks
. Thanks to 1Password for the feature request. -
[Mail/Commands] When composing, replying, or relaying email, added a new
#start note
command for adding a multi-line sticky note to the message once created. The note can be any number of lines following the command until an#end
command on its own line. -
[Mail/Drafts/Commands] Implemented the
#start comment
command for multiple line comments in drafts for compose and replies. -
[Metrics/Dimensions] In metrics, added a
number
type to dimensions. This efficiently stores a positive whole number. -
[Automations/Metrics] In the automation builder, added a helper interaction for the
metric.increment:
command. This automatically defaults the available dimension key/values. -
[Automations/Reminders] Added a reference
cerb.reminder.remind.email
automation for thereminder.remind
automation event. This sends reminders by email to the target worker. -
[Data Queries/Metrics] In
metrics.timeseries
data queries, added the ability to aggregate results inperiod:
by week, month, and year. Previously this only supported: minute, hour, and day. -
[Data Queries/Metrics] On
metrics.timeseries
data queries, a newseries.*:missing:
key configures what to do with missing samples at a time interval. The options arenull
(default),zero
(set to 0), orcarry
(carry the last sample). -
[Data Queries] Added a new
autocomplete.completions
data query that returns autocompletion suggestions data for a given automation key path. This can be used by functionality like interactions to inspect an automation at the current cursor to offer contextual suggestions. -
[Data Queries] Added a new
data.query.types
data query that returns metadata about the available types (name, description, etc). This can be used by functionality like interactions to assist in data query generation. -
[Data Queries] Added a new
platform.extension.points
data query type for filtering and paging through a list of platform extension points. -
[Debug] In the
/debug/status
endpoint, a newscheduler
section shows stats for all scheduler jobs, including the last run time. This simplifies monitoring and alerts. -
[Records/Search/Calendars] On calendar records, added a
workerAvailability:
search filter. This matches calendars configured for worker availability (opposed to calendars owned by workers). -
[Records/Search] On draft worklists, added a
ticket.id:
filter. -
[Toolbars] In toolbars,
divider:
items draw a horizontal divider between menu item sections. -
[Tickets/Worklists] On ticket worklists, added a new icon to the top right which automatically scrolls to the actions toolbar below the list. This removes the need to scroll down when working with long work pages (e.g. 50+ items). Thanks to NJ Advance Media for the feature request.
-
[Dates] Added new date range shortcuts in data queries and search filters for:
this year
,last year
, andnext year
. -
[Automations] In automations, added
log.warn:
andlog.error:
actions. These are aliases forlog:
but set the severity for filtering. The default severity oflog:
isdebug
.
Changed
-
[Data Queries/Worklists/Subtotals] On
worklist.subtotals
data queries, thetimezone:
option must now be a location (e.g.America/Los_Angeles
) rather than an offset (e.g.-08:00
). This makes it possible to localize data queries for each worker by using their timezone placeholder. An invalid timezone returns an error, and if omitted it defaults to the timezone of the current worker (if there is one). This removes the need to specify a timezone or offset in the date range, as any date-based filters and date-based groupings are now synchronized automatically. -
[Data Queries/Worklists/Series] On
worklist.series
data queries, added thetimezone:
option. This takes a location likeAmerica/Toronto
orEurope/Berlin
. If omitted, it defaults to the timezone of the current worker, or the server if there’s no worker session. -
[Calendars/Recurring] Fixed an issue in calendars with recurring events that spanned multiple days. For instance, if a worker had an overnight shift from 6p-2a (18:00-02:00), the event wasn’t displaying unless the end time was
tomorrow 2am
. Now, end times with earlier hours than start times are assumed to be the next day. Multiple day recurring events patterns now generate separate events for each day. This already happened for non-recurring events. Thanks to 1Password for the report. [#1601] -
[Calendars] On calendars, event start and end times (when visible) are now displayed to the right of the name. Times are not shown for all-day events like holidays.
-
[Search/Fulltext/Performance] When running a fulltext search, Cerb will now first check the total hit count for the given terms. If less than a lower threshold (default
1,000
) the results will be returned as IDs rather than anIN(...)
join. This reduces index contention in complex queries. The threshold can be configured with theAPP_OPT_FULLTEXT_THRESHOLD_IDS
constant. -
[Search/Fulltext/Performance] When running a fulltext search, Cerb will now first check the total hit count for the given terms. If greater than the upper threshold (default
10,000
) the results will be joined usingEXISTS
rather thanIN
. TheEXISTS
strategy is faster when there are fewer matches for non-fulltext filters than fulltext (e.g. searching a date range or a particular org’s history). TheIN
strategy is usually faster when there are fewer matches for fulltext filters than non-fulltext (e.g. searching all historical tickets for an uncommon phrase). The threshold can be configured with theAPP_OPT_FULLTEXT_THRESHOLD_EXISTS
constant. -
[Automations] Automations now have an execution time limit (default 25s) rather than an operation limit. This still prevents infinite loops without inconsistently prohibiting functionality. The time limit can be override from the automation policy with the
settings:time_limit_ms:
key. -
[Project Boards/Performance] Project boards now load up to 100 cards per column by default. Additional cards can be loaded with a ‘show more’ link at the bottom. This improves performance on heavily used boards; particularly in the ‘Completed’ column. One noteworthy client had over 23,000 completed cards and was experiencing memory issues while rendering the column.
-
[Automations] The
cerb.data.records
(ui.sheet.data) automation now accepts aquery:
input (rather thanrequired_query:
) and aquery_params:
input for untrusted query placeholder substitution. -
[Profiles/Performance] Profile tabs are now properly loaded from the cache rather than the database.
-
[Profiles/Performance] Profile widget configurations are now cached per profile tab, rather than loaded from the database on every request. The cache is properly invalidated on widget edits as well as reordering.
-
[Profiles/Tickets/Performance] Optimized database queries when loading ticket profiles: requesters, senders, workers, contacts, orgs, custom fields, headers, files, and toolbars. More data is bulk loaded in fewer queries, and previously loaded records are reused when possible.
-
[Automations/HTTP] In automations, the http.request action can now directly stream large attachment/resource uploads for PUT and POST HTTP requests. Set the
Content-Type:
header toapplication/vnd.cerb.uri
and set the HTTP body to a record URI likecerb:attachment:123
. The automation will take care of streaming the bytes to the HTTP endpoint, which avoids memory issues with loading large attachment content into an automation variable. -
[Automations] In automations, when using the http.request command, a large HTTP response body (>1MB) will now be returned as an automation resource record for further processing. These bytes are streamed directly to a file to avoid memory limitations in the automation (e.g. video processing). When this occurs,
output:is_cerb_uri:
istrue
, theoutput:content_type:
key is replaced withapplication/vnd.cerb.uri
,output:content_type_original:
contains the original content type, and the HTTP body is a Cerb record URI (e.g.cerb:automation_resource:c10028f0-1cad-11ec-81e5-59d4c4af2d7
). The newfile.read:
command can be used to process the file in chunks. -
[Automations] In automations, when using the http.request command, a binary HTTP response body is now automatically converted to a base64-encoded
data:
URI. This resolves issues with serializing automation states containing unprintable characters (e.g. simulation). You should always use thehttp.request:on_success:
handler to verify an HTTP response. When this occurs, theoutput:is_data_uri:
istrue
. -
[Platform/Cache/Performance] When using Memcached for the cache service, consistent hashing is now enabled by default. When using a cluster that adds or removes nodes, consistent hashing reduces the number of keys that are rebalanced.
-
[UI/Styles/Themes] In the stylesheet, separated the colors (themes) from layout and condensed styles. This makes it easier to create alternative color schemes – like dark mode. [#1281]
-
[Mail/Routing/Automations] Automations on the mail.route event can now route directly to a specific bucket rather than just to a group inbox.
-
[Cards/Widgets] Time-series chart widgets can now be added to cards.
-
[Sheets] On sheets, selection: columns may now specify an optional
params:label:
,params:label_key:
, orparams:label_template:
. This displays a text label next to the checkbox or radio button; avoiding the need for an extra column. -
[Data Queries/Record Types] On record.types data queries, a new
options:
filter returns record types with one or more matching options:autocomplete
,avatars
,cards
,comments
,custom_fields
,links
,owner
,records
,search
,snippets
,va_variable
,watchers
,workspace
-
[Snippets/Bulk] In snippet worklists, bulk update can now delete multiple records. [#1282]
-
[Custom Records/Bulk] On custom record worklists, bulk update can now delete multiple records at once. [#1512]
-
[Mail/Parser] When threading inbound messages to existing conversations, the
In-Reply-To:
header is now prioritized, and allReferences:
message-ids are checked in reverse order. This should resolve issues where a ticket is split, but replies to the split messages still thread to the original conversation. -
[Interactions/Sheets] In interactions using a
form:await:
continuation with asheet:
element, an__index
key is now synthesized in thedata:
dictionaries. This is the index of the dictionary in the collection, which is often not otherwise available as a dictionary value. In many cases this would be a zero-based ordinal position. For instance, this allows asheet:
element to return the index of a dictionary, from which any key can be loaded by later logic. -
[Sheets/Grid] In sheets, the
layout: grid
style has been significantly improved. The grid no longer shows checkboxes on each item for selection. Instead, the entire cell is toggled on and off by clicking anywhere in it. Cells use flexbox for arrangement, and sheet columns are displayed from top-to-bottom; allowing for enhancements like icons and descriptions. This makes it easier to show many options in a smaller space while retaining readability. -
[Interactions/Editor] In interaction.worker automations, with an
await:form:
continuation,editor:
form elements with asyntax:
option will now properly control syntax highlighting and autocompletion in the editor. For instance,syntax: data_query
will highlight and autocomplete data query syntax. -
[Automations/Editor/Usability] In the automation editor, improved autocompletion for values on the same line as their key (e.g.
key: value
). [#1476] -
[Automations/Editor/Usability] In the automation editor, the value for
uri:
keys now autocompletes in commands. -
[Automations/Editor/Usability] In the automation editor, the possible keys for
inputs:
are now autocomplete suggestions in thefunction:
command. -
[Automations/Editor/Usability] In the automation editor, the possible values for
record_type:
are now autocomplete suggestions inrecord.*:
commands. -
[Automations/Editor/Usability] In the automation editor, the possible keys for
fields:
are now autocomplete suggestions inrecord.*:
commands. -
[Automations/Editor/Usability] In the automation editor, the possible values for
metric_name:
are now autocomplete suggestions formetric.*:
commands. -
[Automations/Editor/Usability] In the automation editor, the possible keys for
dimensions:
are now autocomplete suggestions formetric.*:
commands. -
[Automations/Editor/Usability] In the automation editor, the possible values for
queue_name:
are now autocomplete suggestions forqueue.*:
commands. -
[Automations/Editor/Usability] In the automation editor toolbar, the “add” menu button has been replaced with a “magic” interaction that provides contextual suggestions based on the current cursor position in the code. These suggestions may also launch helper interactions to build syntax.
-
[Automations/Editor/Usability] In the automation editor, improved the helper interaction for building
data.query:
commands. -
[Automations/Editor/Usability] In the automation editor, improved the helper interaction for building http.request commands.
-
[Automations/Editor/Usability] In the automation editor, possible values for
icon:
are now autocomplete suggestions insheet:
andsubmit:
elements forawait:form:
continuations. -
[Automations/Editor/Usability] In the automation editor, autocomplete suggestions are now ranked so the most common options are recommended first.
-
[Automations/Editor/Usability] In the automation editor, autocomplete suggestions now include descriptions.
-
[Automations/Editor/Usability] In the automation editor, autocomplete suggestions insert more complete code templates.
-
[Automations/Editor/Usability] In the automation policy editor, added an autocomplete suggestion for
deny/type:
to thedata.query:
command. -
[Toolbars/Autocomplete] In the toolbar editor, possible values for
uri:
are now autocomplete suggestions ininteraction:
commands. -
[Toolbars/Autocomplete] In the toolbar editor, possible values for
icon:
are now autocomplete suggestions ininteraction:
commands. -
[Toolbars/Autocomplete] In the toolbar editor, possible keys for
inputs:
are now autocomplete suggestions ininteraction:
commands. -
[Calendars] On calendars, ‘Easter’ is now a valid pattern for recurring events. Alone it will be evaluated as Easter day in the current year and timezone. It may also be used relatively, like “Easter -7 weeks Wednesday” and “Easter +3 days”. Thanks to 1Password for the request! [#1535]
-
[Automations/Interactions/Sheets] In interactions,
sheet:
prompts now automatically continue when they’re in single selection mode and the only prompt. The continue button should be hidden to avoid requiring two clicks. -
[Interactions/Sheets] In worker interactions,
sheet:
prompts have a newcolumns
layout style that renders sheet items from top to bottom in a columns. Columns start from the left and responsively add/reduce based on the popup width. This is similar to thegrid
layout which arranges items in rows from left to right, top to bottom. -
[Automations/Editor/Usability] In the automation editor, the helper for the record.create: command now automatically selects all of a record type’s required fields by default. Previously this had to be done manually.
-
[Automations/Events] In the automation event editor, the
interaction:uri:
key now autocompletes with only suggestions from the current event trigger. Suggestions are also provided forinteraction:inputs:
. -
[Automation/Events/Usability] In the automation event editor, the (+) toolbar item now starts the interaction in a single click. Previously this showed a one item menu and required an extra click.
-
[Automation/Events] In the automation event editor, the (+) interaction now warns on invalid cursor placement. New automations can only be added at the top-level of the KATA script (no indentation).
-
[Portals/Interactions] interaction.website automations can now
return:redirect_url:
to redirect the portal visitor to a URL. For instance, after completing a survey the visitor can be redirected back to the project website or support portal. -
[Sheets/UI] In sheets using
layout:style:grid
, alayout:params:width:
option determines the width of grid cells. The default isauto
where each cell can be a different width. -
[Portals/Interactions] In Website Interactions’ portals, it’s now possible to disable the floating icon when viewing the portal directly (rather than embedding on a website).
-
[Resources] Resource records may now store additional parameters based on their type. For instance, after validation, an ‘image’ resource can store the width, height, and MIME type.
-
[Portals] When saving a portal configuration, the ‘updated’ timestamp is now updated on its record.
-
[Records/Snippets] When editing snippet records, prompted placeholders now provide autocomplete suggestions.
-
[Portals/Interactions] When configuring website interaction portals, a copy/paste code snippet is provided for including an interaction widget on your website. Previously this syntax was buried in the documentation.
-
[Portals/Interactions] In website interaction portals, interactions open in wide mode when viewing the portal directly (rather than the widget on a third-party website).
-
[Portals/Interactions] In website interaction portals, styles are more easily configurable from third-party website stylesheets using CSS
--var
variables. -
[Records/Usability] All record editors now support the warning when closing the popup before saving.
-
[Records/Automations] Automation worklists can now display rows on two lines if the ‘Name’ column is omitted. The name is shown on its own line and the second row has more room for extra columns.
-
[Portals/Website Interactions/Mobile] On website interaction portals, improved responsiveness for mobile devices. When a popup is very tall it will now scroll rather than disappearing out of the viewport.
-
[Resources/Portals] Resource records of the ‘Portal image’ type may now include the SVG format (vector).
-
[Records/Watchers/Performance] In the record watchers popup, added a cache for worker responsibilities and workloads to improve performance on large teams.
-
[Automations] When editing automation records, the
cerb.
namespace is reserved. These automations are managed automatically and shouldn’t be edited directly. -
[Records/Tickets] On the ticket record editor popup, a
Shift+Enter
keyboard shortcut automatically focuses the ‘Save Changes’ button. Thanks to Kent at Flexibits for the feature request. [#1593] -
[Records/Search] In record search queries, date-based filters can now use date range shortcuts like
this week
,last week
,last month
,last year
,today
,yesterday
, andtomorrow
. -
[Records/Search] Fixed an issue with
header.*:
filters on message record search queries. These weren’t filtering by theheader_name
attribute, which could return inflated counts and use a less efficient join strategy. For instance, usingheader.deliveredTo:sales@cerb.example
would count hits in all headers and not justdelivered-to
. The final results were accurate, but the aggregation could time out. -
[Resources] When editing resource records, the
cerb.
namespace is reserved. These resources are managed automatically and shouldn’t be edited directly. -
[Automations/HTTP] In automations, the
http.request:
command now returns a full HTTP response in theon_error:
event. This includesstatus_code
,content_type
,headers
, andbody
. Previously, only a truncated error message was available. [[#1605](https://github.com/jstanden/cerb/issues/1605] -
[Calendars/Localization] Recurring calendar events are no longer required to specify a timezone. Instead, a new “(use calendar timezone)” option may be selected. This allows ‘all-day’ recurring events (e.g. Christmas) to be shared properly between calendars in different timezones.
-
[Mail/Relay] Bot behaviors that use the ‘Send email relay to workers’ action will no longer relay to disabled workers.
-
[Calendars] On calendars, all-day events no longer show a start time.
-
[Platform/Dependencies] Updated the Twig templating engine from 3.1.1 to 3.3.8. This improves PHP 8.1 support.
-
[Platform/Dependencies] Updated the Smarty templating engine from 3.1.44 to 4.1.0. This improves PHP 8.1 support.
Deprecated
-
[Platform] The upcoming Cerb 10.3 update will require PHP 8.0+ and MySQL 5.7+.
-
[Platform/Search] Sphinx search engine support will be removed in Cerb 10.3.
-
[Bots/Behaviors] Bot behaviors should continue to migrate to automations.
-
[Tickets/Comments] On ticket profiles, with the “Conversation” widget, the “Pin the last comment to the top of the conversation” will be removed in a future update. Use the new “pin” feature directly on comments.
Removed
- [Profiles/Ticket/Usability] On ticket profiles, removed the attachments search button from the top right when hovering over a message. This can be reimplemented as an interaction on the
mail.read
toolbar. We had reports of the attachments and permalink buttons being confused for each other. [#1547]
Fixed
-
[Platform/PHP] Compatibility with PHP 8.0 and 8.1.
-
[Records/Custom Fields] Fixed an issue in record dictionaries when expanding the
customfields
key. This didn’t write a value tocustomfields
in the dictionary, so subsequent requests could re-load fields and duplicate values for some types (e.g. record links). -
[Interactions/Sheets] Fixed an issue with worker interactions with sheet prompts. If single selection is enabled, de-selecting a row still keeps its value until another option is selected. This meant someone could ‘Continue’ after de-selecting an option without selecting something else.
-
[Records/Custom Fields] When creating or updating records, URL-based fields now automatically truncate when over 255 characters in length. Previously these fields returned a validation error.
-
[Automations/Validation] Fixed an issue with validation on some automation commands (e.g.
var.set:
) where values didn’t allow pure numbers. -
[Data Queries/Records] In record.fields data queries, fixed an issue with the worker record type where keys weren’t returned for
email
,email_ids
, andpassword
. -
[Interactions/Website] Fixed an issue with interaction.website automations when selecting
sheet:
items with the keyboard rather than the mouse. -
[Dashboards/Maps] On profiles and dashboards, fixed an issue with ‘Map’ widgets where the Maps KATA was inserted in the wrong editor.
-
[Automations/Data Queries] Fixed an issue with data query
query_params:
dynamic bindings. Dynamic text values are now always enclosed in quotes. This affected functionality that converts tokens back to queries, where the values weren’t properly escaped. -
[Automations/Continuations] Added a maintenance cleanup task for automation continuations.
-
[Tickets/Mail] Fixed an issue with the ‘Expand quoted text’ option on plaintext email. A quoted block wasn’t collapsed if it started on the first line of the email. This isn’t common since most mail applications add a header line like, “At date/time, someone wrote:”.
-
[Data Queries/Worklists] Fixed an issue with data queries that can specify a
query:
with filters. Nested booleans weren’t parsed properly (e.g.(a OR (b AND c))
. -
[Tickets/Cards/Usability] Fixed an issue when replying to a ticket from its card when scrolled down a page (e.g. replying to a long message body). When the reply was sent, the ticket card was still positioned far down the page, rather than at the top where it was expected. Thanks to @mryanb for the report!
-
[Mail/POP3] Fixed an issue with POP3 mailboxes when downloading messages that used an unsupported encoding in the envelope headers. This could prevent new mail from downloading as the message repeatedly failed on each attempt. The issue was in the Horde IMAP library, but is mitigated by returning the raw headers and parsing them ourselves. The situation is only required when a message is larger than the mailbox limit. Thanks to PassMark Software for reporting!
-
[Mail/Parser] Fixed an issue with the email parser when a message specified an unsupported encoding on the plaintext part. This caused the message to fail and temporarily blocked the scheduler job from parsing other email (for about 10 mins). The encoding wasn’t being checked before testing if the current message contained an inline bounce message (which is converted to an attachment). If the encoding fails, the bounce test is now skipped and processing continues normally.
-
[Interactions/Sheets/Toolbars] Fixed an issue when rending toolbars on sheets prompts in worker interactions. The Toolbar KATA didn’t have access to all placeholders in the automation state, which made it difficult or impossible to conditionally enable/disable toolbar items based on anything other than selected rows. Thanks to Corey at 1Password for discovering and reporting the issue.
-
[Calendars/Sync] In calendars, fixed an issue where a calendar could synchronize with itself. This caused calendar operations to time out. Thanks to 1Password for discovering and reporting the issue.
-
[Platform/Installer] The requirements checker now ensures the
mysqlnd
PHP extension is enabled. This is required for asynchronous queries, parallel queries, and query timeouts. -
[Mail/Localization] Fixed an issue in the email parser when generating a plaintext part from an HTML-only message. If the HTML part included a content-type in the meta header, non 7-bit characters were corrupted (e.g. accents, emoji, multibyte). Thanks to @ScreamBE for reporting. [#1597]
-
[Mail/Parser] Fixed an issue in the email parsing when generating a plaintext part from HTML. Non-breaking spaces could be left in the plaintext. These are now ignored.
-
[Behaviors/Custom Fields] Fixed an issue on the ‘Create’ actions in behaviors (e.g. ‘Create task’) when setting custom fieldsets.
-
[Mail] Fixed an issue when sending mail with a custom ‘From:’ header.
-
[Worklists/Bulk] Fixed an issue with bulk updating multiple checkbox custom fields on worklists. [#1526] [#1556]
-
[Tickets/UI] On HTML messages and comments, fixed an issue with improper aspect ratios when responsively scaling images. The maximum width was being enforced, but this could stretch the height.
-
[Addresses/Merge] Fixed an issue when merging email addresses when the Support Center plugin has never been enabled. These database tables are now ignored if they don’t exist.
-
[Automations/Inputs] Fixed an issue with automations where trailing whitespace in
inputs:record:record_type:
would return an ‘invalid record’ error for valid record IDs. Thanks to ChargeOver for the bug report. -
[Automations/Mail/Filtering] Fixed an issue with
mail.filter
automations where thereturn:set:email_subject:
key wouldn’t re-thread the inbound message if a ticket mask was added or removed in the subject line. Thanks to Corey at 1Password for discovering the bug. -
[Dashboards/Prompts] Fixed an issue with dashboard ‘chooser’ prompts. If the
default:
value was provided as an array it could prevent the dashboard from rendering. Thanks to Corey at 1Password for discovering the issue. -
[Widgets/Charts] Fixed an issue on card, profile, and workspace chart widgets. If the y-axis was formatted as time elapsed (seconds or minutes), but provided as a float (e.g.
65.5
) then the human-readable date included the textundefined
, like1m,5undefined5s
. -
[Records/Dates] Fixed an issue in record editors with a date field. It’s now possible to input relative times like
+1h
and-2hr
. Previously these failed unless a space was provided between the count and the unit. Thanks to 1Password for the report. -
[Automations/Records] Fixed an issue in automations with the
record.upsert
action. Thefields:
dictionary had its placeholders evaluated twice – once byrecord.upsert
and a second time by eitherrecord.create
orrecord.update
. This led to unexpected results when a placeholder value contained characters that were interpreted as another placeholder (like{{
). Thanks to @mryanb for reporting the issue. -
[Automations/HTTP] In automations, fixed an issue with the
http.request:
command when setting thebody:
as a dictionary and using aContent-Type
header. The header name is no longer case-sensitive, and attributes likecharset
are ignored when matching. [#1606] -
[Reports/Time Tracking] Fixed an issue on the example ‘Time Spent By’ reports. These reports are now properly based on seconds rather than minutes.
-
[Records/Search] Fixed a browser warning about ‘showLineNumbers’ being an invalid option when opening a search popup.
-
[Workspaces/Usability] Fixed an issue on workspace dashboards where a widget would disappear if it failed to load.
-
[Automation/Scripting] Fixed the missing
array_count_values()
scripting function in code editor autocompletion suggestions.
Security
-
[Security] Worker default passwords are created in the new
password_hash
format. Previously this used the old salt+SHA1 format and was automatically upgraded after the first login. -
[Tickets/Security] Added additional role permission checks when workers delete tickets from worklists or profile pages.
-
[Automations/Scripting/Security] In automation scripting, the
|markdown_to_html(is_untrusted=true)
filter now uses ‘untrusted’ mode by default to allow Markdown formatting escape HTML tags. The optional argument can allow HTML tags for trusted input in special cases. -
[Portals/Interactions/Security] Website interaction portals now include the
nonce
attribute onscript
tags. This makes it easier to implement a strictContent-Security-Policy
. -
[Portals/Interactions/Security] On website interaction portals, the direct pages now use a strict
Content-Security-Policy
. -
[Portals/Interactions/Security] In website interaction portals, when using the direct page link, the
Content-Security-Policy:
headerimg-src
directive can be configured withsecurity:contentSecurityPolicy:imageHosts@list:
. This allows external images to be used in interactions from trusted hosts. -
[Dashboards/Widgets/Security] On cards, profiles, and workspaces, ‘Time Series’ widgets may now use the
${placeholder}
syntax in data queries for untrusted user input.