Re-key the email notification channel from login accounts to profiles.
Each profile owns its mode, dispatch watermark, and destination address;
there is deliberately no fallback to the account email, so the account
holder no longer receives mail for every household profile. A profile
receives nothing until its own address is verified.
- Genericize the watermark-sweep engine over a recipient key
(accountChannel[K]): email keys by profile_id, Discord stays on
user_id. Delivery reads move into the channel adapters.
- Custom addresses verify via single-use SHA-256-hashed token links
served by a public endpoint; enabling the channel requires a verified
address, and clearing the address switches the channel off.
- Addresses are globally unique (case-insensitive): rejected when
verified for another profile or matching another account's email or
username. Checked at request time, re-checked at verify time
(first-to-verify wins), backstopped by a partial unique index.
- Every email carries an RFC 8058 one-click unsubscribe link backed by
a per-profile capability token, minted lazily under the claim tx.
- Child profiles cannot set addresses (and so receive no email in v1).
- Verification sends are rate limited (1/min, 10/day per profile);
mail.Message gains custom header support for List-Unsubscribe.
- Migration drops the account-level prefs table without carrying
opt-ins over, so nobody gets surprise emails post-upgrade.
Android/Apple notification settings need follow-up for the new
profile-scoped response shape and address-management endpoints.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>