unbreak /admin/analytics; make failed email sends honest
- Analytics: the layout renders 8 KPI cards but the fast /kpis endpoint that
- populates the header only ever returned 7 β `consultations` was missing, so
- `k.consultations.current` threw on every render. Being a layout, it took down
- every page under /admin/analytics, not just the overview. TypeScript missed it
- because the payload is typed Partial<ConversionsData>, and Partial only makes
- the top level optional. /kpis now returns consultations, and the header treats
- each metric as optional so future drift degrades one card instead of the hub.
- Team: an admin could edit a member's email in the dialog and see "updated"
- while PUT /api/admin/users/[id] silently dropped the field β a typo in an
- invite locked the person out permanently. Managers/owners can now correct it,
- audited as email_change, revoking outstanding tokens for both addresses.
- Email failures: sendBrevoEmail RESOLVES with { success: false }; the reset
- route awaited it in a try/catch and reported "reset link emailed" for sends
- Brevo had refused β every one of them since the authorised-IP list went on.
- It now returns the provider's reason plus the link, the admin UI offers that
- link for hand delivery, and reset tokens last 24h instead of 1h so a link
- sent over WhatsApp is still good when it is read.
a8681a0View on GitHub β