candidateQuery now blocks a lead whose WhatsApp number is shared by 2+
leads, unless a shared-number override exists. The inner correlated
subquery compares the bare other.whatsapp column (not normalizedSql())
against the outer row's two computed number forms so SQLite can use
idx_leads_whatsapp instead of a full table scan, keeping the 1.3M-row
perf test within budget.
Also updates the pre-existing 'persiste erro temporario e nao repete
equivalente' test: its two leads use 8/9-digit equivalent numbers,
which the new filter now blocks by default, so an override is added
to keep exercising the intended equivalent-number dedup behavior.
Implement shared-number detection in reserveOutreachSend: reject manual WhatsApp sends with HTTP 409 when the destination number is shared across 2+ leads and hasn't been explicitly released via override.
- Add test: reserveOutreachSend bloqueia numero compartilhado sem override e libera com override
- Add check in reserveOutreachSend right after isOptedOut check
- Uses isNumberSharedAcrossLeads and isSharedNumberOverridden from Task 1
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The v15 test pattern (delete migration records >= 15, drop schema, reopen to replay)
was failing because outreach_shared_number_overrides table from v19 migration was not
dropped before replaying. Add DROP TABLE IF EXISTS to the schema cleanup block to
match the same fix applied to v17 test.
This resolves the 'table already exists' error during v19 migration replay.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Add migration v19: creates outreach_shared_number_overrides table
- Implement 7 new data-layer functions:
- leadsSharingNumber: find leads sharing a phone number variant
- isNumberSharedAcrossLeads: detect if number is shared by 2+ leads
- getSharedNumberOverride: retrieve override entry for a number
- isSharedNumberOverridden: check if number has an override
- addSharedNumberOverride: create or update override with reason
- removeSharedNumberOverride: delete override record
- listSharedNumberGroups: group leads by shared numbers, reflect override state
- Add 4 comprehensive tests covering migration, detection, override crud, and grouping
- Update version assertions from 18 to 19
- Fix v17 migration test to properly clean up v19 table for schema reset
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Tracks the app that was already in place (capture, treatment, outreach,
WhatsApp integration, server, frontend, tests, docs) so future feature
work can branch and use isolated worktrees.