Matthew Meszaros
|
103fa00b55
|
feat: state in the configuration reference and the troubleshooting guide that a hosted form page takes its error-reporting environment from the forms service's APP_ENV, stamped into the page, rather than from WARMBLY_SENTRY_ENVIRONMENT like the dashboard and the admin panel do
|
2026-09-07 05:19:24 -07:00 |
|
Matthew Meszaros
|
1239f1d191
|
Merge main into the Sentry branch, routing the new smtp reporting through the errs wrapper instead of the SDK import main added
|
2026-09-07 05:00:43 -07:00 |
|
Matthew Meszaros
|
f043bfc761
|
feat: address the CodeRabbit review on the Sentry PR by escaping every runtime-config value the web and admin entrypoints write into a JavaScript string literal so a quote or newline in a DSN cannot inject or discard the whole config, reporting only the count and types of a failed query's parameters instead of their values now that the db scope actually applies, cloning the fallback hub in errs.Hub so scope cannot leak between requests, flushing the tracking service before every fatal exit since process::exit skips the guard's drop, treating a blank WARMBLY_RELEASE or APP_ENV as unset in realtime, stamping the environment and a service tag into the forms page, and correcting the docs claim that an unset DSN means the SDK is never initialised
|
2026-09-07 04:47:51 -07:00 |
|
Matthew Meszaros
|
4582896f54
|
merge
|
2026-09-07 04:43:45 -07:00 |
|
Matthew Meszaros
|
cebcd2cc83
|
merge
|
2026-09-07 04:37:07 -07:00 |
|
Matthew Meszaros
|
6bfba363d3
|
feat: address the CodeRabbit review on the SMTP compatibility PR by carrying the server's own refusal in a rejected-recipient error so an address that no longer exists is distinguishable from one a policy blocked, classifying our own refusal to authenticate over an unencrypted link as the configuration problem it is rather than retrying it four times as an outage against a server that is answering fine, and fixing the fake server's canned refusal at construction so the session goroutine and the test no longer race on it under go test -race
|
2026-09-07 04:30:04 -07:00 |
|
Matthew Meszaros
|
be16f77f5d
|
Merge main into the Sentry branch
|
2026-09-07 04:25:41 -07:00 |
|
Matthew Meszaros
|
9c63cbe0b6
|
Merge branch 'main' into fix/web-sentry-dsn-runtime-config
|
2026-09-07 04:25:16 -07:00 |
|
Matthew Meszaros
|
1af5ac1ea6
|
feat: let a fixed mailbox problem stop showing as a permanent error (issues #362, #363): resolve a mailbox's connection errors on the first sync pass that reaches the server again, because nothing but a credential reconnect ever resolved an error row, so a five-minute outage left a red needs-attention on the mailbox for good and held its health at warning; carry what the folder listing had to skip as sync state shown in the drawer's Sync card instead of raising an error row nobody can withdraw, so the note disappears once the mailbox is back under the folder limit or the duplicate folder id is renamed; and keep only a fingerprint per message in the IMAP flag scan rather than the whole flag set and Message-ID, which held 74 MB per mailbox at the window and folder limits against 14 MB for the digests, on a worker whose base capacity is 16 mailboxes
|
2026-09-07 04:24:09 -07:00 |
|
Matthew Meszaros
|
211650af8d
|
feat: send through every kind of SMTP server (issues #359-#361): negotiate the sign-in method from what the server advertises, preferring CRAM-MD5 then LOGIN then PLAIN, because sending AUTH PLAIN blind was refused by every server that offers only LOGIN, which is Microsoft 365 relays and most appliance relays, and that refusal was reported to the mailbox's owner as a wrong password and deactivated the account; put a deadline on the whole SMTP conversation so a peer that stops answering without closing the connection can no longer park a send goroutine forever, which only the dial was protected against; classify a refusal by its reply code so a permanent 5xx on the sender, the recipient or the message is reported as the rejection it is and not retried four times as though the server were offline, while a 4xx still retries; announce the sender's own domain in EHLO rather than net/smtp's localhost, which relays read as a spam signal; and share one AUTH LOGIN implementation with the notification mailer instead of keeping two copies of the code that handles credentials
|
2026-09-07 04:19:42 -07:00 |
|
Matthew Meszaros
|
b32a28778c
|
Merge pull request #355 from warmbly/feat/agent-tools-forms-segments-suppressions
feat: expose forms, segments and the suppression list to agents
|
2026-09-07 04:06:57 -07:00 |
|
Matthew Meszaros
|
51dedc90ee
|
feat: put every runtime behind one optional error-reporting story: a single internal/observability/errs wrapper that is now the only package importing sentry-go, InitSentry for cmd/forms, release and environment tags on every service from the existing build stamp, optional Sentry in the admin panel and the public forms app, the sentry crate in the Rust tracking service, release tagging in realtime, CI source-map upload that only runs when a Sentry token is configured, and docs covering the DSN for each service
|
2026-09-07 03:51:06 -07:00 |
|
Matthew Meszaros
|
63d6637d0c
|
feat: expose forms, segments and the suppression list to agents by adding twenty-three tools to the shared registry, so an MCP client, a Hermes-style REST agent, the dashboard assistant and warmblyctl can all build an audience, publish a lead-capture form, link one to a campaign and manage who is unreachable, each gated on the same contact and campaign permissions its HTTP route already uses
|
2026-09-07 03:39:42 -07:00 |
|
Matthew Meszaros
|
20c18bc2f7
|
feat: read the dashboard's Sentry DSN from the container-injected runtime config instead of a literal DSN in web/src/main.tsx, so a self-hosted install reports its users' browser errors, URLs and IPs nowhere unless the operator sets WARMBLY_SENTRY_DSN, and document the variable in configuration.mdx and the no-reporting-by-default stance in data-control.mdx
|
2026-09-07 03:36:27 -07:00 |
|
Matthew Meszaros
|
90f5e8c625
|
feat: follow only one folder per UIDVALIDITY on IMAP, because the folder row is keyed on that id while RFC 3501 only promises UIDs are stable within a folder, so a server that derives it from the creation time gives a folder tree made in one second a single shared id and the two folders would advance each other's cursor and delete each other's row; the inbox and special folders win the collision, the dropped folder is reported in the mailbox drawer and named in the worker log, and the folder classification, ranking and localized-name matching gain direct tests
|
2026-09-07 03:20:46 -07:00 |
|
Matthew Meszaros
|
1a87720d5a
|
merge
|
2026-09-07 03:14:42 -07:00 |
|
Matthew Meszaros
|
f2c35cf872
|
feat: sync every kind of IMAP mailbox (issues #345-#349): connect servers without CONDSTORE by following UIDNEXT per folder and mirroring read state with a periodic flag scan, so Outlook.com, Microsoft 365 over IMAP and Yahoo work instead of failing at load; fall back to a STATUS per folder when the server has no LIST-STATUS, which silently made an account look empty; bound the wait between IMAP responses so a peer that vanishes without a FIN cannot park a command forever; keep the inbox and special folders when a mailbox has more folders than the cap (raised to 100) and relay the overflow as a warning instead of failing the mailbox silently; recognize localized folder names and the server's own hierarchy delimiter so a Sent folder called Gesendete Elemente is not filed as inbox; and back off on a widening interval while a mail server is unreachable so one outage is one warning rather than one a minute
|
2026-09-07 03:12:22 -07:00 |
|
Matthew Meszaros
|
6f0284fc2b
|
feat: state in the campaigns API reference that the start-and-wait behaviour applies to a campaign that has at least one lead and nothing left to send, so API clients can tell it apart from the no_leads refusal for a campaign that never had a lead
|
2026-09-07 03:00:10 -07:00 |
|
Matthew Meszaros
|
889b96c38e
|
feat: address the CodeRabbit review on the campaign restart PR by turning on Keep running for a form's campaign only after every field is validated and failing the form save on any error other than a foreign campaign, running the automation's campaign flip before the automation is saved and failing the save visibly when the campaign is not the workspace's or the flip does not land, and clarifying in the error-code table and the campaigns API reference that no_leads covers a campaign that never had a lead while one whose leads all finished starts and waits
|
2026-09-07 02:55:12 -07:00 |
|
Matthew Meszaros
|
5d60fe9a21
|
feat: fix campaign restart dead end (issue #340): resolve preflight tracking senders through the same explicit/tags/all pool the scheduler uses so a connected mailbox is never reported missing, fetch the launch dialog's step count from the steps endpoint instead of a field the campaign API never returns, turn on Keep running for new leads when a form or an automation feeds a campaign (migration 000131 backfills existing ones) and when a member starts a campaign whose every lead has finished so it goes active and waits for leads instead of answering 400, return waiting_for_leads from the start endpoint for the dialog's success screen, and document the no_leads and no_remaining_leads codes and the new behaviour in the campaigns, forms, automations and API docs
|
2026-09-07 02:26:50 -07:00 |
|
Matthew Meszaros
|
54b5cba9a5
|
feat: address the CodeRabbit review on the continuous campaigns PR by clearing idle_since in the same update that turns the continuous setting off so the dashboard stops reading a campaign as waiting for leads, adding idle_since to the documented campaign response, qualifying the start endpoint's nothing-left-to-send 400 for continuous campaigns, and noting in the automations and forms guides that a finished campaign restarts through the launch checks and a refusal is written to its activity log
|
2026-09-06 02:58:33 -07:00 |
|
Matthew Meszaros
|
7b11489c85
|
feat: keep a campaign running for new leads (issue #336): add a continuous campaign setting (migration 000130, on by default once a segment is linked) under which a campaign that runs out of leads stays active and idle with idle_since set instead of finishing, is startable with no leads, is re-checked by the reconciler every pass and shows as waiting for leads in the dashboard list, header and live activity panel with a CAMPAIGN_IDLE realtime event; make WakeCampaigns restart a finished campaign through the full launch checks so a lead added by the contacts API, a bulk update, an import or the add-to-campaign automation action reopens it exactly like a linked segment does, and write a refused restart to the campaign activity log once an hour per reason instead of only the backend log; expose continuous on the campaign API and preferences page and document it in the campaigns, segments, forms, automations, API reference and realtime docs
|
2026-09-06 02:50:16 -07:00 |
|
Matthew Meszaros
|
04a2ed59c9
|
feat: address the CodeRabbit review on the lead-intake PR by giving the webhook sink its own copy of every map payload so the automation goroutine never writes into the map still being marshalled for endpoint delivery, propagating contact lookup errors in the upsert action's skip mode and in the native actions adapter so a failed lookup is never mistaken for a missing contact, adding the contacts source CHECK as NOT VALID in migration 000129 to skip the table scan under the migration lock, defaulting a new create-or-update-contact node's email template to the address key the chosen trigger actually carries, correcting the n8n guide on which lead-form sources have a trigger node, naming API batches over 100 contacts among the silent bulk arrivals in the contacts guide, and updating the marketing automations page from nine to twelve triggers
|
2026-09-06 00:47:33 -07:00 |
|
Matthew Meszaros
|
a3989f9d9c
|
feat: turn automations into a lead-intake path so a Facebook, Instagram, LinkedIn or TikTok lead form pushed by Zapier, Make, n8n or any webhook becomes a tagged, campaign-enrolled contact without leaving Warmbly: add the warmbly.upsert_contact and warmbly.add_to_campaign built-in actions with templated field mapping, custom fields, tags, campaign and an if-exists policy, fire a rich contact.created event from the one contact write path (silent for file imports, sheet syncs and API batches over 100) and expose contact.created and form.submitted as automation triggers with condition fields, variables and sample data, carry an automation depth through events raised by an action so a flow that creates a contact cannot re-trigger itself past five hops, stamp automation-created contacts with the new automation source (migration 000129), share the campaign picker between the sheet sync wizard and the automation builder, document lead intake in the automations, Zapier, Make, contacts, forms, integrations, expressions and webhook pages plus a new n8n guide, mirror the new triggers and actions on the marketing automations page, and drop the 34 MB cli binary that was committed by mistake
|
2026-09-06 00:36:05 -07:00 |
|
Matthew Meszaros
|
3bf8d4bdfa
|
Merge remote-tracking branch 'origin/main' into feature/mailbox-fair-use-allowance
|
2026-09-04 21:25:53 -07:00 |
|
Matthew Meszaros
|
bf46839fb7
|
feat: address the CodeRabbit review on the mailbox allowance work by reserving the mailbox slot inside the account insert transaction under a per-organization lock so concurrent connects cannot both take the last one, resolving the storage limit under the quota lock so a plan change cannot be raced past, deleting refused attachment objects on a context that outlives the request, settling already-connected rows before the bulk batch spends allowance, leaving password columns out of the failed-rows CSV, stopping click propagation from the portalled allowance dialog, and counting bulk progress once
|
2026-09-04 21:11:25 -07:00 |
|
Matthew Meszaros
|
b35e111705
|
fix: address the review on the CLI PR: give the sign-in handshake its own per-IP budget so a 200-poll login cannot lock the address out of the browser login, keep https for a remote host that names a port instead of sending a bearer token in cleartext, report truncation when a paginated walk stops at max-pages, accept a piped secret with no trailing newline, normalise WEBSOCKET_URL on its suffix so a bare /socket becomes a real endpoint, destroy a minted secret the moment its code expires, gate cli-installer-ci on the required status check, print a rejected flag instead of an unbound-variable error, and use a portable sha256 so the packaging runs on macOS
|
2026-09-04 21:03:58 -07:00 |
|
Matthew Meszaros
|
3596a9770f
|
feat: make mailboxes truly unlimited under a fair-use allowance of one mailbox per daily send the plan includes (15,000 on Business), drop the 200 hard cap and the 5-per-day connect throttle, open a request-more dialog with inline limit requests and plan upgrade when the allowance is reached, add bulk CSV mailbox import with live progress and a downloadable failed-rows file, reserve attachment storage atomically under a per-org lock so concurrent uploads cannot pass the quota (#326), report storage and the allowance on the billing usage meters, and honor approved daily-send overrides in the sender
|
2026-09-04 21:00:26 -07:00 |
|
Matthew Meszaros
|
f68918d7f6
|
Merge remote-tracking branch 'origin/main' into feature/warmbly-cli
|
2026-09-04 20:14:46 -07:00 |
|
Matthew Meszaros
|
23f88293c8
|
feat: document the warmbly CLI at docs.warmbly.com/api/cli with every install channel, the device flow in api/authentication, the new auth/cli and api-keys/self routes in the endpoint scope map, a warmbly-cli agent skill, and a note on warmblyctl saying which of the two CLIs a reader wants
|
2026-09-04 20:14:43 -07:00 |
|
Matthew Meszaros
|
5fd9aedb80
|
Merge remote-tracking branch 'origin/main' into feature/plan-upgrade-paywall-modal
|
2026-09-04 09:11:51 -07:00 |
|
Matthew Meszaros
|
e5360713e7
|
Merge remote-tracking branch 'origin/main' into feature/install-script-setup-wizard
|
2026-09-04 06:43:12 -07:00 |
|
Matthew Meszaros
|
5c4f87c1aa
|
feat: list the campaign's unscoped attachments under a Sent with every step group in the step composer, so files the step really carries stop being invisible in the panel that claims to show them, and say in the confirm that removing one takes it off every step
|
2026-09-04 06:40:48 -07:00 |
|
Matthew Meszaros
|
b0db8cc02b
|
feat: chain the backup bundle cleanup behind a successful docker compose cp so a failed copy cannot delete the only backup, and tell a pinned image install to set WARMBLY_TAG before pulling by hand
|
2026-09-04 06:35:04 -07:00 |
|
Matthew Meszaros
|
af9e852314
|
Merge branch 'main' into fix/step-attachments-mount
|
2026-09-04 06:34:53 -07:00 |
|
Matthew Meszaros
|
9a2184fda7
|
Merge remote-tracking branch 'origin/main' into fix/step-scoped-attachments
|
2026-09-04 06:28:26 -07:00 |
|
Matthew Meszaros
|
04689a8bfc
|
feat: mark step_id required on the CampaignAttachment schema, since the attachment response always carries the key and serialises a campaign-wide file's as null, so a generated client that treats it as optional loses the difference between an unscoped file and one it forgot to read
|
2026-09-04 06:28:26 -07:00 |
|
Matthew Meszaros
|
77058a2cb4
|
feat: address the review on the installer branch by keeping the database password out of pg_dump's argv, excluding backup bundles from the blob root they are written into, tolerating blobs that change or vanish mid-archive, making the instance-settings bootstrap a single atomic insert, and validating the release tag before it is written into .env
|
2026-09-04 06:24:05 -07:00 |
|
Matthew Meszaros
|
85f3dad215
|
feat: send the files a step actually carries by honouring campaign_attachments.sequence_id in the send, test-send and preview paths instead of attaching every campaign file to every step, count them per step in the preflight content score, and refuse an upload naming another campaign's step
|
2026-09-04 06:16:16 -07:00 |
|
Matthew Meszaros
|
81d6ba4520
|
Merge remote-tracking branch 'origin/main' into feature/plan-upgrade-paywall-modal
|
2026-09-04 06:09:14 -07:00 |
|
Matthew Meszaros
|
7314e85dfe
|
Merge branch 'main' into fix/create-schedule-windows
|
2026-09-04 06:08:05 -07:00 |
|
Matthew Meszaros
|
a0c9d5a5b0
|
feat: add operator notification channels an admin configures in the panel (Discord, Slack, HMAC-signed webhook, or email) with per-channel event subscriptions, a synchronous test probe, SSRF-guarded URLs and credentials redacted on read, wire nine instance events including the enterprise inquiry that previously wrote a row nobody was told about, and reword the plan-specific limits copy so it reads correctly without billing
|
2026-09-04 06:02:40 -07:00 |
|
Matthew Meszaros
|
d68bbcd2ab
|
feat: add a one-command self-host installer at warmbly.com/install.sh with an interactive data-control wizard, give docker-compose.yml image keys and per-store volume variables, add an image-mode updater, move engagement/form/audit retention into instance settings, and add warmblyctl backup/restore
|
2026-09-04 05:49:54 -07:00 |
|
Matthew Meszaros
|
87ada2c99f
|
feat: drop the purple gradient and indigo plan accents for the app's own slate and sky palette (Business wears sky, Enterprise solid ink, no gradients anywhere), highlight the best-value plan instead of whatever sits one rung up, remove the duplicated capability matrix from Overview and the comparison table from Plans, and stop calling dedicated workers 'dedicated IPs' across the dashboard, docs, pricing page, FAQ and agencies page
|
2026-09-04 05:11:47 -07:00 |
|
Matthew Meszaros
|
01dd6e3450
|
feat: rebuild Billing > Plans on the same large plan cards the upgrade dialog uses (extracted to a shared component with rolling prices, interval sheen and a highlighted next-step-up plan), add a side-by-side comparison table of every limit and capability sourced from the server plan records with the current plan column highlighted, and show the proration preview per card
|
2026-09-04 05:03:28 -07:00 |
|
Matthew Meszaros
|
19f8dfbc20
|
feat: rebuild Billing > Overview as a real control panel with cancel and resume, live usage meters against server-enforced limits, a capability matrix, trial and past-due and pending-cancellation banners; price plan switches with a proration preview on the Plans tab; fix the cancel client that sent no body and always 400'd; stop the Payment tab claiming no card is on file
|
2026-09-04 04:48:59 -07:00 |
|
Matthew Meszaros
|
7fe7b7c8e9
|
feat: scope the collaboration guide's offline claim to the data that is actually refetched, since live events are never replayed and presence and cursors resume from current state rather than backfilling what was missed
|
2026-09-04 04:07:44 -07:00 |
|
Matthew Meszaros
|
1533b83c16
|
feat: open a full-screen upgrade dialog from every plan lock (sidebar rows, the unified inbox frosted overlay, the free-workspace screen) with the four plan cards, a monthly/annual toggle with animated prices, the unlocking plan highlighted, promo codes and one-click Stripe checkout or in-place plan change through a shared useUpgradeFlow hook that the billing page now uses too, return the Stripe redirect to the originating page and settle it in place, and add a plans and billing guide
|
2026-09-04 04:03:44 -07:00 |
|
Matthew Meszaros
|
ebc6de1f81
|
feat: refetch the campaigns list on a slow cycle while the realtime socket is not connected, so send counts kept current by live invalidation cannot sit on their five-minute cache with no event coming to refresh them, and document what the header's connection dot means and what still refreshes while it is down
|
2026-09-04 04:03:01 -07:00 |
|
Skylinerffm97
|
16d4a13810
|
feat: mount StepAttachments under the step composer in SequenceView for email steps so per-step attachments can be seen, uploaded and removed from the dashboard, and describe per-step attachments in the sequences guide (issue #307 item 3)
|
2026-09-04 12:59:19 +02:00 |
|