# Email Validation Strategy

We use `EctoCommons.EmailValidator` with **both** `:html_input` and `:pow`
checks, defined centrally in `Mv.Constants.email_validator_checks/0`
(`@email_validator_checks [:html_input, :pow]`).

## Why both checks

- `:html_input` — pragmatic validation matching browser `<input type="email">`
  behavior; accepts the common formats users expect from web forms.
- `:pow` — stricter, spec-following validation (RFC 5322 and related);
  supports international (Unicode) email addresses.

Using both balances user experience (accepting common formats) against
technical correctness (validating against email standards) and international
support.

## Usage

The checks are applied consistently at every validation point, all reading the
single central constant so they stay in sync:

- `Mv.Membership.Import.MemberCSV.validate_row/3` — CSV import (schemaless
  changeset: trims whitespace, requires email, then validates format via the
  shared checks).
- `Mv.Membership.Member` validations — Member resource.
- `Mv.Accounts.User` validations — User resource.

Member and User use similar schemaless changesets inside their Ash validations.

## Changing the validation strategy

Update `@email_validator_checks` in `Mv.Constants`; the change applies
everywhere automatically.

**Migration caveat:** tightening validation may invalidate existing data.
Consider whether stored emails are still valid, a migration strategy for those
that are not, and user communication.
