Matthew Meszaros
d855abfaa3
feat: replace the marketing site's Open Graph and Twitter card with a top-left 1.91:1 crop of the new dashboard export, and derive og:image type, width and height from the real image so blog covers stop declaring 1280x640 jpeg
2026-09-19 18:45:55 +02:00
Matthew Meszaros
d8a3e70450
Merge pull request #609 from warmbly/fix/suppression-add-dialog
...
feat: suppression add dialog, row menu fix, and warmup suppression cleanup
2026-09-19 15:51:20 +00:00
Matthew Meszaros
530b184748
Merge pull request #607 from warmbly/feature/two-factor-setup-flow
...
feat: rebuild two-factor setup in Settings > Security as a three-step wizard with a QR code, manual setup key and TOTP parameters, inline code errors, and recovery codes with download, copy and print; show enable date and remaining recovery codes, add POST /auth/2fa/recovery-codes to regenerate them, return two_fa_invalid_code on a mismatched code, and update the security guide, API reference, error codes and OpenAPI
2026-09-19 15:48:03 +00:00
Matthew Meszaros
6b834b49f6
feat: cap the suppression add dialog's chip preview at 200 with a count of the rest, and refuse a paste over the server's 5000-entry limit before submitting instead of after
2026-09-19 08:46:24 -07:00
Matthew Meszaros
68ec5a016e
feat: delete the reauth attempt counter when a refund leaves it at zero or below so it always carries an expiry, and focus the first field of a 2FA dialog on open
2026-09-19 08:43:11 -07:00
Matthew Meszaros
e9d1a7e734
feat: reserve the per-account reauth attempt atomically before checking a password or 2FA code, keep the 2FA dialogs open while a request is in flight, move and trap focus in them, show a retry row when 2FA status fails to load, and drop Idempotency-Key from the recovery-code route with the reason documented
2026-09-19 08:36:59 -07:00
Matthew Meszaros
b8f47c94f4
Merge pull request #608 from warmbly/feat/unibox-message-details
...
feat: open a message details panel in the unibox from the recipient line, sender and an info icon, with every address, exact times, mailbox, folder, size and identifiers, and add email_id and folder to GET /unibox/:id
2026-09-19 15:31:23 +00:00
Matthew Meszaros
8349ac2695
Merge pull request #610 from warmbly/fix/posthog-sourcemap-dlx
...
Fix the PostHog source map upload on Cloudflare Pages
2026-09-19 15:25:50 +00:00
Matthew Meszaros
69ddac8c75
feat: replace the inline suppression add form with a modal dialog that previews each pasted address and domain as chips with counts and flags unrecognized values, fix the suppression row menu so Remove from list sits on one line with its icon and the added date no longer wraps, tint danger menu item icons red, and add migration 000186 removing suppression entries and deliverability events that only warmup sends produced
2026-09-19 08:23:10 -07:00
Matthew Meszaros
eceed10d89
feat: invoke the PostHog CLI as pnpm dlx @posthog/cli@<version> sourcemap ... in the web, admin and forms source map scripts, because pnpm dlx --package <pkg> <bin> is only understood by pnpm 10 and later and Cloudflare Pages builds the dashboards with an older pnpm that reads --package as the package name and fails the deploy on a registry 404
2026-09-19 17:23:10 +02:00
Matthew Meszaros
a1d3f3f3f1
feat: open a message details panel in the unibox from the recipient line, sender and an info icon, showing every From, Reply-To, To, Cc and Bcc address, sent and received times in the reader's zone, the mailbox, folder, size, Message-ID and In-Reply-To with one-click copy; summarise all recipients on the header line; add email_id and folder to GET /unibox/:id and document both
2026-09-19 08:22:14 -07:00
Matthew Meszaros
de10ca5216
feat: put 2FA disable and recovery-code regeneration behind the per-account reauth attempt budget and document it in the account API reference
2026-09-19 08:16:53 -07:00
Matthew Meszaros
274ff888a5
feat: rebuild two-factor setup in Settings > Security as a three-step wizard with a QR code, manual setup key and TOTP parameters, inline code errors, and recovery codes with download, copy and print; show enable date and remaining recovery codes, add POST /auth/2fa/recovery-codes to regenerate them, return two_fa_invalid_code on a mismatched code, and update the security guide, API reference, error codes and OpenAPI
2026-09-19 08:15:31 -07:00
Matthew Meszaros
7dd0177e0a
Merge pull request #604 from warmbly/feat/warmup-plan-cloud-upsell
...
feat: present the $15 pool plan as the Warmup plan everywhere: rename the plan row (migration 000185), add it to the dashboard catalog so the header and billing overview name it, show the cloud tier in a self-hosted instance's header pill and a Plan section under Settings > Warmbly Cloud with upgrade and manage links to the cloud billing page, nudge on the mailboxes page only when the free pool is full, drop the self-host framing from the cloud's checkout dialog, paths panel and locked screen, rebuild the checkout dialog in the plan chooser's style, pitch Premium on deliverability from one shared benefit list, and update the billing and Warmbly Cloud guides and the pricing FAQ
2026-09-19 13:00:55 +00:00
Matthew Meszaros
464ec521ca
feat: present the $15 pool plan as the Warmup plan everywhere: rename the plan row (migration 000185), add it to the dashboard catalog so the header and billing overview name it, show the cloud tier in a self-hosted instance's header pill and a Plan section under Settings > Warmbly Cloud with upgrade and manage links to the cloud billing page, nudge on the mailboxes page only when the free pool is full, drop the self-host framing from the cloud's checkout dialog, paths panel and locked screen, rebuild the checkout dialog in the plan chooser's style, pitch Premium on deliverability from one shared benefit list, and update the billing and Warmbly Cloud guides and the pricing FAQ
2026-09-19 05:57:41 -07:00
Matthew Meszaros
895c76210a
Merge pull request #603 from warmbly/fix/restore-home-hero-b2b-copy
...
feat: restore the home hero B2B outreach copy and first-paint mock scaling reverted by the CASA merge
2026-09-19 12:02:17 +00:00
Matthew Meszaros
d0857718c0
feat: restore the home page hero subheading about scaling B2B outreach and the first-paint hero mock scaling from PR #597 , which the CASA AL1 merge in PR #599 reverted by re-committing a stale copy of site/src/pages/index.astro
2026-09-19 04:58:49 -07:00
Matthew Meszaros
14724065b6
Merge pull request #602 from warmbly/fix/tracking-rust-toolchain
...
fix: raise the tracking builder to Rust 1.96 and pin the Rust CI job to it
v0.4.27
2026-09-19 11:55:42 +00:00
Matthew Meszaros
3923b50a2b
feat: raise the tracking builder to Rust 1.96 because the AWS SDK now declares rust-version 1.94.1, and pin the Rust CI job to whatever that Dockerfile says instead of stable so a dependency outgrowing the builder fails a pull request rather than a release
2026-09-19 13:49:43 +02:00
Matthew Meszaros
848e64865d
Merge pull request #600 from warmbly/fix/mailbox-disconnect-and-prod-errors
...
fix: workspace-scoped mailbox disconnect, eviction of mailboxes whose row is gone, and the production errors from this morning
2026-09-19 11:31:28 +00:00
Matthew Meszaros
834da184d9
feat: clear every dependency advisory that has an upstream fix, dropping the AWS SDK's legacy-rustls-ring default feature that was pulling a second hyper 0.14, rustls 0.21 and rustls-webpki 0.101 into the tracking service alongside the current ones, moving async-nats to 0.50 for the last old webpki and reqwest to 0.12, boxing the NATS producer variant the bigger client made oversized, refreshing the node trees with overrides for the esbuild and postcss-selector-parser that fumadocs pins, recording why the two unpatched cowlib advisories cannot be reached from a service that sets no cookie, and deciding the credential-validation timeout from the subscription context's deadline rather than the error's shape
2026-09-19 13:25:33 +02:00
Matthew Meszaros
28b3dc9f05
feat: move the CASA evidence pack out of this repository to CASA_EVIDENCE_DIR and make the generator refuse any destination inside the tree, because a pack that maps every control to its file and lists the advisories still open with their reachability conditions is a reconnaissance document for anyone attacking a self-hosted instance that has not updated yet
2026-09-19 13:08:33 +02:00
Matthew Meszaros
9b1eb4db7c
Merge pull request #601 from warmbly/test/multi-sender-reply-attribution
...
Test multi-sender reply attribution end to end
2026-09-19 11:08:27 +00:00
Matthew Meszaros
1497762d66
feat: add live regression tests proving replies to a campaign rotating across several mailboxes stamp each lead as replied and reach the campaign reply count, with and without thread headers, and document in the analytics guide that each lead's reply is expected in the mailbox that wrote to them
2026-09-19 04:05:34 -07:00
Matthew Meszaros
2c886a3202
feat: decide the credential-validation timeout from the subscription context rather than the error's shape so a Redis socket timeout inside a live deadline stays an internal error, and require a synthetic mechanism and an empty stack as well as a default object string before dropping an exception so a message that stringified an object alongside real text is still reported
2026-09-19 13:00:23 +02:00
Matthew Meszaros
acecd62c88
feat: scope mailbox disconnect and warmup lifecycle to the workspace rather than the member who connected the mailbox so an admin can act on every mailbox the list already shows them, evict a mailbox whose row is gone from every live worker when its provider errors arrive so a deleted mailbox stops calling the provider once a sync interval forever, subscribe before publishing the credential-validation job and classify a socket deadline as the retryable timeout it is, give the worker's validation reply its own budget so a slow mail host no longer loses a finished verdict, guard every global key handler against a keydown carrying no key, drop exceptions whose whole message is an object's default toString, make the Postgres pool size configurable, and record the CASA and security invariants in AGENTS.md
2026-09-19 12:49:46 +02:00
Matthew Meszaros
b09ec39907
Merge pull request #599 from warmbly/chore/casa-al1-security-assessment
...
feat: complete the ADA CASA AL1 control set and ship the assessment evidence pack
v0.4.26
2026-09-19 06:39:12 +00:00
Matthew Meszaros
03f59d4d6f
docs: state the tenant and key-shape invariants in these comments as the constraints they are, rather than as an account of what each check replaced, since this repository is public and every self-hosted instance that has not updated yet reads the same text
2026-09-19 08:28:41 +02:00
Matthew Meszaros
e0d68fddeb
style: format the realtime runtime config so mix format --check-formatted passes
2026-09-19 08:21:14 +02:00
Matthew Meszaros
e668a2a36b
feat: complete the ADA CASA v2.1.1 AL1 control set across authentication, sessions, access control, cryptography, input validation and configuration, adding a breached-password denylist and per-account login throttling, enforced multi-factor authentication on the admin panel, step-up confirmation before an action that mints a lasting credential, purpose-scoped session tokens, single-use TOTP steps, tenant verification on every cross-referenced identifier, security headers on every surface, encrypted webhook signing secrets, per-organization idempotency, PKCE and a minimal two-scope Gmail consent on the mailbox OAuth flow, bounded spreadsheet and archive decoding, a patched Go toolchain with govulncheck in CI, and the evidence pack under compliance/casa
2026-09-19 08:18:35 +02:00
Matthew Meszaros
6428e6b3e9
Merge pull request #594 from warmbly/feature/disable-google-oauth-new-mailboxes
...
feat: route new Gmail mailboxes through a guided app-password connect instead of Google sign-in, behind BOX_GOOGLE_OAUTH_CONNECT, leaving existing OAuth mailboxes sending and re-authorizable
2026-09-19 06:11:15 +00:00
Matthew Meszaros
8664684b3f
Merge pull request #595 from warmbly/fix/warmup-system-issue-592
...
feat: hold a pending warmup send when the day's target is cut after it was scheduled
2026-09-19 06:03:47 +00:00
Matthew Meszaros
c24f0265f2
Merge remote-tracking branch 'origin/main' into fix/warmup-system-issue-592
2026-09-18 22:47:16 -07:00
Matthew Meszaros
79bd4f62e3
feat: hold a warmup send whose send-time budget reports the mailbox not warming instead of letting it through, because a failed campaign read produces that sentinel and let a health-check mailbox send uncapped, and cover both held-status writes with a test that a hold whose write fails is retried rather than acknowledged
2026-09-18 22:47:09 -07:00
Matthew Meszaros
91ceb59fac
Merge pull request #598 from warmbly/fix/posthog-error-handling
...
feat: fix the open PostHog issues and the error handling underneath them
2026-09-19 05:45:18 +00:00
Matthew Meszaros
d46cfad597
feat: check the warmup daily target again at the moment a send executes rather than only when the next one is placed, so a spam placement, health band or partner loss that cuts the target while a send is pending holds it as skipped_daily_limit and parks the chain at the next opening with a reply-back's aim intact, fail closed when that count cannot be read, share one target resolver between the placer and the send-time gate, add the skipped_org_suspended task status the suspended-workspace hold has written since #233 without a migration so its write stops failing and leaving the task pending for the dispatcher to re-fire, and anchor the ramp live fixture in UTC off the day boundary so its assertions no longer depend on the host timezone
2026-09-18 22:39:52 -07:00
Matthew Meszaros
49acd51b64
feat: stop one recurring fault burying error tracking by reporting it once per five minutes with the count it stands for, keep a cache outage from answering every signed-in request with a 500 and from taking realtime down by treating an unreachable Redis as a miss and the websocket handshake nonce nothing reads as best-effort, answer a 5xx with a sentence the reader can act on while the call site's own words go to the log against the same request id, prefer the API's own message over the HTTP class in the admin and dashboard clients, and name the fix on a schema registry refusal, an SES sandbox rejection and a mailbox check that could not be run
2026-09-19 07:39:40 +02:00
Matthew Meszaros
caeeb1d2aa
Merge pull request #597 from warmbly/feature/home-hero-copy-and-instant-mock
...
feat: home hero copy about scaling B2B outreach, and a hero mock that renders on first paint
2026-09-19 05:39:25 +00:00
Matthew Meszaros
c42207ea5e
feat: rewrite the home page hero subheading around scaling B2B outreach and winning more clients in a wider max-w-3xl box, and render the hero dashboard mock on first paint by giving its frame a CSS 16:9 aspect ratio and scaling the shell from an inline script instead of a deferred bundled module that left the frame at zero height until it loaded
2026-09-18 22:38:35 -07:00
Matthew Meszaros
e8f14bb2fd
feat: address the review on the Gmail app-password connect by reading BOX_GOOGLE_OAUTH_CONNECT through config.GoogleOAuthConnect in the instance-settings table so a yes/on value cannot display true against a gate that parses it as false, dropping the coming-soon line from the walkthrough banner on deployments where Google sign-in is actually available, naming the 2-Step Verification app-password control an administrator still has rather than the Less secure apps page Google removed, saying the OAuth client re-authorizes existing mailboxes as well as refreshing them, and marking the marketing send trace as the Google sign-in path
2026-09-18 22:18:56 -07:00
Matthew Meszaros
0e652bf357
Merge pull request #596 from warmbly/feature/pricing-page-redesign
...
feat: rebuild the pricing plan cards as the home page's joined panel and redesign the self-hosted block
2026-09-19 05:10:17 +00:00
Matthew Meszaros
b884d65d8b
feat: rebuild the /pricing plan cards as the single joined panel the home page uses, replacing the four ring-outlined floating cards with shared hairline dividers, a tint plus top accent rule on the featured plan, annual price with struck monthly and a yearly-saving badge, and a sends-per-day meter, and redesign the self-hosted block into a two-column section whose right panel carries the two warmup pool tiers over a one-command install terminal, with the paid tier renamed Premium and sold on the premium pool, priority service and better deliverability rather than the free tier claiming the same pool
2026-09-18 22:09:01 -07:00
Matthew Meszaros
ee46cb49e8
feat: route new Gmail and Google Workspace mailboxes through a guided three-step app-password connect over smtp.gmail.com and imap.gmail.com instead of Google sign-in, behind BOX_GOOGLE_OAUTH_CONNECT (off by default) and announced to clients as gmail_oauth_connect on /auth/config, refusing a new gmail OAuth start with 403 mailbox_gmail_oauth_disabled in both the direct and Warmbly Cloud broker paths while leaving mailboxes already connected that way sending, syncing and re-authorizable
2026-09-18 22:06:09 -07:00
Matthew Meszaros
e562e09354
Merge pull request #593 from warmbly/fix/mailbox-disconnect-workspace-scope
...
Scope mailbox disconnect to the workspace and surface the API's reason
2026-09-19 04:15:40 +00:00
Matthew Meszaros
4b2b641f92
feat: pass the workspace id to the mailbox delete in the database-backed removal and erasure tests, which compiled with the owner's id but would answer not found now that Delete is scoped to the organization, and rename the cloud link stub's parameter to say what it carries
2026-09-19 06:10:32 +02:00
Matthew Meszaros
f99ee57484
feat: scope mailbox disconnect to the workspace instead of the connecting member, so a teammate with manage_emails no longer gets 404 on a mailbox the list shows them, delete by id in the repository on the strength of that check while the worker removal still names the owner the consumer's unibox cleanup is keyed on, and read the API's own reason off the normalised AppError in the accounts page so a refused disconnect says why instead of "The mailbox couldn't be disconnected" on every failure
2026-09-19 06:01:03 +02:00
Matthew Meszaros
b31c5d521b
Merge pull request #591 from warmbly/fix/reply-attribution-and-human-opens
...
Count thread replies from any address as replied, and count only a person's opens
v0.4.25
2026-09-18 12:56:39 +00:00
Matthew Meszaros
ffe3159256
feat: order the repair sweep's fake inbox by id so the cursor assertion is deterministic like the query it stands in for
2026-09-18 14:51:18 +02:00
Matthew Meszaros
bd092dcf04
Merge remote-tracking branch 'origin/main' into fix/reply-attribution-and-human-opens
...
# Conflicts:
# internal/app/consumer/event_new_email.go
2026-09-18 14:44:41 +02:00
Matthew Meszaros
6aebfe7e63
feat: store IMAP-synced addresses as Name <addr> like the Gmail and Graph syncs instead of Name (addr), teach mailhdr.Bare, the reply path's sender and recipient checks and the warmup sender fallback to read the old form for existing rows and older workers, so a reply into an IONOS or any other IMAP mailbox is attributed to its lead again after the address checks added on 16 September refused every one of them, and add a consumer sweep that re-offers unclaimed inbound mail answering a campaign send or coming from a contact to reply processing at boot and daily so the replies missed that week are attributed without anyone touching the database
2026-09-18 14:37:35 +02:00