Blog

Release announcements, helpful tips, and community discussion

8.2.1

Cerb (8.2.1) is a maintenance update released on November 6, 2017. It includes 27 minor features and fixes from community feedback covering the 8.2 update. You can follow these instructions to upgrade.

  • [Mail/Buckets] Fixed an issue with the bucket ‘Send as’ setting not properly using the group-level default.

  • [API/Records/Links] In the API, implemented a ‘links’ field for create and update on /records. This allows links to be created on a new or updated record in a single request.

  • [Records/Validation] Fixed an issue with the validation service in Devblocks when a field key begins with custom_ and isn’t a custom field.

  • [Records/Validation] Fixed an issue in the validation service where custom record link fields always failed. These now properly validate using the record type configured on the field.

  • [Time Tracking/Cards] Fixed an issue with time tracking cards. Administrators weren’t able to edit time entries for other workers.

  • [Knowledgebase/API/Snippets] Placeholder dictionaries for knowledgebase categories can now expand the parent_ placeholder.

  • [GPG/Encryption] Fixed an issue with GPG Public Key records. If the fingerprint in the database was somehow blank, the card for the key showed the subkeys of all other keys.

  • [API/Attachment] In the API, it’s now possible to set a content key on attachment records during creation or modification. This accepts either a text value (the default), or a base64-encoded binary file in data:mime/type;base64, URI format.

  • [API/Webhooks] In the API, webhook records now display the extension_params key.

  • [Worklists/Webhooks] The webhooks worklist no longer shows the (+) create option to non-admins.

  • [Worklists/Mail/Templates] The email templates worklist no longer shows the (+) create option to non-admins.

  • [Records/Validation] Added a language() validator to records. This ensures the language is formatted like en_US.

  • [Records/Validation] Added a timezone() validator to records. This ensures the timezone field is formatted like America/Los_Angeles.

  • [Records/Validation] Added an extension() validator to records. This ensures the extension field is valid for the given extension point.

  • [Records/Validation] Added a context() validator to records. This ensures the context field is valid record type. It also accepts aliases like ticket rather than full IDs.

  • [API] Fixed an issue with authorizing API request signatures. If a query argument was formatted like &field without a trailing = then the request signature would fail to validate.

  • [Records/API/Validation] In records, all of the validation logic for creating and updating records has been consolidated for reuse between the web UI, API, packages, and bots. This makes it much simpler to do abstract record operations.

  • [Workers/Cards] In the worker record editor, the delete option now uses a two-step confirmation. After deletion, the underlying card popup is automatically closed.

  • [Records/API] Added a new /records endpoint to the API for performing abstract operations on all record types (e.g. create, retrieve, update, delete, search). The record type is specified in the path like /records/tickets/, and aliases are supported in addition to full context IDs. Custom records are supported. All fields are supported. All of the same validation logic from the UI is enforced in the abstract API (roles, record ownership, etc). This drastically simplifies working with the API. Previously, each record had to be specifically implemented as an API endpoint, with a limited number of fields, and code that used the API had to hardcode all of those paths. See: Records API

  • [Records/API/Upserts] Upserts are now supported in the abstract records API. An “upsert” is a single operation that updates an existing record when a match is found, or creates a new record when a match isn’t found. Upserts are performed with a request like PATCH /records/<record-type>/upsert.json. The body has the same format as a PUT update using an array of fields[key]=value. Upserts require a query parameter with a quick search query that must match exactly 0 (insert) or 1 (update) rows. For instance, you could upsert an organization with the query name:"Apple, Inc.", and if an organization is found it is updated, and otherwise a new organization is created. To perform an upsert, a worker must have permission to create and modify records of the given type. They also must have access to update a matched record. Upserts are particularly useful when synchronizing records into Cerb from a third-party source. For instance, when issues are updated in a bug tracker (like GitHub Issues or JIRA), a webhook could prompt Cerb to pull those changes into a custom record. The upsert query could match on the external ID to determine if a record was previously synchronized or not. See: Records API Upsert

  • [API/Credentials] API credentials can now only be created by administrators. Admins can create credentials for other workers and determine the allowed endpoints. A worker can view their secret key by clicking the ‘(reveal)’ link on the API credential’s card.

  • [API/Cards] On API key cards, an ‘Allowed Endpoints’ section displays the privileges of the keypair. Previously this was only visible with edit permission on the key. With the change that only admins can modify API keys, this meant that workers weren’t able to see their own API permissions.

  • [API/Attachments] In the /records API, attachments can now include an attach field with an array of context:id tuples to link the file to.

  • [Packages/Custom Records] In packages, it’s now possible to create a custom record type, and import records of that new type, in the same package.

  • [Roles/Tickets] Fixed an issue that prevented workers from moving a ticket into a group they are not a manager/member of. [#510]

  • [Custom Records/Permissions] On custom records, owner__context is now only required when creating a custom record, and not on updating.

  • [Bots/Behaviors] In bots, when using a dictionary as a string placeholder, it is now automatically converted to JSON text from an object.