feat(notifications): visible unsubscribe footer link in lifecycle mails

- inject signed unsubscribeUrl into every optional-workflow Novu payload
  (templates render it via {{#if unsubscribeUrl}} footer)
- add 'conversion' campaign workflow to OPTIONAL_WORKFLOWS + email_marketing
  category so its one-click tokens validate and opt-outs suppress it
- declare UNSUBSCRIBE_SECRET/URL_BASE/EMAIL in env schema (""→undefined
  preprocess against the url().optional() boot-crash trap), .env.example and
  both compose env blocks
- fix confirmation-page settings link (?tab=notifications)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 16:35:47 +03:00
parent 66b39862c8
commit 29e10b432f
6 changed files with 61 additions and 12 deletions

View File

@@ -73,6 +73,10 @@ services:
- NOVU_API_KEY=${NOVU_API_KEY:-}
- APP_PUBLIC_URL=${APP_PUBLIC_URL:-https://sase.tr}
- MAILTRACK_SECRET=${MAILTRACK_SECRET:-}
# Unsubscribe links (List-Unsubscribe header + mail footer); empty secret = mailto-only
- UNSUBSCRIBE_SECRET=${UNSUBSCRIBE_SECRET:-}
- UNSUBSCRIBE_URL_BASE=${UNSUBSCRIBE_URL_BASE:-}
- UNSUBSCRIBE_EMAIL=${UNSUBSCRIBE_EMAIL:-}
# PostHog server-side analytics (payments, subscription lifecycle, $revenue).
# Empty key → PostHogService no-ops (server-side analytics disabled).
- POSTHOG_API_KEY=${POSTHOG_API_KEY:-}
@@ -211,6 +215,10 @@ services:
- NOVU_API_KEY=${NOVU_API_KEY:-}
- APP_PUBLIC_URL=${APP_PUBLIC_URL:-https://sase.tr}
- MAILTRACK_SECRET=${MAILTRACK_SECRET:-}
# Unsubscribe links (List-Unsubscribe header + mail footer); empty secret = mailto-only
- UNSUBSCRIBE_SECRET=${UNSUBSCRIBE_SECRET:-}
- UNSUBSCRIBE_URL_BASE=${UNSUBSCRIBE_URL_BASE:-}
- UNSUBSCRIBE_EMAIL=${UNSUBSCRIBE_EMAIL:-}
# PostHog server-side analytics (payments, subscription lifecycle, $revenue).
# Empty key → PostHogService no-ops (server-side analytics disabled).
- POSTHOG_API_KEY=${POSTHOG_API_KEY:-}