v36.1

adbar/trafilaturav36.1Aug 2, 2026by pierre-b

AI Summary

Addresses critical bugs regarding workspace deletion, template validation, and preview text rendering involving MJML and Liquid.

Key Highlights

  • Fixes workspace deletion revoking system database privileges.
  • Fixes template validation crashing on missing visual_editor_tree fields.
  • Fixes duplicate preview text injection in MJML templates.
  • Fixes Liquid rendering in preview text to prevent XML parse errors.

Full Release Notes

- **Fix**: Deleting a workspace no longer revokes the application user's privileges on the *system* database. The revoke statements applied to the connected database rather than to the workspace being deleted, so afterwards authentication failed with `permission denied for table users` (superuser deployments, the default, were unaffected). Workspace databases are now removed with a single `DROP DATABASE ... WITH (FORCE)` and the system-database cleanup runs in one transaction. To repair an already-affected install, connect to the system database and run `GRANT ALL ON ALL TABLES IN SCHEMA public TO <db_user>;` plus the same for `ALL SEQUENCES` (#396)
- **Fix**: `templates.create` and `templates.update` no longer crash the request when the `email` object omits `visual_editor_tree`. Validation called a method on the missing tree and panicked, so the connection was dropped and API clients behind a reverse proxy saw a bodyless `502 Bad Gateway`; such payloads now return `400` naming the missing field and pointing to the code-mode alternative (`editor_mode: "code"` with `mjml_source`). Also applies to per-language `translations` entries (#401)
- **Fix**: Applying preview text to a template whose MJML already contains a self-closing `<mj-preview />`, or an `mj-preview` carrying attributes, no longer injects a *second* preview element. Only the plain `<mj-preview>` form was recognised, so the other two shapes were treated as "no preview present" — the attribute form shipped two preheader blocks with the stale text still in the first, and a bare `<mj-preview />` (which an `mj-liquid` block can emit) was duplicated instead of filled. Both shapes are now matched, attributes are preserved, and a self-closing tag is expanded in place (#394)
- **Fix**: Preview text containing Liquid no longer breaks sends for code-mode templates, and preview or title text that renders to a value containing `<` or `>` no longer fails compilation. Code-mode templates escaped the preview text *before* rendering it, so a feed value containing `&` (e.g. a "News & Updates" subject) aborted the whole send with an XML parse error, and Liquid comparisons such as `{% if a > b %}` silently evaluated the wrong branch because the operator had been entity-encoded. Separately, `<` and `>` were escaped with named entities that the MJML parser decodes back into markup before parsing, so an `mj-preview` or `mj-title` block whose Liquid resolved to a value containing angle brackets failed to compile (#394)
- **Fix**: Liquid in a template's *Preview Text* is rendered again at send time for visual-editor templates whose body has no `mj-preview` block — the common case for console-built templates. The preview text was spliced into the MJML after Liquid processing had already run, so expressions like `{{ global_feed.subject }}` reached recipients literally in the inbox preview text; the injected value is now rendered through Liquid first, and malformed Liquid in preview text surfaces as a compile error instead of being sent raw. Rendered preview values containing `<`, `>` or `&` no longer break the send either: the injected text is escaped with numeric character references, which survive MJML parsing where the named `&lt;`/`&gt;` entities are decoded back into markup (#394)