v0.15.3
28 September 2026 Latest- Scan cost. The hourly scan resolves opt-outs, exclusions and cooldown for the whole candidate batch in three
IN (…)queries instead of three round trips per order. Skip logging is unchanged (still once per order and reason). A failed lookup aborts the channel run rather than sending past the exclusion list. - Overview / Exclusions tabs.
GET /statsno longer runs the full dry-run scan on every open: the pending summary is memoised for 60 s, shared between concurrent callers, and dropped after a real run, a manual send, or a config / exclusion / opt-out change. - Rating cache. A failed Trustpilot / Google lookup is remembered for 10 minutes (a success still for 6 h), so a transient outage no longer blanks the star block until the next restart. The admin "check" button probes live and never writes the key/domain typed in the form into the shared cache. A rating with a non-numeric score can no longer throw mid-send (
Number.isFiniteguard,formatScore). - Templates.
review_template.bodyis MEDIUMTEXT (16 MB; was 64 KB — templates with inlined images were silently truncated). Saving now returns400with the size in the message when the subject exceeds 255 characters or the body 4 MB, and a500with the database message instead of a bare "Save failed"; the admin UI shows that message. - Log retention. Monthly (worker only)
review_logrows withstatus <> 'sent'older than 18 months are deleted in batches of 5 000.sentrows are kept — dedup and cooldown depend on them. - Postgres. A corpus test (
tests/pg-corpus.test.ts, skipped unlessHULO_PG_URLis set) extracts every SQL statement insrc/, translates it with the dialect adapter and runs it against PostgreSQL 17 with quoted-camelCase stand-ins for the Vendure tables. 43 statements, all passing.