Matthew Meszaros
|
853afe458e
|
Merge pull request #430 from warmbly/fix/bootstrap-and-tracking-domain-check
fix: two aws-bootstrap defects, and a check for tracking on your own brand
|
2026-09-10 20:29:46 -07:00 |
|
Matthew Meszaros
|
947ba4f2d0
|
Merge pull request #429 from warmbly/fix/rds-tls-verification
fix: sslmode=verify-full against RDS could never have worked
|
2026-09-10 20:29:35 -07:00 |
|
Matthew Meszaros
|
62903b3806
|
Merge pull request #428 from warmbly/fix/tracking-rustls-provider
fix: the tracking service panics on its first TLS connection
|
2026-09-10 20:29:23 -07: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 |
|
Matthew Meszaros
|
a962683511
|
feat: ship AWS's RDS truststore in the backend and consumer images and point the docs at it, because Amazon RDS chains to a root that is in no public trust store so the sslmode=verify-full those docs recommended failed every connection with x509 certificate signed by unknown authority, while deliberately not setting PGSSLROOTCERT by default since an RDS-only store would break a Postgres fronted by a public CA
|
2026-09-11 05:23:23 +02:00 |
|
Matthew Meszaros
|
e7f25890d2
|
feat: install the ring crypto provider at tracking startup so the service can open a TLS connection at all, because rustls 0.23 refuses to choose when both aws-lc-rs and ring are in the tree and panics at the first handshake, which took the whole service down the moment it pointed at a tls:// bus and which plaintext local development never reveals
|
2026-09-11 05:19:52 +02:00 |
|
Matthew Meszaros
|
1260dff108
|
Merge pull request #426 from warmbly/feature/posthog-error-tracking
feat: PostHog error tracking across every runtime, Sentry kept as an option
v0.4.4
|
2026-09-10 10:28:28 -07:00 |
|
Matthew Meszaros
|
a84ab48729
|
Merge branch 'main' into feature/posthog-error-tracking
|
2026-09-10 10:25:21 -07:00 |
|
Matthew Meszaros
|
3bd9d2a1d7
|
Merge pull request #424 from warmbly/feature/issue-421-implementation
feat: locate every spam-check issue in the subject or body, and analyze campaign copy with AI
|
2026-09-10 10:18:10 -07:00 |
|
Matthew Meszaros
|
84a0ca0b29
|
feat: correct the noteStep guidance comment to match what the callers actually pass, a bounded route pattern rather than a fixed phrase, so the rule a future caller reads is the rule the trail is built on
|
2026-09-10 19:16:13 +02: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
|
2ff350ecf9
|
feat: apply WARMBLY_POSTHOG_ERROR_TRACKING to the public form pages too, by having cmd/forms stamp an empty browser key when it is false, since the page can only act on whether a key arrived and the flag otherwise silenced the dashboard and the admin panel while leaving form pages reporting
|
2026-09-10 19:14:34 +02:00 |
|
Matthew Meszaros
|
f8625b085a
|
Merge remote-tracking branch 'origin/main' into feature/issue-421-implementation
|
2026-09-10 10:12:04 -07: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
|
abe9800d5b
|
Merge pull request #425 from warmbly/fix/dockerfile-cache-mount-ids
fix: name every BuildKit cache mount so the images build on hosted builders
|
2026-09-10 10:09:33 -07: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
|
512451c8d6
|
feat: give every BuildKit cache mount an explicit id so the Dockerfiles build on hosted builders that reject an unnamed one, which is what stopped the backend, consumer, worker, forms, cli, updater and tracking images from building on Railway with 'flag --mount=type=cache is missing an id argument'
|
2026-09-10 19:05:01 +02: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
|
5411b1033c
|
feat: say in the analyze endpoint reference that a finding's category is absent when the model named something outside the documented set, matching the enum the response is now held to
|
2026-09-10 09:29:35 -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
|
9f2ddc218c
|
feat: correct the content-check guide to describe the badge the editor actually renders, which names both halves when the wording straddles them rather than carrying a line number the rules pass never puts there
|
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
|
b8e31433a5
|
Merge pull request #423 from warmbly/feat/frontends-on-pages
feat: serve the dashboard and admin panel from a static host
|
2026-09-10 09:07:46 -07:00 |
|
Matthew Meszaros
|
bbe9d9055a
|
feat: let web and admin be served from a static host by teaching each app's own entrypoint to render config.js wherever WARMBLY_CONFIG_OUT points, so one definition of the runtime key set serves both the container that renders it at start and a build:pages script that renders it into dist, ship a _redirects in each so a deep link stops 404ing without nginx try_files, and add scripts/check-pages-build.sh to make lint because a malformed config.js reads fine in a diff and leaves the app blank at runtime
|
2026-09-10 18:03:00 +02:00 |
|
Matthew Meszaros
|
368b2f1bef
|
Merge pull request #422 from warmbly/fix/split-cloud-bus-bundle
fix: the split-deployment bus bundle could not start, and nothing would have caught it
|
2026-09-10 08:45:17 -07:00 |
|
Matthew Meszaros
|
a08ada6666
|
feat: address the review on the bus bundle by downloading the compose file and config the documented one-command install never fetched, resolving container names through compose so --install-dir stops inspecting containers that do not exist, renewing a certificate that is present but expired instead of starting a stack that refuses every connection, refusing to write an empty credential when openssl fails, and falling back to dig or host where getent does not consult DNS
|
2026-09-10 17:39:58 +02:00 |
|
Matthew Meszaros
|
5ef8b608c6
|
feat: record the split-cloud scripts and aws-bootstrap.sh as executable, which a checkout on a filesystem that does not preserve the mode had silently dropped so make lint died with Permission denied in CI only, and assert the recorded git mode in check-split-cloud so it cannot ship non-executable again
|
2026-09-10 17:30:16 +02:00 |
|
Matthew Meszaros
|
9e689e6d91
|
feat: fix the three defects that stopped the split-deployment bus bundle from starting at all (NATS given store_dir twice on the command line and in nats.conf, which it refuses rather than reconciling; Redis unable to read its own private key because the image's entrypoint drops from root with gosu and discards the added group; and a healthcheck on localhost when the monitor binds IPv4 loopback, leaving the service unhealthy while serving fine), add bus/setup.sh so standing the box up is one idempotent command that verifies with real clients before printing the control plane's URLs, and add scripts/check-split-cloud.sh to make lint so a bundle that cannot start fails CI
|
2026-09-10 17:22:14 +02:00 |
|
Matthew Meszaros
|
a3edc3b0be
|
Merge pull request #419 from warmbly/fix/issue-415-contact-panel-rebase
Fix: re-subscribing a contact no longer pops a discard prompt
|
2026-09-10 06:57:25 -07:00 |
|
Matthew Meszaros
|
378e1d15ee
|
feat: build the custom-field record from entries so a contact field named __proto__ is a real key instead of silently setting the prototype and dropping out of what gets saved, and count a row the user has typed a value into but not named as unsaved work, so leaving the panel on it asks rather than discarding it while Save stays disabled because there is nothing to send
|
2026-09-10 06:54:58 -07:00 |
|
Matthew Meszaros
|
6a6d7fa74b
|
Merge branch 'main' into fix/issue-415-contact-panel-rebase
|
2026-09-10 06:50:02 -07:00 |
|
Matthew Meszaros
|
a04d5d98e4
|
Merge pull request #420 from warmbly/feat/worker-capacity-soft-target
Worker capacity is a placement target, not a hard gate
|
2026-09-10 06:31:24 -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
|
cd051c7150
|
Merge branch 'main' into fix/issue-415-contact-panel-rebase
|
2026-09-10 05:42:35 -07:00 |
|
Matthew Meszaros
|
e82a249792
|
Merge pull request #418 from warmbly/feat/issue-414-delete-api-key
Add a permanent delete for revoked API keys
|
2026-09-10 05:42:17 -07:00 |
|
Matthew Meszaros
|
f9d9967389
|
Merge branch 'main' into fix/issue-415-contact-panel-rebase
|
2026-09-10 05:38:58 -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 |
|
Matthew Meszaros
|
6149f84c7d
|
feat: give warmblyctl the same apikey purge the customer CLI has, so the operator half of the API surface can delete a revoked key too and the two CLIs name the verb the same way
|
2026-09-10 05:37:28 -07:00 |
|
Matthew Meszaros
|
396bab0e06
|
Merge branch 'main' into feat/issue-414-delete-api-key
|
2026-09-10 05:36:06 -07:00 |
|
Matthew Meszaros
|
c1a3d52015
|
feat: address the review of the contact panel rebase, comparing custom-field rows structurally so adopting a server change no longer deletes a row the user has typed a value into but not yet named, comparing records key by key instead of as JSON so re-entering a field in a different order stops leaving the panel permanently unsaved, and comparing id lists sorted so a repeated id cannot pass for a different one
|
2026-09-10 05:33:26 -07:00 |
|
Matthew Meszaros
|
ca1cd6c7af
|
Merge pull request #417 from warmbly/feat/split-cloud-hosting
feat: split deployment across a container host, machines you own, and a cloud region
|
2026-09-10 05:26:36 -07:00 |
|
Matthew Meszaros
|
1e1231f3b1
|
feat: address the review of the API key delete, putting the permanent-delete route in the published OpenAPI contract with its 409, keeping one auto margin in the drawer footer so the Delete button lands on the right, and deciding the dashboard's status pill, its footer and the key-count strip on whether the key can still authenticate rather than on a status column that never says expired
|
2026-09-10 05:23:56 -07:00 |
|
Matthew Meszaros
|
64dfaa8c60
|
Merge remote-tracking branch 'origin/main' into feat/split-cloud-hosting
|
2026-09-10 14:20:22 +02:00 |
|
Matthew Meszaros
|
510ee692ba
|
feat: address the review on the split-deployment branch by moving the two broker routes onto their own NODE_BROKER_TOKEN so the internet-facing tracking and forms services no longer hold a credential that can open any organization's data key, refusing to presign any key outside the prefixes a node reaches, fixing IAM policies that named an alias ARN KMS never resolves in a Resource element, bounding both brokered HTTP clients because the sync loop's context never expires, no longer reporting a 403 from the object store as a missing body, and redacting the DSN and URL credentials the dry-run listing printed in clear
|
2026-09-10 14:19:53 +02:00 |
|