- Shipped
- September 3, 2026 at 8:03 PM UTC
- Author
- Kamo
- Commit
- f774107
**The Leads nav icon says when you cannot accept.** A member who holds leads they have not worked gets a red block emblem over the Leads icon and a tooltip naming what is blocked, why, and what to clear. Fed by /leads/available-summary and kept live by a new accept-gate event on the credit/assignment socket — the payload carries only a member id, so each browser ignores everybody else's and re-asks the server for its own. Shown to any member who can see leads, not only credit holders: since a free-for-all lead can now be self-claimed, the gate governs them too. The availability dot stays credit-only, so the two statements remain separable — you can be blocked from accepting while leads sit there available, and those are different things to say. **Every status is named the way THIS org names it.** The tooltip, the /leads/available notice and the detail-page copy resolve New Lead / Farm Fresh through useStatusLabels: labels are replaceable on /settings/features/crm, and telling a member to move a lead off "New Lead" when their org calls it something else names a status they cannot find in the picker. **/leads/available's notice splits into its two reasons** — leads owed a note, leads owed a status change — because merged into one list they read as an undifferentiated pile and the member has to open each lead to learn what it wants. A lead failing both is listed once, badged. **Assign to Myself** sits under Hot Reassign on an unassigned lead. Offered on a free-for-all lead to anyone not currently barred, and on any unassigned lead to a holder of ASSIGN_LEADS. The response carries the lead back unmasked, so setting it into state flips assignedToMe, recomputes the mask decision to UNMASKED, and reveals the contact information with no reload. **The status control pulses** while the lead is mine and still at New Lead or Farm Fresh — that is the control that fixes it, and the header is read long before a nav tooltip. Honours prefers-reduced-motion. **Masked contact info is obfuscated, not blanked.** contactObfuscator.ts mirrors the server's ContactObfuscator exactly, asserting the same strings, because the realtime lead relay ships a full unmasked DTO to every subscriber in the org and the browser is the only thing standing in front of it there. A blank field reads as "this lead has no e-mail", which is a different and wrong statement. **The /leads Unassigned filter is offered to everyone.** Without VIEW_UNASSIGNED_LEADS it returns the unassigned free-for-all leads this member may claim, and the label says so rather than the option quietly meaning two different things. The client no longer forces assigned=ASSIGNED for those members — the server's floor is wider than that now, and sending ASSIGNED would clip exactly the rows this change exists to show.