- Shipped
- August 26, 2026 at 3:52 AM UTC
- Author
- Kamo
- Commit
- 1b811a6
Two fixes the account rollup made visible. A phone number can be a contact point on more than one owner at the same time, and two leads on one account sharing one is the ORDINARY case — they are the same person enquiring twice, which is why they are on one account. The matcher writes a row per owner deliberately, because each of those timelines needs its own; unioned into a rollup, that is one call shown twice. Worse than untidy: the from the last entry shown, so the next page starts in the wrong place. Rows are now collapsed on (channel, sourceId) — the identity ingestion already uses to stay idempotent — and counts use COUNT(DISTINCT sourceId) so the rail agrees with the list. The second is older than this feature. membersFor returned Map.of() when no row named a staff member, and callers look each row up by row.getMemberId(), which is null for every inbound call, text or e-mail nobody handled. Map.of().get(null) throws, so a page whose entries were ALL unattributed answered 500 — the state an unworked lead's timeline is in by definition. It returns a HashMap now, which answers null, which is what the mapper already expected. Mapping also moved after the merge, so an account rolling up 25 leads resolves staff members in one query instead of 25.