Hardening release. Two default behavior changes — read these first if you're upgrading:
⚠️ Upgrade notes (behavior changes)
- Check failures now fail open by default. Previously, any error during the disposable check (missing table, DB hiccup) rejected the record — a broken blocklist could block every signup. Now the record is allowed through with a loud error log. Restore the old behavior with
config.on_check_failure = :reject. - Subdomains of listed domains are now blocked by default.
user@x.tempmail.comno longer slips past a listedtempmail.com(walks up to 3 parent labels, never matches bare TLDs). Restore exact-only matching withconfig.check_parent_domains = false. Allowlist a specific subdomain viaexcluded_domains— exact entries always win.
Added
- Bundled seed list (8,201 domains): fresh installs are protected immediately — the install migration seeds the table, and updates fall back to the bundled snapshot if the remote fetch fails against an empty table. Closes the fresh-install window where everything passed until the first successful remote update.
config.check_parent_domainsandconfig.on_check_failure(see above).
Improved
- Domain list updates: single bulk
insert_all(was per-rowcreate), 10s fetch timeouts (was 60s defaults), skipped rows reported instead of silently swallowed, input normalization + case-insensitive dedupe. additional_domains/excluded_domainsmatch case-insensitively everywhere.- Apps without an initializer no longer fail every validation — configuration is lazily initialized.
Full details in the CHANGELOG. 299 tests across Rails 7.2 / 8.0 / 8.1.