Skip to content

Heisenberg v0.0.2 - email personalization, builder phases, URL-filter XSS fix

Choose a tag to compare

@tedydonel tedydonel released this 27 Aug 06:49
· 5 commits to master since this release

What's new in 0.0.2

This release is dominated by the email subsystem and two fixes that touch every surface.

✉️ Email personalization (host variables + admin batch export)

  • Host-defined email variables: register any dotted key with a typed formatter contract and a safe non-secret sample. Six built-in types ship (text, url, email, number, boolean, date).
  • Strict context-aware interpolation before rich-text sanitization / URL filtering, with value-free aggregated errors for unknown tokens, missing values, formatter failures, and target mismatches.
  • Per-recipient EmailRenderer and HeisenbergMailable seams across MIME subject, HTML, plain text, size accounting, and CID embeds — while preserving legacy token-free calls.
  • Sample-only public/editor preview, size, and single HTML/EML export. Runtime maps are never read from author-facing GET query strings, bodies, or headers.
  • Email-only authoring picker (subject, rich text, compatible text settings, URL settings) inserting literal {{ dotted.key }} tokens via text nodes / setRangeText, never innerHTML.
  • Admin-only, all-or-nothing batch ZIP export (email.generate, default admin) of exactly N recipients × requested locales as HTML or EML. Recipients are explicit value maps; Heisenberg still does not own SMTP, subscribers, campaigns, or recipient discovery.
  • Usage docs (docs/email-personalization.md) and compile-checked host examples (examples/EmailVariables/).

🧱 Builder / editor

  • Single-row content model — one post carries every configured locale instead of separate translation rows.
  • Native threaded comments, moderation, a public thread API, and shared-surface route wiring.
  • SEO persistence, scoring, sitemap, hreflang, and opt-in public post routes.
  • User-saved block patterns, quick-inserter browse-all, number-stepper UI, gradient values, nested/per-state fonts, and expanded column/inspector controls.
  • Responsive featured-image rendering in the public preview.
  • Deep published-config merging plus heisenberg:config-diff.

🔒 Security

  • javascript: URL-filter XSS bypass fix in BlockRenderer::safeUrl() / NullMediaResolver::safeUrl(): control characters inside the scheme are stripped before parsing (e.g. java\tscript:…), with regression coverage for all obfuscated variants.
  • target="_blank" now emits rel="noopener noreferrer".
  • ThemeRepository::save() writes with LOCK_EX.

🐛 Notable fixes

  • Autosave no longer reverts queued status/slug/date; schedule/publish timestamps no longer drift with viewer timezone.
  • Email rendering matches authored content, including translated block attributes.
  • Discussion settings target the real toggle input; disabled commenting keeps a frozen thread while hosts can choose how to display it.
  • Duplicated blocks get fresh IDs; navigator selection, child toolbar targeting, column flex-basis, heading specificity, icon theming, and font-family quoting fixed.
  • AI assistant icon lookup, translation preservation, prompt-size limits, composer height, SEO scoring and sitemap locale assumptions.

Built against

  • PHP 8.2 / 8.3 / 8.4 × Laravel 11 / 12 / 13, prefer-lowest + prefer-stable — all green on 14c9037f.
  • Full suite: 1539 tests / 6121 assertions (email wave alone: 8 feat(email) commits).

Install

composer require heisenberg/heisenberg
php artisan migrate
php artisan storage:link

Open /editor and start writing.