This website requires JavaScript.
Explore
Help
Sign In
starred
/
warmbly
Watch
1
Star
0
Fork
0
mirror of
https://github.com/warmbly/warmbly.git
synced
2026-09-13 08:05:05 +00:00
Code
Issues
Packages
Projects
Releases
Wiki
Activity
Files
6466a8bf9178c439e550e37b92ed8ab1c1afd55d
warmbly
/
docs
/
content
/
docs
T
History
Matthew Meszaros
55894a0e9d
feat: fix the campaign Leads tab and contact export stopping partway through a large list by rebuilding the contacts keyset cursor: the boundary subquery named the outer row's alias so Postgres read it as a correlated self-reference and the whole comparison collapsed to c.id >= <cursor uuid>, serving each page the newest rows of a randomly shrinking id range until it ran out at a third of the leads, so the opaque token now carries the ordering it was taken under plus the boundary row's own sort value and id, rejects a token replayed under another sort, and pairs with a direction-following id tiebreak, an ORDER BY that names its NULL placement, a new (organization_id, created_at DESC, id DESC) index, EXISTS campaign and category filters and a lateral campaign_count the query only joins when a filter or sort asks for it, taking a page of a 50k-contact organization from 120ms to 3ms, and the dashboard now keeps the rows it already loaded when a later page fails and says how far through the list Load more is
2026-09-08 05:01:15 -07:00
..
api
feat: fix the campaign Leads tab and contact export stopping partway through a large list by rebuilding the contacts keyset cursor: the boundary subquery named the outer row's alias so Postgres read it as a correlated self-reference and the whole comparison collapsed to c.id >= <cursor uuid>, serving each page the newest rows of a randomly shrinking id range until it ran out at a third of the leads, so the opaque token now carries the ordering it was taken under plus the boundary row's own sort value and id, rejects a token replayed under another sort, and pairs with a direction-following id tiebreak, an ORDER BY that names its NULL placement, a new (organization_id, created_at DESC, id DESC) index, EXISTS campaign and category filters and a lateral campaign_count the query only joins when a filter or sort asks for it, taking a page of a 50k-contact organization from 120ms to 3ms, and the dashboard now keeps the rows it already loaded when a later page fails and says how far through the list Load more is
2026-09-08 05:01:15 -07:00
development
feat: frontend half of the admin panel upgrade: drop ten unused dependencies, the dead worker-load and plan requests, the stub pages and the retired permission names, fix the analytics client that sent the wrong query parameters and the mail test toasts that used an unmounted toaster, add a Cmd-K command palette with live user, organization, mailbox and worker search, a mobile nav drawer, document titles, a Sentry-wired route error boundary and permission gates on every route, replace polling with the realtime spine wherever an event exists, fold Analytics into Overview with a signups-by-channel card, merge System Status into Setup and health and Settings, Notifications and Effective limits into Configuration as tabs with redirects from every old path, add the Sync, Sends, Jobs, Fleet, Admins and Transfers pages plus API-key, webhook and transfer tabs on the organization page, mailbox reassignment on the worker page and abuse and action-history tabs on Warmup, and add the admin-panel docs page with every nav reference updated
2026-09-07 21:40:38 -07:00
guides
feat: address the review on the loopback mailbox mode by building every mail address with net.JoinHostPort, so an IPv6 literal keeps the brackets a host:port string needs and "::1" on 1143 stops dialling a host called "::1:1143" with no port, by moving the self-hosted half of the rule into the dialers as well as the connect form, because an organization archive exported from a self-hosted instance carries its mailboxes and an import must not hand a hosted worker one that dials its own loopback in the clear, by refusing an unencrypted CSV row on a hosted instance where the API would only reject it a moment later, and by saying in the docs that the port never selects the mode and that the whole 127.0.0.0/8 range counts
2026-09-07 08:27:54 -07:00
learn
feat: give every campaign email a working opt-out: a reply-to-opt-out line by default or an unsubscribe link (workspace setting under Settings > Sending with a per-campaign override and a {{.UnsubscribeLink}} variable), signed per-recipient unsubscribe links served on the API origin so the List-Unsubscribe header no longer points at a dead warmbly.com page, a confirm page on GET with RFC 8058 one-click on POST and a resubscribe button, reply opt-out detection through the whole-word compliance lexicon with quoted history stripped, a first-class suppression list (Contacts tab, GET/POST/DELETE /suppressions with address and domain entries, audited removal, contact drawer action), the contact Subscribed flag enforced in campaign routing, migration 000122 with a shared recipient_suppressed() predicate, and docs for all of it
2026-09-03 01:52:40 -07:00
meta.json
Publish development docs to docs.warmbly.com
2026-06-28 13:25:08 +02:00