2026-05-30 · Platform
Consent — push + SMS gates now enforced
- Marketing-class push + SMS sends now honour the same consent ledger as email broadcasts. `sendPushSchema` + `sendPushTopicSchema` + `sendSmsSchema` gain optional `category` field (`transactional | broadcast | workflow | auth`, default `broadcast`).
- Push — per-token gate inside `dispatchTokens` looks up `{userId: token.userId}` consent when `enforce_consent=true` + category is broadcast/workflow. Anonymous tokens (`token.userId === null`) suppress under enforcement — strict explicit-opt-in posture. Gate-fail row carries `status='suppressed' suppressedReason='no_consent'` + `push.suppressed` event.
- SMS — `{phone: input.to}` lookup before the suppression-list check. Gate-fail writes `status='failed' provider='suppressed' metadata.suppressed_reason='no_consent'` + new `sms.suppressed` event.
- Drift parity test (`developer-tools/consent-gate-drift.test.ts`) asserts all 3 channels import `shouldSend` + `isConsentEnforced` from the canonical consent service + write `no_consent` on gate fail.
- Closes the Wave 1a follow-up specifically called out in the Privacy product page + Wave 15 Email retract.