Commit Graph
1032 Commits
Author SHA1 Message Date
Matthew Meszaros ea8d15374e Merge branch 'main' into feature/editor-image-links-and-buttons 2026-09-11 22:56:16 -07:00
Matthew Meszaros 88b483d227 Merge branch 'main' into fix/issue-432 2026-09-11 22:47:54 -07:00
Matthew Meszaros 7d79dcc282 feat: append a -kafka image variant to every version the control plane hands a fleet node when the instance runs Kafka, so a joining worker pulls a build that can actually reach the bus instead of failing at boot (#449) 2026-09-11 22:46:02 -07:00
Matthew Meszaros f41eac289d Merge branch 'main' into fix/issue-432 2026-09-11 22:35:43 -07:00
Matthew Meszaros a3aec0a9cb Merge branch 'main' into feature/editor-image-links-and-buttons 2026-09-11 22:27:11 -07:00
Matthew Meszaros e3092f2322 feat: address the review by releasing the topic lock before the broker call so one slow creation cannot stall every publish, subscribe and close for the full admin timeout, refusing to open an admin connection once the bus is closed so a publish racing past the closed check cannot resurrect a client nothing will shut, building rather than vetting the tagged Kafka backend in CI because vet does not link and a CGO backend fails at link time, and correcting the Confluent tier wording to say auto topic creation is configurable only on Dedicated 2026-09-12 06:54:34 +02:00
Matthew Meszaros 069ab15194 feat: address the second review pass on the Edit with AI fix by reading a markdown destination with balanced parentheses so a link the model normalises out of the angle-bracket form it was given comes back whole instead of truncated at the first paren with a stray one left in the copy, restoring only spaces and tabs around the model's answer so a selection that ran to the start of the next paragraph joins the two the way a paste would rather than gaining a blank paragraph nobody typed, and capping the completion at a flat 4096 tokens, above the 3072 it was and below the smallest completion limit in common use, because a request over a backend's own cap earns a 400 naming max_tokens that openAIProvider.adaptParams latches for the life of the process and degrades every later call 2026-09-11 21:21:40 -07:00
Matthew Meszaros 6504d9958a feat: create Kafka topics from the bus that uses them, because a worker's command topic is named after the node id issued at join time so the set is not knowable in advance, and the broker's auto-creation is off by default on Confluent Cloud and not configurable below Standard, which left a worker subscribed to a topic that did not exist receiving nothing and reporting no error, and compile the tagged Kafka build in CI so a backend nothing else builds cannot rot unnoticed 2026-09-12 06:02:49 +02:00
Matthew Meszaros 704e793c8a Merge branch 'main' into feature/editor-image-links-and-buttons 2026-09-11 20:57:20 -07:00
Matthew Meszaros 131e9ff093 feat: give the JetStream stream a size ceiling from NATS_MAX_BYTES, accepting a byte count or a size like 2GiB, because a managed account can require every stream to declare one and Synadia's Max Bytes Required rejects creation without it, turning that refusal into an error naming the variable to set, and fix the retry path which passed a zero max age and would have recreated the stream with no age limit after a failure 2026-09-12 05:40:43 +02:00
Matthew Meszaros f1f5249153 feat: authenticate to NATS with a user JWT and nkey seed so a managed bus like Synadia Cloud can replace a self-run one, taking the credential from a file path for containers and from a single-line base64 value for the fleet, because a node receives environment variables rather than files and the env file docker reads cannot express the multi-line credentials format, in both the Go event bus and the Rust tracking publisher 2026-09-12 05:29:09 +02:00
Matthew Meszaros 1bdd1da800 feat: address the CodeRabbit review on the Edit with AI fix by leaving the caret after text written at a collapsed position instead of in front of it (an insertion maps to itself unless the position associates rightwards, so continuing to type went before the insert), splitting the model's blocks one separator at a time so a blank paragraph the author used as spacing survives a rewrite instead of being swallowed by a greedy newline run, carrying a link destination that holds a paren or a space through in markdown's angle-bracket form rather than dropping the link, putting the author's boundary whitespace back on the model's trimmed answer in both hosts so a selection ending on a space does not glue the rewrite to the next word and "did anything change?" compares exactly what was written, and sizing the completion cap from the passage's own rune count so an 8000-rune CJK body is not truncated by a cap chosen for English 2026-09-11 20:23:53 -07:00
Matthew Meszaros 6501cb599c feat: fix the "Edit with AI" rewrite in the campaign body and the unibox composer for issue #432 by running /generation/edit on a new generation.BuildEditRules system prompt through AIProvider.Complete instead of the cold-outreach writer prompt that redefined the model's role, capped it at 80 words and imposed a five-part email skeleton on every instruction, raising the completion cap so a full-body rewrite is no longer truncated at 1024 tokens and counting the request limits in runes rather than bytes, carrying merge variables, AI blocks, conditionals, form links and link destinations through the round trip in web/src/components/app/ai/richTextPassage.ts instead of deleting every atom node via doc.textBetween, replacing the passage with paste semantics so a phrase rewritten inside a sentence stops splitting its paragraph into three, saying "No change" when the model hands the passage back untouched, and clamping the floating AI card to the surface it is editing so it no longer draws outside the step drawer over the flow canvas 2026-09-11 20:04:32 -07:00
Matthew Meszaros 3ee636e2e6 Merge branch 'main' into feature/editor-image-links-and-buttons 2026-09-11 20:01:18 -07:00
Matthew Meszaros 7ff9f4d2c6 feat: let a campaign body image carry a link and add a call-to-action button to the editor toolbar, both rendered as mail-safe markup (an anchor-wrapped img, a one-cell table whose cell holds the colour and padding for Outlook's Word engine), with the plain-text half now keeping every link destination 2026-09-11 20:01:16 -07:00
Matthew Meszaros 470654f5b0 feat: say machine_clicks counts the contacts whose only clicks on a step were automated rather than counting steps, document the zero-send rule on all four step rates in the OpenAPI schema, and stop get_campaign_stats dropping the machine open and click counts from both the campaign totals and each step 2026-09-11 09:12:22 -07:00
Matthew Meszaros 35d9d3d612 feat: count automated clicks from one rolled-up bool_and(machine) per step and contact joined into both the campaign summary and the per-step stats, instead of a correlated EXISTS pair per progress row, which measured 78ms against 33ms on a 50k-lead campaign with 20k logged clicks 2026-09-11 09:01:17 -07:00
Matthew Meszaros 5087023e48 feat: give every campaign step its own open, click, reply and bounce rate in Step performance, computed against that step's own sends, with the automated share of its opens and clicks carried alongside them through GetSequenceStats, the campaign analytics API, the get_campaign_stats AI tool and the docs 2026-09-11 08:56:03 -07:00
Matthew Meszaros a5b0e2c2f3 Merge branch 'main' into feat/cleanmylist-verification 2026-09-11 06:12:10 -07:00
Matthew Meszaros a8c66591ce feat: correct the isInstant comment that claimed a backwards-skewed clock must not mark events human when the code does exactly that, describing the real behaviour instead: an event stamped before its dispatch means the clocks disagree, so the timing rule abstains and leaves the verdict to the user agent and source network 2026-09-11 06:04:38 -07:00
Matthew Meszaros 9698052569 Merge branch 'main' into feat/cleanmylist-verification 2026-09-11 06:03:55 -07:00
Matthew Meszaros 27c5df5072 feat: refuse a redirect that downgrades a verification request from https to http in both provider clients, since Go keeps the Authorization header across a redirect that stays on the same host and the pasted API key would go on the wire in the clear, and label the verification action from the connection id rather than the active provider, because a degraded connection reports the built-in checker while still being a connection to manage 2026-09-11 05:26:33 -07:00
Matthew Meszaros 6c6a0d1909 feat: record a verification provider's failure before marking its connection and serialize both health writes behind a per-connection gate, since the report is a database round trip and a check resolving alongside it compared itself against a failure that had not been cached yet, withdrawing a degraded state raised by a check newer than its own and leaving the connection healthy while the account was empty 2026-09-11 04:24:17 -07:00
Matthew Meszaros 2219d764cf feat: stop the tracking window live tests from resetting the instance settings row they run against, snapshotting the real document and restoring it verbatim instead of writing defaults back, and assert the untouched click window against that snapshot rather than against the shipped default, which silently required the database to start at defaults 2026-09-11 04:15:19 -07:00
Matthew Meszaros 0e8a05b6df Merge remote-tracking branch 'origin/main' into fix/scanner-timing-window 2026-09-11 04:02:06 -07:00
Matthew Meszaros da4b89da0b feat: split a unibox message's provider placement into its own provider_folder column (migration 000146) so Archive and Delete in the thread header survive the next sync without the sync losing the ability to follow a real provider move, and narrow PATCH /unibox/folder to inbox/archive/trash behind the unibox feature gate with an audit entry so the move reaches every teammate's list live 2026-09-11 03:23:19 -07:00
Matthew Meszaros 623dc7ec61 feat: rewind the cooldown deadline as well as the observation time in the exhausted-account test so it fails when the fifteen-minute hold regresses to the ordinary one-minute lookup cache rather than only when the cache stops being deadline-keyed, and ask again next to the write whether a verifier is already connected, since validating the pasted key is a round trip to the provider and is long enough for a second connect to pass the first check 2026-09-11 03:12:28 -07:00
Matthew Meszaros 80c3c79a31 feat: add live coverage that the machine windows survive the settings document's jsonb round trip and reach the classifier, a guard that every shipped scanner CIDR is written as its own network address since the loader truncates host bits silently, and correct the comments that claimed an edit lands on the very next event when the consumer reads through a thirty second cache in its own process 2026-09-11 03:11:35 -07:00
SUMAN JANA 727ddb1482 feat: wire the unibox thread header's Mark as unread, Archive and Delete to a new PATCH /unibox/folder, add an Add as contact action for senders outside the CRM, and replace six private From-header parsers with one shared lib/helper/emailAddress that also understands the parenthesised form the IMAP sync stores, which left the reply composer's seeded To failing its own validator 2026-09-11 03:10:18 -07:00
SUMAN JANA 73f6bff2ed feat: stop a browser signed in as someone else from being offered Accept on an invite it cannot accept, comparing the signed-in address with the invited one on the invite page and offering Switch account instead, and naming both addresses in the backend's 403 so the cause is visible 2026-09-11 03:10:18 -07:00
Matthew Meszaros 4d0f0fb6b6 feat: hold an exhausted verification account that publishes no balance for a cooldown instead of re-deriving its health from an account check that cannot see exhaustion, since CleanMyList answers GET /v1/jobs identically whether or not there is allowance left, so the minute-long lookup cache retired every observed 402 and put the whole next batch back on doomed paid calls while Settings reported the service as healthy, and refuse a second verification connection while one is connected rather than letting creation order silently move every check onto a different bill 2026-09-11 02:57:08 -07:00
Matthew Meszaros 184a3dc08e feat: make the automated-open and automated-click windows operator-editable under Instance settings and raise their defaults to 60s and 30s, because the ten-second window was anchored on dispatch to the worker rather than on delivery and routinely expired before the recipient-side gateway it was meant to catch had even seen the message, and add Barracuda's published Email Gateway Defense blocks to the scanner catalogue with Proofpoint, Mimecast and Cisco shipped commented out because browser isolation renders a clicked page from the vendor's own network 2026-09-11 02:53:34 -07:00
Matthew Meszaros 1866c45c67 feat: serve a PostHog reverse proxy at /ingest on the backend so the dashboard, admin panel and marketing site can report analytics and errors through this instance instead of posthog.com, which content blockers drop for a large share of visitors, splitting asset traffic to the bundle host because sending it to the ingestion host 404s, withholding the caller's cookies and Authorization from a third party, and preserving the trailing slash that path cleaning removes and PostHog's capture endpoint needs 2026-09-11 06:02:21 +02:00
Matthew Meszaros eb21d978a8 feat: stop aws-bootstrap from treating a bucket that exists in another region as done, since head-bucket answers globally and a second region silently kept its blobs in the first, stop it printing the database master password to stdout where a terminal, a CI log or an agent transcript keeps it forever, and add an instance check that reports a tracking domain sharing a registered domain with the product's own URLs 2026-09-11 05:24:57 +02:00
Chris Edington 59122e6c8a feat: add CleanMyList contact verification with API key setup and built-in fallback 2026-09-10 20:06:29 +01:00
Matthew Meszaros a84ab48729 Merge branch 'main' into feature/posthog-error-tracking 2026-09-10 10:25:21 -07:00
Matthew Meszaros 79127c345d feat: drop a nil error and an empty message at the errs boundary instead of turning them into an issue with nothing in it, which the Sentry SDK used to swallow on its own and the PostHog one would have captured as a titleless exception 2026-09-10 19:15:21 +02:00
Matthew Meszaros ced741e352 feat: make PostHog the default error tracker across every runtime while keeping Sentry fully supported alongside or instead of it, by turning internal/observability/errs into a two-sink fan-out with a local-log fallback, adding $exception capture to the Go services, the Rust tracking service, the Elixir realtime service and the dashboard, admin and form apps, reporting gin panics with their route, request id, workspace and user, attaching that identity plus a route and failed-request trail to browser exceptions, and wiring POSTHOG_ERROR_TRACKING, the node join env, compose, source-map upload and the docs to match 2026-09-10 19:11:32 +02:00
Matthew Meszaros 4b93e849a1 feat: drop the occurrence struct left behind in the round-robin span emitter, which the map of per-term span lists replaced before it was ever used and which golangci-lint's unused check does not flag for an unreferenced type 2026-09-10 10:07:18 -07:00
Matthew Meszaros 77dfefcf88 feat: give every occurrence of a repeated trigger term its own span rather than only the first, since pointing at one 'free' out of three sends the writer back to hunt for the other two on the next re-check, and emit the spans round by round so every term shows once in every half before any shows twice, because the list is capped for display and a word written twenty times would otherwise fill it and hide the other terms that are also wrong 2026-09-10 10:01:57 -07:00
Matthew Meszaros d51de7db3a feat: address the CodeRabbit review by quoting a fragment in the copy's own casing rather than the model's retyping of it, extracting the case-fold offset map into internal/pkg/casefold so the AI half gets the same Unicode safety the rules half has, giving a trigger term a span in each half it appears in instead of losing the second one to deduplication, scanning subject links before body anchors so the display cap cannot drop the subject's own, requiring WRITE_TEMPLATES on the credit-spending analyze route so a read-only key cannot spend the workspace balance, refusing to tell a customer their credits came back when the refund is what failed, and no longer letting a stale analysis retire the newer rules request that was about to replace it 2026-09-10 09:50:28 -07:00
Matthew Meszaros e7b9491975 feat: drop an AI finding's category when the model returns one outside the closed set the API documents, so a client validating the response against that enum is never handed something outside it, and correct the parse comment that still described an unreadable response as falling back to the rules pass when Analyze now refuses it and refunds 2026-09-10 09:28:00 -07:00
Matthew Meszaros 427c9ce27c feat: pin the invariant the trigger-span offset map rests on, that foldIndex folds byte-for-byte identically to strings.ToLower and lands every recorded offset on a rune boundary, across Turkish dotted I, the Kelvin sign, ligatures, titlecase runes and invalid UTF-8 where a bad byte becomes a three-byte replacement rune 2026-09-10 09:28:00 -07:00
Matthew Meszaros f468f44e1d feat: let a content-check issue's field carry the location instead of repeating it in the message, so the launch dialog and campaign feed stop reading 'Body: 3 spam-trigger term(s) found in subject/body', and say 'Subject and body' for an issue whose fragments straddle both halves rather than dropping the location entirely, with the editor labelling each quoted word on such an issue 2026-09-10 09:28:00 -07:00
Matthew Meszaros ade18d1650 feat: leave an AI finding's field empty when the model labelled neither half and nothing in the finding could be anchored in the copy, instead of defaulting it to the body and rendering a badge that sends the writer to the wrong box on the one panel whose whole purpose is saying which box to open 2026-09-10 09:28:00 -07:00
Matthew Meszaros 3a9b1747dc feat: map a trigger term's offset back through the case fold before slicing the copy, so a rune that changes byte length when lowercased (U+0130, U+212A) no longer shifts every following span into bytes the writer never typed or cuts one in half into invalid UTF-8, read an issue's field from the whole span list before the display cap trims it so a subject-first list of more than eight can no longer relabel a both-halves issue, and refuse an AI response carrying a verdict with no score and no findings instead of pricing its empty finding list into a confident 100 out of 100 above a verdict saying the opposite 2026-09-10 09:28:00 -07:00
Matthew Meszaros 331db196d8 feat: locate every content-check issue in the subject or the body with the exact fragments that caused it and a one-line fix, add POST /templates/analyze running the configured LLM over a campaign template for located spam findings quoted verbatim from the copy plus a rewritten subject and an overall score, verify every model quote against the draft so an invented sentence is dropped rather than shown, pin the analysis temperature so re-checking unchanged copy returns the same number, and give the editor panel a Re-check button that re-runs both passes and reports the movement since the last check 2026-09-10 09:28:00 -07:00
Matthew Meszaros 2998f8a8c6 Merge remote-tracking branch 'origin/main' into feat/worker-capacity-soft-target 2026-09-10 06:26:47 -07:00
Matthew Meszaros fa2b5330d7 feat: drop the auth-pressure placement term because worker_capacity_view aggregates auth_errors (per-mailbox credential failures) and not rate_limit_errors (the 454/421 per-IP throttles it claimed to measure), measure projected utilization against an age-free Capacity.Target so a freshly joined node can relieve a full fleet instead of scoring as 200% loaded after one mailbox, bound the isolated-egress override with an explicit OverTarget check now that Eligible no longer caps it, and cap rotation moves per destination since a tick scores every mailbox against one frozen materialized-view snapshot 2026-09-10 05:51:17 -07:00
Matthew Meszaros 7fa4fdfbc4 feat: make worker capacity a placement target rather than a hard gate, so Eligible refuses only on health and an over-target worker costs enough score to lose to anything with room instead of returning nil and dropping assignment into selectFallback, score projected utilization including the incoming mailbox's own weight, and penalise the 454/421 auth pressure the capacity view already collected and threw away 2026-09-10 05:38:17 -07:00