* feat: add REDIS_KEY_PREFIX env var for Redis ACL namespace isolation
Adds optional REDIS_KEY_PREFIX env var that prefixes all Redis keys
(BullMQ queues via `prefix` option, cache/lock/rate-limit keys via
`redisKey()` helper). When unset, behavior is unchanged (BullMQ
defaults to "bull:", cache keys are unprefixed).
This enables self-hosters using Redis ACL multi-tenancy to restrict
useSend to its own key namespace (e.g. `~usesend:*`).
16 files changed across env schema, Redis module, 9 BullMQ queue/worker
files, and 5 direct Redis key operation sites.
* docs: add REDIS_KEY_PREFIX to self-host assets and fix docker run example
Add REDIS_KEY_PREFIX env var to docker/prod/compose.yml, .env.example,
.env.selfhost.example, and self-hosting docs. Fix missing trailing
backslashes in standalone docker run example.
* fix(redis): disable ioredis ready check and BullMQ version check
Redis ACL blocks INFO command (in @dangerous category). ioredis uses
INFO for ready check, BullMQ uses it for version detection. Without
these flags, BullMQ workers fail to initialize and silently stop
processing jobs.
- Add enableReadyCheck: false to ioredis connection
- Add skipVersionCheck: true to all 5 Queue + 5 Worker constructors
* fix(redis): add skipVersionCheck to remaining BullMQ job queues
Add skipVersionCheck: true to Queue and Worker constructors in all 4 job
files (campaign-scheduler, cleanup-email-bodies, usage-job,
webhook-cleanup) to match the pattern already used in service files.
This prevents BullMQ version mismatch errors when using REDIS_KEY_PREFIX
with Redis ACL namespace isolation.
* feat: add customizable contact double opt-in flow
* test: add double opt-in service coverage
* fix: address review comments for double opt-in PR
- Make pending status conditional on doubleOptInEnabled flag
- Backfill legacy unsubscribeReason for reliable pending detection
- Add doubleOptInContent to contact book listing select
- Fix duplicate toast on DOI editor subject save failure
- Harden searchParams parsing against string[] values
- Make default DOI template use link mark for clickable URL
- Make public API create+update atomic via transaction
- Prevent contact upsert failure when DOI email send fails
- Fix empty string template variable replacement
Co-authored-by: opencode <opencode@anthropic.com>
* fix: harden double opt-in confirmation safeguards
Preserve explicit unsubscribe intent in DOI flows and prevent confirmation links from re-subscribing opted-out contacts. Also sanitize subscribe-page error messaging and use timing-safe hash comparison for link verification.
* ui stuff
* fix: require doubleOptInUrl in double opt-in templates
* feat: add configurable from address for double opt-in emails
* feat: add resend confirmation flow for pending contacts
* fix: move subscribe confirmation to explicit POST flow
* test: add contact book public API endpoint coverage
* docs: add double opt-in documentation and update OpenAPI spec
Add a user guide for the double opt-in feature covering setup, contact
statuses, email customization, template variables, and best practices.
Update the OpenAPI spec to include doubleOptIn fields in all contactBook
request/response schemas.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: opencode <opencode@anthropic.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: prevent premature webhook auto-disable and allow re-enable
Use persisted failure counters when deciding auto-disable status and restore dashboard re-enable flow so webhooks are not deactivated unexpectedly after reset.
* fix: count webhook failures per failed call
Only increment consecutive failure counters after a call exhausts retries, while keeping the 30-call auto-disable threshold and stale-state protection.
* fix(docs): correct webhook SDK package name (#363)
* test: isolate webhook unit suite from mailer deps
Mock limit service in webhook unit tests so Vitest does not resolve team-service and mailer paths requiring usesend-js during CI.
* Correct API reference in Go package documentation
Updated description to reference the useSend API instead of Unsend API.
* Update documentation to reflect useSend branding
Added a issue to the package maintainer.
If maintainer isn't actively maintaining the package. Will fork it.
* fix(docs): remove community section and update Go SDK documentation
- Remove community section until content is ready.
- Update Go SDK docs to useSend implementation.
* Added transaction to creating SES setting & upgraded Prisma to Prisma ORM 6
* Keep logging of the queue status in
---------
Co-authored-by: Kumarion <121711454+Kumarion@users.noreply.github.com>