v36.1

Notifuse/notifusev36.1Aug 2, 2026by pierre-b

AI Summary

This release focuses on critical bug fixes related to workspace deletion, template validation, and Liquid rendering in preview text. It addresses permission denied errors, crashes during template creation, and issues with preview text encoding and structure.

Key Highlights

  • Fixed workspace deletion to correctly revoke privileges on the system database, resolving permission denied errors.
  • Resolved crashes in template creation/update when the visual_editor_tree field is missing by returning a proper 400 error instead of a 502.
  • Fixed duplicate preview elements in templates containing self-closing or attribute-based MJML preview tags.
  • Corrected Liquid rendering in preview text to prevent XML parse errors and ensure special characters are properly encoded.

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)