Commit Graph
11 Commits
Author SHA1 Message Date
Matthew Meszaros f0846eb034 feat: stop a freshly connected mailbox being silently excluded from every campaign send, by making an unset mailbox timezone representable as the empty string the campaign scheduler already checks for, since email_accounts.timezone defaulted to 'UTC' while campaigns.timezone defaults to 'Europe/London' and nothing in the OAuth or SMTP onboarding paths ever set either, so a brand new mailbox looked deliberately placed in UTC, was compared against the differing campaign zone and dropped by the hardcoded 8am-8pm business-hours gate whenever the current UTC hour fell outside it, emptying the candidate pool and failing the campaign start, adding a migration that changes the column default and converts existing 'UTC' rows because until now no API field, dashboard control or onboarding path could set that column at all so every such row is the old default rather than a choice, adding the missing Timezone field to UpdateEmail with IANA validation so the setting the sending-behaviour UI already tells people to change is finally reachable and an unloadable zone is rejected instead of being silently coerced to UTC by the scheduler, and replacing the misleading 'no active email accounts found for campaign's email tags' response for a pool that exists but is entirely gated out with a distinct message naming the real cause, via an ErrNoEligibleMailbox that wraps ErrNoEmailAccounts so the three callers that pause a campaign on it are unaffected (#126) (#125) 2026-08-16 07:54:45 +02:00
Matthew Meszaros 3922333930 feat: run the tracking service on nats by default, kafka behind a cargo feature 2026-07-20 09:56:29 +02:00
Matthew Meszaros cc52878966 fix: apply cargo fmt to the tracking service (line wrapping in abuse.rs, config.rs, links.rs) so the Rust CI format check passes 2026-06-12 17:45:32 +02:00
Matthew Meszaros 8732805934 feat: replace signed click redirects with server-side link tickets (tracked_links store, internal resolver API, opaque /c/<id> URLs, layered anti-probe caches with miss budget and circuit breaker) removing TRACKING_LINK_SECRET entirely 2026-06-11 09:30:21 +02:00
Matthew Meszaros 2c5e8b2cbd feat: make TRACKING_LINK_SECRET a required boot-time secret on backend and tracking service with no unsigned mode and no rotation grace, so rotating the key revokes old links immediately 2026-06-11 09:00:04 +02:00
Matthew Meszaros 515efce991 feat: support TRACKING_LINK_SECRET_PREVIOUS rotation grace on the tracking service so rotating the click-signing key never breaks links in already-delivered emails 2026-06-11 08:53:29 +02:00
Matthew Meszaros 8b9277dabf feat: harden tracking service against abuse with per-IP rate limiting, prefetch/scanner filtering, URL length caps, and HMAC-signed click redirects (TRACKING_LINK_SECRET) closing the open-redirect hole 2026-06-11 08:11:05 +02:00
Matthew Meszaros d57febd1e3 ci: relax golangci-lint to real-bug rules, silence dead-code in tracking
Go:
- Drop errcheck, unparam, prealloc, gosec, exportloopref from the
  enabled set. The legacy codebase has thousands of unchecked
  `tx.Rollback()` calls (idiomatic — Rollback after Commit is a
  no-op), prealloc suggestions the author chose not to follow, and
  gosec rules that don't apply to our control-plane code.
  Real-bug linters (govet, staticcheck, ineffassign, gosimple,
  unused, bodyclose, noctx, sqlclosecheck, typecheck) stay enabled.

Rust:
- Add #[allow(dead_code)] to `Config::from_aws` — legacy
  AWS-only loader kept as fallback while we migrate fully to the
  unified loader. Clippy's `-D warnings` was failing the build on
  the unused warning.
2026-05-23 16:44:00 +00:00
Matthew Meszaros c12fd93def Add local Sentry logging 2026-02-14 05:49:49 +01:00
Máté Mészáros (Laptop) 7ed5719c15 Config & Deploy 2026-01-29 08:50:38 +01:00
Máté Mészáros (Laptop) 41624a6f79 Analytics & Tracking 2026-01-29 05:59:04 +01:00