Matthew Meszaros and Devin AI
9d0f43780b
feat: provision onboarding-complete reviewer workspaces with expiring Test access, bounded credits and Test header labels
...
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-05 16:15:56 +00:00
Matthew Meszaros
0731a8c788
feat: refuse an HTML page as an API response in the dashboard client (api_url_not_api) so a missing or wrong API_URL falls back to the unreachable login state instead of crashing, and serve config.js with Cache-Control no-store from the dashboard and admin Pages _headers to match the nginx images
2026-10-05 17:04:05 +02:00
Matthew Meszaros
b2bde4ed92
Merge pull request #840 from warmbly/devin/1791198671-admin-health-notices
...
feat: correct admin setup and health notices and add safe invitation cleanup
2026-10-05 12:35:00 +00:00
Matthew Meszaros and Devin AI
5ae09e0e15
feat: separate fleet mailbox targets from measured CPU and RAM, report node public egress IPv4 and add workload share analytics
...
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-05 11:24:32 +00:00
Matthew Meszaros and Devin AI
ded4e5f700
feat: correct split-host admin health checks and registration notices, distinguish informational context from problems, and add audited expired-invitation cleanup
...
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-05 11:17:13 +00:00
Matthew Meszaros
1de33d9f41
feat: guard configuration tab links against losing unsaved edits, keep the login captcha mounted for resend, confirm warmup appeal decisions by mailbox, show header tabs only on section pages, show the update pill in the mobile drawer, make admin sign-in alerts opt-in per channel, check the admin bit before loading the account, and alert on admin access only when it changes
2026-10-05 03:21:44 -07:00
Matthew Meszaros
8910b02198
feat: redesign the admin panel in a black and white dark-first theme with grouped sidebar sections, header tabs, a collapsible animated sidebar and a rebuilt sign-in, alert operators on admin sign-ins and admin access changes through opsnotify, and carry first-touch attribution from the marketing site to every dashboard link
2026-10-05 03:01:22 -07:00
Matthew Meszaros
f092b71a30
feat: answer a spent confirmation budget with reauth_limited and say so in the dashboard and admin dialogs, keep an open confirmation dialog from timing out under the person, and stop the OAuth app webhook secret reveal from re-prompting after a cancel
2026-10-04 05:25:32 -07:00
Matthew Meszaros
df0949a019
feat: mask invite and next URL parameters in dashboard and admin analytics, clear a copied invite link when the invitation is sent again, and read hex.info's newest stable release without consuming the gate's package list
2026-10-04 05:22:40 -07:00
Matthew Meszaros
3c45c3764c
feat: mask token, session, agent_session and code URL parameters in admin panel analytics the same way the dashboard does
2026-10-04 03:38:02 -07:00
Matthew Meszaros
f9a2e9af10
feat: state dependency floors, the Sentry HTTP client choice and auth cache budgets as the guarantees they hold, with no advisory identifiers or past behaviour in comments
2026-10-04 03:00:56 -07:00
Matthew Meszaros
32da32a0a8
feat: mask every revealed secret in session replay by tagging API key, client and signing secrets, inbound webhook URLs, join commands, tester passwords, pairing codes and the TOTP QR, block inputs holding credentials, mask token, session and code URL parameters in dashboard analytics, give the admin panel the same masking with console recording off, and update the privacy page to match
2026-10-04 02:57:17 -07:00
Matthew Meszaros
db4fc7b115
feat: require a recent confirmation for 2FA enrollment (a fresh sign-in for accounts with no password or factor), pool link approval, workspace export and import, member invites and role changes, webhook and OAuth app secret reveal and rotation, and the admin fleet join token, admin grant and workspace archive routes, with a confirm-it-is-you dialog and retry in the admin panel
2026-10-04 02:56:18 -07:00
Matthew Meszaros
9f7d45a1fb
feat: charge every password, emailed-code and TOTP attempt atomically before comparing it (Redis INCR+expire script) with a per-account TOTP budget across challenges, put the signed-in password change on the reauth budget, set the per-account login limit to 50 per hour, give tester passwords an expiry (users.password_expires_at, migration 000257) and clear them plus every session on revoke, mint warmblyctl reset links with the password-reset purpose, expire fleet join tokens (7 days default, 30 max, reusable inside the window), derive captcha from the resolved Turnstile secret, refuse weak bootstrap argon2id hashes, make registration codes single-use, rate-limit the v1 invitation lookup, and draw RIDs and user codes without modulo bias
2026-10-04 02:52:22 -07:00
Matthew Meszaros
d505508997
feat: audit OAuth app moderation and developer blocks under their own entity types, refuse logo removal on suspended apps, delete a replaced workspace-uploaded app logo once no other app shows it, confirm before revoking every token in the admin panel, open store cards on Space, retry a new logo URL after a failed one, toast only after the clipboard write succeeds, and freeze the listing form baseline while it is open
2026-10-04 01:20:28 -07:00
Matthew Meszaros
7555f641a5
feat: turn Integrations into an app store with sidebar views, search, sorting and filters, list community apps by link until featured or widely installed, redesign the OAuth app registration dialog, store app logos re-encoded per app like the workspace logo, and add admin suspension, token revocation and developer blocks for OAuth apps
2026-10-04 00:31:52 -07:00
Matthew Meszaros
4957214431
feat: redesign the Integrations page with search, category chips, recommended and popularity-ranked integrations, add a community app directory where OAuth apps are published unverified by link and verified in a new admin review queue, with docs and OpenAPI
2026-10-03 09:24:34 -07:00
Matthew Meszaros
e79551867f
feat: have a worker learn from its own dials when its network blocks outbound 465, dial 587 at once there, tell a mailbox whose server only takes 465 that the block is on the sending side instead of blaming its server, report the block on every heartbeat as the node's last error, rename the admin Workers filter to Has node error, and document the outbound ports a worker needs
2026-10-02 08:02:36 +02:00
Matthew Meszaros
d99a09825f
feat: run one inbox placement test across many sending mailboxes as a placement batch (issue #736 ): server-side sender scopes (a campaign's senders or the whole workspace, filtered by provider, domain, tag and untested days) and sampling (random, percent stratified by provider or domain, per domain, per provider) snapshotted at creation, a runner that starts senders under per-workspace and instance-wide concurrency and a start rate with defer or skip for unavailable mailboxes, aggregate placement by sending domain, sending provider and recipient provider, fleet coverage, cancel, credits agreed per batch, org transfer, operator settings in the admin panel, dashboard pages and dialog, CLI commands, agent tools, OpenAPI and docs
2026-09-29 10:19:46 -07:00
Matthew Meszaros
4924d2c88d
feat: let a placement test target chosen seed inboxes or providers, add a quick pace that sends copies seconds apart, charge credits with explicit consent for tests past the monthly free allowance with automatic refunds for tests that deliver nothing, and add a Seeds picker to the compose window
2026-09-27 21:16:12 -07:00
Matthew Meszaros
ea5dd435d7
feat: revive only whole RFC3339 timestamps (never custom field values or text that starts with a date), keep equal revived Dates across React Query refetches so unchanged data keeps its identity, type every revived response timestamp in the dashboard models as Date, reset the launch dialog only when a different campaign opens, show the build on the page error panel, and tag Cloudflare Pages dashboard and admin builds with their commit as the release
2026-09-27 14:59:06 +02:00
Matthew Meszaros
caf1852217
feat: keep placement seeds out of warmup pools as recipients too, store a probe's Message-ID before the send, hold queued probes against the sender's day and size a test to what is left, claim due monitors so one replica runs each, write comparison halves in one transaction, scan each seed's mail once per tick, keep test history when a mailbox is deleted, default to 20 seeds a minute apart, and render cloud-panel tests without a real lead by default
2026-09-25 21:46:09 -07:00
Matthew Meszaros
d4467ce10e
feat: add the admin Seed panel page to manage the instance placement seed inboxes, run operator tests and read every workspace's results, plus the placement allowance and pacing settings on the Configuration page
2026-09-25 20:56:11 -07:00
Matthew Meszaros
9426c0da51
feat: validate every person, workspace and company name through internal/pkg/displayname on each write path (profile, onboarding, setup, IdP sign-in, org create and rename, org import, enterprise inquiry, admin testers, warmblyctl) with a 400 invalid_name code, render stored names in platform email through the same rules, mirror them in the web forms, check the org slug format, and document the rules in error-codes, security and AGENTS.md
2026-09-21 03:34:03 -07:00
Matthew Meszaros
f11df9268f
Merge pull request #640 from warmbly/fix/admin-list-pagination
...
feat: make every admin panel list page past the first and filter by id, and report failed admin requests
2026-09-21 09:29:48 +00:00
Matthew Meszaros
4dde9708c9
feat: honour an ascending created_at sort on the admin users list with a matching id tiebreak, and record an admin API failure whose call omitted the method as GET, the method axios sent
2026-09-21 02:24:36 -07:00
Matthew Meszaros
cc244e5159
feat: make every admin panel list page past the first and filter by id: bind query-string ids through models.ParamUUID since gin cannot set a uuid.UUID, page the explorers and secondary lists by an opaque offset cursor with an id tiebreak instead of an id keyset that disagreed with the sort, page the audit log on (created_at, id) with an inclusive YYYY-MM-DD end day and read next_cursor on its page, cast every before-date bound to timestamptz, coalesce nullable audit ip and user agent, and report failed admin queries and 5xx mutations to PostHog or Sentry with method, path, status, code and request id
2026-09-21 02:11:38 -07:00
Matthew Meszaros
0a5e7947b4
feat: return a failed warmup retention delete from the worker so the bus redelivers it up to five times, re-key a Graph message in the map on every move so the sender copy's body can be dropped, never expunge a whole IMAP folder for one message (UID EXPUNGE, else MOVE to Trash, else refuse), build the two retention indexes concurrently in their own migrations 000193 and 000194, keep the dashboard stepper off 1 and 2 days, and describe retention as applying wherever the placement files warmup mail
2026-09-21 01:11:22 -07:00
Matthew Meszaros
1513419a2a
feat: delete warmup mail from each mailbox once past a per-mailbox retention window (email_accounts.warmup_retention_days, else retention.warmup_mail_days, default 30) via a consumer sweep that retires the receipt and sender copy and a worker delete action that trashes on Gmail, deletes on Graph, expunges on IMAP and drops the stored body, prune per-message warmup records after retention.warmup_event_days, and count a warmup deletion as tampering only within 24 hours of arrival and never for a retired message, judging Gmail's Trash label on the same rule
2026-09-21 00:52:02 -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
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
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
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
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
d6025ea4c0
feat: address worker capacity review findings with safe migrations and recovery reporting
2026-09-17 06:24:14 -07:00
Matthew Meszaros
bab9f86727
feat: correct worker capacity, mailbox distribution, observed IPv4, fleet pagination, and premium pool promotion
2026-09-17 04:15:05 -07:00
Matthew Meszaros
de8da6396e
feat: build the tester sign-in address from DASHBOARD_URL instead of rewriting the admin origin's first label to dev., which handed an OAuth reviewer a different deployment than the dashboard every other link in the panel points at
2026-09-16 19:40:14 +02:00
Matthew Meszaros
03f813dd43
feat: let an admin create a tester account that joins an existing workspace with an explicitly chosen role instead of always minting an empty one, so an OAuth reviewer signing in lands in a workspace that shows the app doing real work
2026-09-16 19:37:32 +02:00
Matthew Meszaros
0334d2c64a
feat: prevent ResizeObserver feedback warnings from reaching PostHog and scope worker outage alerts per workspace on shared cloud workers
2026-09-16 17:42:38 +02:00
Matthew Meszaros
140c7de436
feat: add the admin panel's Promo codes page and route the six /admin/discounts endpoints that existed as handlers but were never wired, so a launch offer is built in the operator UI instead of an INSERT against production, with caps that an explicit null can actually clear on PATCH
2026-09-16 04:04:09 -07:00
Matthew Meszaros
ae012dd13f
Clear the live error-tracking issues, and the workspace rename that renamed the wrong workspace ( #533 )
...
* feat: stop a managed Kafka cluster refusing topic creation from failing the publish, by treating a topic- or cluster-authorization failure from CreateTopics as a topic the cluster owns rather than one that is missing, which on Confluent Cloud dropped every warmup event and filed one issue per message because the topic never became known
* feat: drop a report whose error is a cancelled context in errs rather than at ninety call sites, so a browser navigating away or a container draining on deploy stops filing one issue per query that happened to be in flight, while a deadline this process set and blew through still reports
* feat: stop renaming one workspace from renaming another, by keying the workspace settings editor on the workspace id so a switch re-seeds the name field instead of leaving the previous workspace's name against the new workspace's autosave baseline, and pinning every save on the workspace, sending and tracking pages to the workspace its draft was hydrated from
* feat: drop Script error. and the ResizeObserver notice on the marketing site and the hosted form page the way the dashboard and admin panel already do, since those two carry no stack and no bug and between them were the largest issues in error tracking, all of it from warmbly.com
* feat: rename the forms Turnstile script module to turnstileScript.ts so it no longer differs only in case from the Turnstile.tsx component, which resolved both imports to one file on a case-insensitive filesystem and failed forms' typecheck with TS1149
* feat: upload source maps from the static build:pages build as well as the image build, so the dashboards served from a static host stop reporting every stack frame as a minified name beside 'Invalid source map: bad json', which is PostHog falling back to fetching the .map from a host that answers with its SPA fallback
* feat: build every admin list in pg_admin.go with make rather than declaring it nil, so an empty page serializes as [] instead of null, and guard the audit table's own empty check, which is what crashed admin.warmbly.com/audit with 'null is not an object (evaluating d.data.length)' whenever a filter matched nothing
* feat: match the whole broker description rather than a substring when deciding a topic create was refused for permissions, since that answer remembers the topic as present, and clear the cached promise and dead tag when the forms Turnstile script fails to load so a blocked first attempt no longer leaves every later mount with the same rejection and the captcha permanently missing
2026-09-15 09:05:53 -07:00
Matthew Meszaros
179af5815f
feat: type the four AdminUserPreview slices as nullable in the admin panel's model so a backend older than the empty-slice fix in pg_admin.go cannot crash a page through an unguarded email_accounts.length again
2026-09-15 13:39:05 +02:00
Matthew Meszaros
0a1ed6f04e
feat: resolve scanner ASNs from a GeoLite2-ASN database so the catalogue's asn: entries match without a Cloudflare transform rule, ship the Proofpoint, Mimecast and Cisco ASNs enabled behind a new probable certainty that widens the consumer's machine window instead of deciding the verdict, make the tracking event dedupe claim one coalesced operation, and report an ASN database that opened cleanly but resolves nothing ( #440 )
2026-09-15 01:48:45 -07:00
Matthew Meszaros
92e298b6ec
fix: clear every open issue in error tracking by fixing the bugs behind them rather than the reports: a document-level mouseleave handing RippleProvider the document itself, whose classList is undefined; the admin panel posting /getaway without the /v1 its baseURL omits, so its realtime socket 404d on every page; Gmail throttles classified from the 403 status alone and told to re-authorize instead of back off; consumer flag and folder events retrying forever on a message the unibox never stored; a lost token-refresh race answered 500 instead of the documented 401; a nil email_accounts slice crashing the admin user page; Turnstile mounted with an empty sitekey; conditional passkey autofill run after the user navigated away; a boot log filed as an issue; and one publish failure per message on a topic the broker refuses ( #519 )
2026-09-14 21:06:14 -07:00
Matthew Meszaros
d74d5e6836
fix: retire the warmup spam score, a counter that grew with volume rather than misbehaviour and that no band could act on ( #508 )
...
* fix: retire the warmup spam score, a ratchet that grew with volume rather than misbehaviour and that no band ever read, dropping the column from the pool row and the reputation ledger and explaining a pool finding with the band's own reason instead (#491 )
* test: pin the advisor snapshot's pool columns against the scan, since the band's reason now reaches the finding through that select alone (#491 )
* fix: hold a warmup sentence's score and reason with the sentence itself, keep the retired spam_score key on the published analytics payload as a deprecated zero, seed the sandbox with severity-shaped scores, and record the raw spam report when the warmup service is absent (#491 )
2026-09-14 07:44:34 -07:00
Matthew Meszaros
7300b3b021
feat: full PostHog coverage: identify the signed-in user and workspace in the dashboard and admin panel with autocapture, heatmaps, dead and rage clicks, web vitals, network timing, console capture and session replay masking only password fields, send server-side signup, trial and subscription events under the user id with the organization as a group, keep the marketing site and form pages cookieless while capturing everything stateless plus a form funnel, upload the form app's source maps, and add WARMBLY_POSTHOG_SESSION_REPLAY
2026-09-13 20:58:22 -07:00
Matthew Meszaros
1dc4aedc3c
fix: retire the warmup invalid-token band with its table, metric query, service and repository methods and admin tab, since nothing has fed it since #481 and no attributable forged-token signal exists; key the live pool fixtures on the canonical pool ids so the warmup, repository routing and tasks routing suites run on a fresh database, and correct every doc, site and advisor line that still described the retired signal or a spam-score threshold nothing implements ( #490 )
2026-09-13 08:09:01 -07:00
Matthew Meszaros
8799680166
fix: never charge a mailbox for a warmup token that arrived in its inbox, hold a quarantine or block for its full term against fresh metrics, and keep a penalised address's standing across removal, pool exit and export through a trigger-maintained mirror, since the recipient never controlled the token, the bands read seven days against 30-day terms, and the pool row died on paths a snapshot at deletion never saw ( #481 )
2026-09-13 04:34:44 -07:00
Matthew Meszaros
43dcbde06c
feat: tester accounts, creatable from the admin panel ( #483 )
...
* feat: excuse one named account from the emailed login code, so a vendor reviewer who cannot read this instance's mail can sign in without turning codes off for everyone, with the reason recorded beside it and every run of warmblyctl status naming the accounts that hold one
* feat: create and manage tester accounts from the admin panel, so letting a reviewer in is a form rather than a shell, with the password shown once and every live exemption listed on one page because forgetting one is the way this goes wrong
* fix: give tester management its own permission bit rather than borrowing ban_users, create the account and its exemption in one transaction so no invisible orphan survives a failure, require an accountable operator on the CLI grant, stop a halted row scan reading as the whole exempt list, and show a failed query as an error instead of as no testers
* chore: re-run CI after the aggregator tripped on a cancelled job from the branch update, with every underlying job green
* chore: retrigger CI, the previous run sat queued indefinitely while other branches ran
* feat: roll back a half-created tester when its workspace step fails and backfill the manage-testers bit onto admins already holding every other permission, so the address is not left taken by an unusable account and the new routes are not 403 for the existing admin
* feat: make the 000151 manage-testers backfill one-way, because clearing bit 22 on the way down would also revoke it from an admin granted it explicitly afterwards and the up migration would not restore that
2026-09-13 03:07:10 -07:00
Matthew Meszaros
7f74664c72
fix: a granted plan unlocks nothing, and Turnstile never renders ( #474 )
...
* fix: let a granted plan unlock the dashboard, since the client decided paid from the Stripe status a managed subscription never touches, and replace the Turnstile size Cloudflare removed so the widget renders and can issue a token at all
* feat: tell people on a preview deployment that it is a public beta, once in a dialog and thereafter as a header pill they can reopen, driven by a config value rather than a hostname so one image stays reusable, and bind both Turnstile modals through onLoad because the component is not forwardRef and execution=execute never fires without the widget instance
* fix: keep the beta pill outside the desktop-only header group so the notice stays reopenable on a phone, and say in the docs that the value is baked into config.js at container start rather than read per load
2026-09-12 21:45:05 -07:00