11.0
Cerb (11.0) is a platform upgrade released on October 28, 2024. It includes more than 151 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 September 30, 2024 then you can upgrade without renewing your license. Cerb Cloud subscribers will be upgraded automatically.
Important Release Notes
-
Cerb 11.0 requires PHP 8.2+ and MySQL 8.0+ (or MariaDB 10.5+).
-
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.4
,v11.0
).
Changelog
Added
-
[Workflows] Implemented workflows. Unlike packages that create a set of records once, workflows provide ongoing versioned updates to keep a related set of records in sync between multiple environments (e.g. dev, staging, production). Workflow templates use KATA rather than JSON.
workflow: name: example.newTask version@date: 2025-12-31T00:00:00Z description: This example workflow manages a task record requirements: cerb_version: >=11.0 <11.1 cerb_plugins: cerberusweb.core, config: text/taskName: label: Task name: default: New task from a workflow chooser/taskOwner: label: Task owner: multiple@bool: no record_type: worker record_query: isDisabled:n records: task/newTask: deletionPolicy: retain fields: owner_id: {{config.taskOwner_id|default(0)}} title: {{config.taskName}}
-
[Workflows] In workflows, requirements can now be enforced from the
workflow:requirements:
key of the template. Thecerb_version:
constraint verifies the current Cerb version is compatible (e.g.>=11.0 <11.1
). Thecerb_plugins
constraint verifies the comma-delimited list of plugin IDs are installed and enabled (e.g.cerberusweb.core, cerb.classifiers
). -
[Workflows/Library] Added a cerb.auto_dispatcher workflow for automatically assigning tickets to workers based on priority.
-
[Workflows/Library] Added a cerb.auto_responder workflow to send an automatic response when new tickets are opened.
-
[Workflows/Library] Added a cerb.satisfaction.surveys workflow for gathering and monitoring customer satisfaction metrics like NPS, CSAT, and CES.
-
[Workflows/Library] Added a cerb.login.terms_of_use workflow for requiring acceptance of a ‘Terms of Use’ page when workers log in.
-
[Workflows/Library] Added a cerb.email.dmarc_reports workflow for visually displaying DMARC report email attachments from email providers.
-
[Workflows/Library] Added a cerb.email.pgp_inline workflow for encrypting messages with PGP and pasting them inline in outgoing email.
-
[Workflows/Library] Added a cerb.capture_feedback workflow for capturing user feedback to custom records while reading email messages.
-
[Workflows/Library] Added a cerb.search.simple workflow for demonstrating how to build simplified point-and-click search popups without using queries.
-
[Workflows/Library] Added a cerb.notifications.mention_emailer workflow to email workers when they are @mentioned in a comment.
-
[Workflows/Library] Added a cerb.email.org_by_hostname workflow to automatically assign organizations to new senders based on their email @hostname.
-
[Workflows/Library] Added a cerb.sla workflow to enforce Service Level Agreements (SLA) for tickets from organizations.
-
[Workflows/Library] Added a cerb.integrations.aws_bedrock.profile_images workflow for generating AI profile images using Amazon Bedrock foundational models.
-
[Workflows/Library] Added a cerb.integrations.ipstack workflow for geolocating IPs and rendering locations on maps.
-
[Automations/Scripting] In automation scripting, added a cerb_workflow_config() function for retrieving and sharing workflow configuration values in any feature that support scripting (e.g. automations, workflows, snippets). If
key
is omitted the function will return all configuration values for the matching workflow. For instance, this can share API keys across multiple records while simplifying key rotation in a single place. It also allows workflow configurations to change without rewriting existing records. -
[Automations/Scripting] In automation scripting, added a cerb_workflow_resources() function for retrieving workflow managed record IDs in any feature that support scripting (e.g. automations, workflows, snippets).
-
[Workflows] In workflows, records may define an
updatePolicy:
as a list of fields to update once a record is created. For instance, if a workflow creates a snippet that workers can edit, it should never overwrite the contents of the snippet if the template changes. -
[Workflows] In workflows, added a
picklist:
configuration prompt. In single value mode it’s a dropdown, and in multiple value mode it’s a set of checkboxes. -
[Workflows/Import] When editing a workflow template, added the ability to link existing records to new workflow resources. This makes it possible to reorganize an existing environment into workflows for much improved maintainability.
-
[Workflows/UX] Workflow templates can optionally provide instructions in Markdown during configuration.
-
[Workflows/Export] Added a workflow builder to Setup » Developers » Workflow Builder. This takes Workflow Builder Schema KATA and outputs Workflow KATA. The schema can match existing records by type and query. A
label_map
allows for continuous exports by rewriting local IDs to abstract record keys (e.g.automation_123
->automation_fetchRecords
). -
[Workflows/Builder] In the workflow editor, added a ‘Builder’ tool to assist with exporting changes to existing records in Workflow KATA format.
-
[Tutorial] Added a built-in ‘Tutorial’ workflow that manages a workspace page with detailed descriptions and examples of Cerb features. This is particularly useful for demonstration, testing, development, and onboarding new workers. The tutorial adapts its examples to the current environment. As a workflow, the tutorial is automatically updated for new versions. This is installed automatically on new instances. Existing instances can install it from Search » Workflows » (+) » Tutorial.
-
[Workflows/UX] When creating workflows, a library of pre-built templates covers common use cases (e.g. tutorial, auto-responder, auto-dispatcher). Options are only displayed if they aren’t currently in use.
-
[Mail/Routing] The most common mail routing scenarios have been greatly simplified with Routing KATA. Automations (mail.route) remain available for complex workflows but are no longer required. Routing can be found at Setup » Mail » Incoming » Routing. Multiple conditions in a single
if:
node are “all of these”, and multipleif:
nodes are “any of these”. Conditions includescript
,recipients
,sender_email
,spam_score
,subject
,body
, andheader
; and actions includebucket
,comment
,group
,importance
,owner
, andwatchers
.rule/dev: if/to: recipients: dev@, development@, bugs@ if/subj: subject: [Bugs] * then: group: Development rule/sales: if: recipients: sales@, leads@, prospects@ then: group: Sales rule/support: if: recipients: support@, team@, help@ then: group: Support
-
[Mail/Routing/Groups] In the group editor, inbox Routing KATA can be configured by managers on the new ‘Incoming Mail’ tab. This routes mail without requiring automations or bot behaviors.
-
[Mail/Routing/Metrics] Added a
cerb.mail.routing.rule.matches
metric for tracking mail routing rule usage over time. It includes dimensions forrule_id
(by ruleset record),rule_key
(by rule), andnode_key
(by condition). -
[Mail/Logs] Added a mail delivery log in Setup » Mail » Outgoing » Log. This saves a copy of the raw message on success or failure through all mail transports for a retention period of 90 days. On failure, a status message provides more information. If a message is marked as ‘sensitive’ (e.g. password reset) then the content is redacted unless
DEVELOPMENT_MODE
is enabled. Previously, there was no log in Cerb for outbound mail if a ticket message record wasn’t created (e.g.mail.transactional
, bots, etc), which tediously required checking the mail server logs to verify if such messages were delivered. This log also indexes theMessage-Id:
header, which can be used by webhook callbacks in email delivery services like Postmark to record deliveries and bounces. -
[Mail/Logs] Added an inbound mail log in Setup » Mail » Incoming » Log. This stores metadata and metrics for every processed message an clearly denotes an exit state of: parsed, failed, or rejected. For mail filtering and routing it also records every triggered automation, behavior, or KATA ruleset, with their outputs and elapsed duration. The total parse duration per message is recorded to aid with optimization. If messages are downloaded from a POP3/IMAP mailbox that record is also linked for reporting (e.g. inbound messages per mailbox over time). Inbound logs are retained for 90 days by default. Previously there was no inbound mail log, and errors were instead saved to the app log or output by the background scheduler.
-
[Workspaces/Tabs] On workspace pages, tabs are no longer sorted in a custom order for each worker. The purpose of workspace pages is to provide a consistent experience for each viewer. This is particularly important when tabs are ordered by priority (e.g. my work, open, waiting). Page owners can sort tabs from the final ‘config’ tab. Previously, when a worker viewed a workspace for the first time, its tabs were sorted in the order they were created.
-
[Workspaces/Tabs] On workspace pages, tabs can now be conditionally visible/hidden. For instance, certain tabs may only be visible for admins or members of a specific group. This improves the reusability of workspace pages by not requiring near duplicates for minor variations. Page owners can view hidden pages and their logic from the final ‘config’ tab. As a consequence, workspace tabs are no longer directly draggable into a new order because this would ignore hidden tabs.
-
[Profiles/Tabs] On record profile pages, tabs can now be conditionally visible/hidden. For instance, a different ‘Overview’ tab could be displayed based on a ticket custom fieldset; making it possible to handle non-email tickets like SMS, calls, forum posts, and bug tracker issues. Rather than a ‘Reply’ button, these tabs could use an interaction toolbar and send updates through an external API (e.g. Twilio). Admins can view hidden tabs and their logic from the final ‘config’ tab.
-
[Automations/Editor/UX] In the automation editor, the toolbar has a new ‘commands’ icon. This displays a searchable list of all editor commands and their keyboard shortcuts. For instance: fold code blocks to level 3, unfold all, duplicate selection, move selection up/down, find, select all, go to line, resize editor height, etc. Previously, these useful commands and shortcuts weren’t referenced anywhere.
-
[Mail/Routing/Metrics] Added a
cerb.mail.routing.group.matches
metric for tracking group inbox routing rule usage over time. It includes dimensions forgroup_id
(by group),rule_key
(by rule), andnode_key
(by condition). -
[OAuth Apps/Tokens] Each OAuth App can now independently configure the expiration time for access and refresh tokens. Previously these were hardcoded at
1 hour
and1 month
respectively. This caused issues when generating a long-lived token from Setup » Developers that refreshed with a 1-hour expiration. Thanks to 1Password for the feature request. -
[Cards/Widgets] On card popups, widgets may now be shown or hidden using conditional logic. For instance, a widget may only be visible when tickets are within a certain group, or lack a custom field value. When at least one widget is hidden, admins will see a ‘Hidden’ button at the top of a card popup. This allows hidden widgets to still be rendered or edited.
-
[Workspaces/Widgets] On workspace dashboards, widgets may now be shown or hidden using conditional logic. For instance, a widget may only be visible when tickets are within a certain group, or lack a custom field value. When at least one widget is hidden, admins will see a ‘Hidden’ button at the top of a dashboard. This allows hidden widgets to still be rendered or edited.
-
[Automations/Events/Listeners] Automation Event Listener records now conditionally bind automations to events using KATA. Previously this was done directly on the event record, which frequently caused conflicts when merging events from packages, workflows, etc. A listener is a group of related bindings. The priority of a listener determines when it is evaluated compared to other listeners. When managed by a workflow, a listener can’t be modified directly in order to provide consistency. Listeners can be disabled as a set without having to comment out Event KATA. The existing KATA for each event has been moved to a new listener named ‘Default’.
-
[Toolbars/Sections] Toolbar Section records now conditionally bind items to toolbars using KATA (e.g. interactions). Previously this was done directly on the toolbar record, which frequently caused conflicts when merging toolbar items from packages, workflows, etc. A toolbar section is a group of related items. The priority of a section determines when it is rendered relative to other sections on the same toolbar. When managed by a workflow, a section can’t be modified directly in order to provide consistency. Toolbar sections can be disabled as a set without having to comment out Toolbar KATA. The existing KATA for each toolbar has been moved to a new section named ‘Default’.
-
[Automations/Search] Added a full-text search index to automation records on the
script:
filter. This indexes the automation name and scripting code. Previously the code was not searchable. -
[Automations/Editor] In the automation editor, a new ‘Usage’ tab displays the records that refer to the current automation (e.g. automations, events, toolbars, timers, card/profile/workspace widgets, portals, webhooks). This makes it much easier to find dependencies and unused automations.
-
[Interactions/Worker/Audio] In interaction.worker automations, added an audio: form element to play MP3, OGG, or WAV files. The audio can be provided in
source:uri:
as an automation resource (e.g. from an HTTP API response) orsource:blob:
as a base64-encodeddata:
URI. The audio plays using a browser’s HTML5 player, which supports autoplay, controls, and looping. For instance, this can play text-to-speech from a virtual assistant. -
[Interactions/Worker/Chart] In interaction.worker automations, added a chart: form element to render highly customizable interactive charts from multiple datasets (data query, automation, manual) using Chart KATA.
-
[Interactions/Worker] In interaction.worker automations, added a chooser: form element for selecting records using a search popup. This can perform single or multiple selection for any record type using search filters and autocompletion.
-
[Mail/Reply/UX] When replying to messages, a warning is now displayed if the recipient is banned or defunct. Previously, messages to defunct recipients were silently disregarded without any indication in the UI.
-
[Connected Services/Packages] Added ‘Anthropic’ to the connected services package library.
-
[Connected Services/Packages] Added ‘IPstack’ to the connected services package library.
-
[Platform/Developers/Datasets] Added a ‘Dataset’ service to the platform. This parses Dataset KATA for features like charts to display multiple series. It can fetch data from automations, data queries, or manual.
-
[Profiles/Tickets] On ticket profiles, the ‘Status’ widget can now quickly set a ticket to the ‘waiting’ status with presets (e.g. 1 hour, tomorrow 8am, next week). On existing environments, add a new ‘Status’ widget from the library to update it.
-
[Interactions/Worker] In interaction.worker automations, a
return:callout:
key will now trigger a callout in the UI. This is particularly useful for onboarding, tutorials, and tours. A callout requires a DOMselector
andmessage
to display. Optionalmy
andat
position elements align the callout to the target element (e.g.right top
,left+20 bottom-5
. -
[Sheets/Icons] In sheets,
icon:
columns and options can now render arbitrary in-line SVG images with the newsvg:
key. Rendered SVG images are automatically sanitized. This is particularly useful for dynamic or single-use images. For instance, a survey could display happy/sad or thumbs up/down images on buttons. -
[Interactions/Worker] In interaction.worker automations, a
fileDownload:
prompt can now optionally providedata:
directly without requiring an automation resource or attachment. -
[Workspaces/Dashboards] On workspace ‘Dashboard’ tabs, added a new ‘halves’ layout. This organizes widgets into two equal width columns without requiring aligned pairs between the columns.
-
[Profiles/Dashboards] On profiles, ‘Dashboard’ tabs now have additional ‘halves’ and ‘thirds’ columnar layouts.
-
[Automation/Scripting] Added a cerb_plugin_enabled() function to automation scripting. For instance, this can be used to make dashboard tabs or widgets conditional on a particular plugin being enabled (e.g. project boards).
-
[Developers/Database] In Setup->Developers->Database Schema, it’s now possible to validate an environment’s database schema against the official schema. For instance, it’s possible to make changes to the database directly (new indices, column types, encoding) and these can interfere with Cerb’s functionality. This page also highlights extra tables (e.g. in-place table backups, deprecated plugins).
-
[Sheets] In sheets, added a
text_align:
option to columns to align text within a cell. This supports the values:left
,center
, andright
. -
[Sheets/Slider] In sheets, a
slider:
column may now set ashow_labels: yes
option to show the min and max values on either side of the slider. This defaults tono
. -
[Sheets/Sliders] In sheets,
slider:
columns can specify customthreshold_colors:
to override the defaults. This is a map with limits as keys and colors as values. -
[Sheets/Search] On sheets,
search:
columns can now provide an optionalicon:
image. -
[Workspaces] Dashboard workspace tabs now support a
locked@bool:
advanced option. This hides the editing toolbar (add widget, edit dashboard) at the top of the tab even from owners of the page. It also prevents dragging widgets. Tabs can still be edited from the top-right menu. -
[Records/Packages/Library] Library packages can now be created from workflows, automations, and the API. For instance, a workflow could add a new type of workspace widget. Clicking ‘Add widget’ would use the package to create copies of it.
-
[Setup/Teams] When creating a new worker account, default pages can be automatically added to their menu. This is configured in Setup » Teams » Configure.
-
[Installer/Tutorial/UX] The installer now automatically adds the ‘Tutorial’ and ‘Checklist’ workspace pages to the first worker’s menu.
-
[Install/Extras] Added a final
cerb_setup.sql
example to the baseline SQL scripts. A new database will be fully initialized without the browser-based guided installer by importingcerb_base_tables.sql
,cerb_base_rows.sql
, andcerb_setup.sql
. This is useful for automated testing, containers, and cloud environments. -
[Automations/Commands] In automations, added
cerb.commands.email.relay.sign
to api.command:. This generates the signedMessage-Id:
header for use with manually generated outgoing worker relay messages. -
[Automations/Commands] In automations, added
cerb.commands.email.relay
toapi.command:
. This sends relay messages to a list of external worker email addresses. -
[Sheets/Code] In sheets, added a new ‘code’ column type. This displays preformatted text with syntax highlighting. It’s much more efficient than using read-only code editors.
-
[Automations/Scripting] In automation scripting, added a cerb_calendar_get_relative_date function for calculating relative dates using calendar availability. For instance, if a calendar is available on weekdays from 8am-8pm, then
+2 hours
fromFriday 7pm
isMonday 9am
. -
[Metrics/Data Queries] In data queries, metrics.timeseries queries now support the
timeblocks
format. This output can be directly visualized by ‘Time Blocks’ widgets (e.g. worker activity heatmap). Previously this required adata.query
automation. -
[Metrics/Data Queries] In data queries, metrics.timeseries queries now support the
dictionaries
format. This output can be directly rendered in ‘Sheet’ widgets. Previously this required adata.query
automation. -
[Interactions/Worker] In
interaction.worker
automations, asubmit:buttons:
prompt can conditionally hide buttons. -
[Connected Accounts/UX] When adding a new connected account, it’s now possible to create a connected service at the same time. Previously, if a connected service wasn’t created beforehand then the new account popup was inexplicably blank. This also streamlines the configuration of workflows.
Changed
-
[Mail/Drafts] Drafts of
ticket.reply
type can now be created without aworker_id
by automations (e.g. auto replies). These drafts are only editable by admins and will be attributed to a worker who edits them. -
[Installer] In the installer, combined the ‘demo’ and ‘prod’ packages into a single ‘base’ package. There are separate workflows for ‘cerb.tutorial’, ‘cerb.demo.data’, and ‘cerb.quickstart’. This makes it possible to completely remove demo data when moving into production.
-
[Installer/Styles] Changed the installer to use dark mode.
-
[Installer/UX] In the installer, streamlined the final two steps (register/finished) into a single step.
-
[Workspaces/Pages] When adding a new workspace page, the ‘Home’ template in the library now includes tabs for ‘Open’ and ‘Waiting’ after ‘My Work’. Workers would check this after their assignments unless using an auto-dispatcher.
-
[Automations] In automations, the http.request: command no longer treats non-2XX response status codes as errors (e.g. 404, 503). This allows them to be properly handled by subsequent automation logic rather than requiring an
on_error:
handler. -
[Activity Log/Performance] Optimized activity log storage for large environments. The
context_activity_log
database table is among the largest in busy Cerb Cloud instances (~20GB). Previously, log entries stored the activity translation ID and the record label/url for the actor/target. These are no longer stored and are instead fetched from the database when displaying a page of log entries. Internal URLs are stored using the shortercerb:record_type:id
format. These changes reduce the table size by ~80% for new log entries. -
[Maint/Performance] In the nightly maintenance scheduler job, further optimized the bulk purge of deleted tickets that exceed the ‘undo’ window. Previously, purging message content in the database storage engine deleted rows individually by ID. Now it can delete batches of IDs. Optimized the deletion of
context_link
andcontext_activity_log
. In a test of deleting over 1M tickets the changes performed 250% faster. -
[Maint/Performance] In the nightly maintenance scheduler job, optimized the bulk purge of unlinked attachments.
-
[Records/Buckets/UX] In the bucket editor, added a ‘Save & Continue’ button.
-
[Platform/JSON] Functionality that exports to JSON (e.g. automations, widgets) no longer escape UTF-8 characters by default.
-
[Profiles/Library/Performance] On ticket profiles, the ‘Participants’ widget in the library now expands contact records in a single query.
-
[Groups/UX] Improved the usability of the group editor popup. It is now organized into tabs for: Profile, Outgoing Mail, and Members. The ‘Members’ splits a long roster into multiple columns. Group membership is now set with a dropdown rather than a trio of radio buttons. The roster bulk update options moved into a toolbar. A new ‘Reset’ bulk option restores the original state of the roster.
-
[Roles/UX] When editing roles, improved the interface for itemized permissions. The ‘Records’ and ‘Other’ tabs have been combined into a single screen. This makes ‘Other’ more obvious after several clients mentioned not noticing it. Record permissions now use three columns (rather than two) on wider displays. The record types are properly sorted by translated label. Added permission IDs to a tooltip.
-
[Workers/Impersonate] The ‘Impersonate’ button for admins moved to worker card and profile toolbars.
-
[Workers/Impersonate] Admin workers can no longer be impersonated by other admins.
-
[Cards/Widgets] On PGP Public key cards, updated the built-in widgets for ‘Subkeys’ and ‘Public Key’.
-
[Search/Data Queries] In search queries and data queries, double-quoted text may contain escaped quote characters by prefixing them with a backslash (e.g.
\"
). Previously it wasn’t possible to search for literal quote characters. -
[UI/Buttons] In the UI, buttons and their icons are now sized using relative measurements (
em
) rather than fixed pixels. For instance, this allowstext_size:
in sheet columns or toolbars to also change the size of buttons. -
[Sheets] In sheets,
toolbar:
columns now respond to thetext_size:
option by resizing buttons and their icons. -
[Data Queries] On
data.query.types
data queries, adocs_url
key contains a URL to the documentation for each data query type. -
[Automations/Workflows] In the automation editor, the export popup now provides ‘package’ and ‘workflow’ formatted output.
-
[Cards/Widgets/Workflows] In the card widget editor, the export popup now provides ‘JSON’ and ‘Workflow’ formatted output.
-
[Profiles/Widgets/Workflows] In the profile widget editor, the export popup now provides ‘JSON’ and ‘Workflow’ formatted output.
-
[Workspaces/Widgets/Workflows] In the workspace widget editor, the export popup now provides ‘JSON’ and ‘Workflow’ formatted output.
-
[Chart KATA] In Chart KATA widgets with a
timeseries
axis, added an example for 12-hour times (e.g. 4 PM). -
[Profiles/Performance] Profile tabs per record type now use the cache rather than a database query.
-
[Project Boards] Project Board Column records now have a
pos
field to rank their position on the board. Previously this was stored incolumns_json
on the board, which was inefficient when creating boards from packages or workflows (i.e. boards and columns needed to know each other IDs ahead of time). -
[Classifiers/Plugins] Moved the Classifiers functionality to an optional plugin. When this isn’t needed, it simplifies UX by removing four record types (classifiers, classifications, classifier entity, and classifier example).
-
[Sheets/Sliders] In sheets,
slider:
columns now supporttext_size:
for scaling. -
[Mail/UX] When composing and replying to email, more informative error messages are now sent back to the browser. Previously, in some situations, the ‘Please wait’ spinner could display indefinitely.
-
[Mail/Relay] On ticket profiles, revamped the ‘Relay to’ reply option to use an email address chooser (defaulting to worker addresses) rather than an inline menu.
-
[Workers/UI] New worker accounts default to dark mode.
-
[Sheets/Tables] In sheets using the
table
layout, specifying aparams:column_widths:
will switch into a fixed width layout where the widths of columns can be set manually as percentages. The value is a map of column names as keys with widths as values. -
[Email/Signatures/UX] When creating a new email signature record, example content is now provided.
-
[Installer] Removed the ‘SMTP Outgoing Mail’ step in the installer, since many modern providers require more complicated authentication like XOAUTH2. This can be set up after installation using connected accounts. A ‘Null’ mail transport is now always configured by default.
-
[Connected Accounts/AWS/UX] When using an ‘Amazon Web Services’ connected account in automations, the
X-Amz-Date:
HTTP header is now automatically added if omitted. -
[Automations/Files] In automations, the
file.read:
command now defaults to alength:
of 4MB if not specified. Previously this was 1MB. -
[Automations/Files] In automations, the
file.write:
command now always returns the newtoken:
in theoutput:
dictionary. Previously this was only returned when appending to an existing automation resource file. -
[UI/Sheets] In sheets using the
table
layout, made the column heading labels more distinct. Previously these were difficult to distinguish from the rows. -
[UI/Sheets] In sheets using the
fieldsets
layout, made the column heading labels more distinct. Previously these were difficult to distinguish from the rows. -
[Interactions/Sheets] In worker interactions with a
sheet:
form element, added thehref_new_tab@bool
option to autocompletion.
Platform
-
[Platform/Mail/Dependencies] Replaced the abandoned Swiftmailer dependency with Symfony Mailer for outgoing email.
-
[Docker] Updated the Dockerfile to use PHP 8.2 and Ubuntu 23.10.
-
[Platform/Dependencies] Updated the Twig template engine from v3.6.2 to v3.8.0. This adds new capabilities to automation scripting.
-
[Platform/Dependencies] Upgraded the GuzzleHttp dependency from 6.5.8 to 7.8.2.
-
[Platform/Ace] Updated the Ace code editor from v1.12.5 to v1.32.3.
-
[Platform/Mail/Dependencies] In the Devblocks platform, abstracted the outgoing email service to remove the dependency on legacy Swift Mailer. It makes it possible to support non-SMTP mail transports. For instance, email sending web APIs like Postmark.
-
[Platform/HTTP] When an HTTP request receives any error in response, the ‘Please wait’ loading panel will automatically be closed if it is open. Previously this had to be implemented in the error handler of each request.
Deprecated
-
[Installer] Disabled the ‘CRM’ and ‘Knowledgebase’ plugins by default in new installs (use custom records).
-
[Workspaces/Widgets] ‘HTML/Javascript’ workspace and profile widgets are now marked as deprecated. These should be migrated to ‘Sheet’ or ‘Automation’ widgets.
Removed
-
[Connected Services/Packages] Removed ‘Nest’ from the connected accounts package library. The service has been retired and merged into Google Home.
-
[Portals/Templates] In the Support Center portal configuration, several templates for core functionality are no longer customizable (e.g. register, login). Changes to these files often broke portals on upgrades.
-
[Storage/Database] The ‘Database’ object storage engine no longer allows arbitrary MySQL connection details. It always uses the local database.
storage_
tables in an external database must be manually migrated to the main database (e.g. SQL dump + import). -
[Storage/Database] The ‘Disk’ object storage engine no longer allows arbitrary filesystem path details. It always uses the local storage filesystem. Existing storage directories in an external filesystem must be manually merged, symlinked, or mounted. The
APP_STORAGE_PATH
setting inframework.config.php
can override the local base path (e.g. volume mount). -
[Tour] Removed the neglected ‘tour’ feature in favor of the new ‘Tutorial’ workflow.
-
[Welcome] Removed the neglected ‘Welcome’ page for new workers in favor of the new ‘Tutorial’ workflow.
-
[Plugins/Twitter] Removed the ‘Twitter’ plugin. This functionality can be reimplemented with automations and custom records. This does not remove existing data.
Fixed
-
[Activity Log/UX] In the activity log, the ‘Cerb’ actor no longer shows a broken hyperlink.
-
[Login] Rate-limited submission of the login forms. Previously, it was possible to submit many times by rapidly clicking the button or holding down the
enter
key. -
[KATA/UX] In KATA, fixed an issue with block value annotations like
@raw
where non-indented blank lines terminated the block. This could happen with some code formatting tools. Block values now rewrite blank lines to match the indent of the next non-blank line. -
[Worklists] Fixed an issue where the last column of a worklist could be omitted if too narrow in proportion to the other columns.
-
[UI/Tabs] Fixed a visual defect when UI tab sets wrapped to additional rows. Also fixed an issue where the selected tab became wider and moved the other tab positions.
-
[Sheets] Fixed an issue with sheets using
grid
orcolumns
layouts whereinteraction
columns didn’t work properly. -
[KATA] Fixed an issue when emitting an object to KATA. If a key is a nested array, it’s now written using
@json
rather than@list
. -
[Project Boards/Profiles] Fixed an issue with ‘Project Board’ profile widgets where placeholders couldn’t be used for the
ID:
(e.g.{{record_id}}
). -
[Plugins/Domains] Fixed an issue in the ‘Domains’ plugin where worklists didn’t display the value in the ‘Server’ column.
-
[Workspaces/Widgets] Fixed an issue on workspace tabs where two widget renders that timed out could prevent all subsequent widgets from loading. Thanks to 1Password for the bug report.
-
[Platform/Updater] Fixed an issue on the
/update
endpoint where frequent parallel requests during a long update can temporarily corrupt the translations cache. This showed text likecommon.search
rather than a translated phrase ‘search’, and was fixed by running/update
again. -
[Connected Accounts/AWS] Fixed an issue with ‘Amazon Web Services’ connected accounts in automations. If using an endpoint extension like
bedrock-runtime
the request signature wasn’t generated properly. -
[Toolbars] Fixed an issue in toolbars where
after:refresh_widgets:
had no effect ifrefresh_toolbar
was disabled.
Security
-
[Security/CSP/XSS] The
Content-Security-Policy
HTTP header no longer permitsunsafe-inline
inscript-src
. All script blocks now use a random per-session “nonce” token. This significantly reduces the potential XSS attack surface. -
[Security/Developers/CSP] Implemented
DevblocksPlatform::getRequestNonce()
for generating a “nonce” (number used once) for theContent-Security-Policy
to harden inline scripts and stylesheets against XSS attacks. This is currently per-session, but ideally it will be per-request in the near future. -
[Security/CSP] Added a
Content-Security-Policy
“nonce” attribute to all inlinescript
tags to use a more strict policy by default. This prevents authorized script blocks from being evaluated. -
[Security/CSP] Added a
Content-Security-Policy
header on all endpoint responses. Previously this was only enforced on UI pages. -
[Security/UI/CSP] Untrusted links (e.g. email message) are now rewritten with href
#cerb-external-link
and adata-cerb-external-link
DOM attribute. Previously the links were rewritten with ajavascript:
scheme, which is no longer permitted with the strictContent-Security-Policy
. This approach makes it easier to use sanitized HTML in third-party integrations (e.g. API). The security popup is no longer displayed when the text of a link exactly matches its URL. -
[Security/CSP/Widgets] ‘HTML/Javascript’ workspace and profile widgets now have a
current_worker_nonce
placeholder for the per-sessionContent-Security-Policy
script-src ‘nonce’ token. This must be added to thenonce
attribute in<script>
blocks or custom widgets will no longer work.