# White-label (M6)

## Branding

Stored on the master tenant row (`tenants.settings.branding`), so pages outside a workspace (the invitation page) can use it without opening the tenant DB.

- Every plan: name, accent colour and footer on reports; reply-to address on client e-mails.
- `whitelabel` plans additionally get:
  - a logo (PNG, JPEG or WebP up to 512 KB; SVG refused because it can carry script), stored on the `public` disk;
  - agency logo, name and colour in place of the platform's in the app, the client portal and the invitation page (CSS variables `--color-brand-*`). Sign-in is shared by every agency on one address, so it keeps the platform brand;
  - workspace e-mails (reports, notifications, invitations) sent under the agency name, and from the agency's own address once its domain is verified (below);
  - the logo on PDF reports, embedded as a data URI.
- The accent colour must reach 4.5:1 contrast with white, because it is used behind white button text.

## Sending from the agency's domain

Settings → "Send e-mail from your domain" (`/settings/domains`) (white-label plans, `SenderDomains`):

1. The agency enters `hello@agency.com`. Free-mail domains, our own domains and a domain another workspace uses are refused.
2. The domain is registered with Amazon SES as an Easy DKIM identity (`SesSenderIdentityProvider`); the three DKIM CNAME records (`{token}._domainkey.agency.com → {token}.dkim.amazonses.com`) are shown and stored in `tenants.settings.sender`.
3. "Check DNS" or `mail:verify-sender-domains` (hourly) marks it verified when SES does.
4. `SenderDomains::from($tenant)` then returns that address for reports (`ReportReady`), workspace notifications and invitations. Before verification, after removal or after a downgrade, mail goes from `MAIL_FROM_ADDRESS` under the agency name. Billing and platform e-mails always come from us.

Requires `MAIL_MAILER=ses` (driver from `SENDER_DOMAIN_DRIVER`, default `ses` when SES is the mailer, otherwise `none`, which shows the reason on the page). The SES account must be out of the sandbox, and the IAM user needs `ses:CreateEmailIdentity`, `ses:GetEmailIdentity` and `ses:DeleteEmailIdentity`. `fake` is the local/testing sandbox.

There are no custom domains: the whole app runs on one address (docs/dev/tenancy.md).
