* feat: support standard AWS env vars and default credential chain
Replace non-standard AWS_ACCESS_KEY / AWS_SECRET_KEY with the AWS-standard
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY. The old names are kept as
fallbacks in the runtimeEnv for backward compatibility.
Both vars are now optional. When omitted, the credentials object is not
passed to SESv2Client, STSClient, or SNSClient — the AWS SDK then falls
back to its default provider chain (IAM roles, ECS task roles, instance
profiles, etc.), which is the recommended approach for cloud-native deployments.
Closes#316
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* refactor: extract shared getAwsCredentialOptions helper and add partial-config guard
- Move the credential spread logic into a single credentials.ts helper
so SESv2Client, STSClient, and SNSClient all share one implementation
- Throw a clear error if only one of AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY
is set, preventing silent fallback to the default provider chain with a
half-configured environment
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: align AWS env vars in docker and docs
* fix: use alias import for AWS credentials helper
---------
Co-authored-by: purva <purvahk08@gmail.com>
Co-authored-by: Purva Kandalgaonkar <136103488+purva-8@users.noreply.github.com>
* 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>