Skip to content

No affordance for case-variant duplicate accounts created outside lead conversion #655

Description

@os-zhuang

Found while implementing #626 (PR #654). Filed unassigned, out of scope there.

What #626 fixed, and what it left

#626 makes lead conversion match accounts on a normalized company name, so the conversion path no longer creates near-duplicates (Acme Corp / ACME Corp). It deliberately did not add a unique index on crm_account.name_normalized — the reasoning is in src/objects/account.object.ts, but the short version is that account-name uniqueness already lives per-tenant on name (#625), and a unique normalized column would subsume that constraint and hard-fail writes that succeed today.

So every non-conversion path can still create two accounts whose names differ only in case or spacing: the Console form, the record API, a CSV import, a future seed row. Nothing detects it and nothing merges it.

Two concrete consequences

  1. No detection. A near-duplicate pair sits in the account list indefinitely. Contrast crm_lead, which already has the soft shape for the same class of problem: lead_duplicate_check flags a re-captured email as duplicate_status: 'suspected' and the suspected_duplicates view is the review queue. crm_account has neither half.
  2. Non-deterministic reuse. When two accounts do share a normalized name, lead_conversion's find_account node reuses an arbitrary one — the built-in get_record executor accepts filter / fields / limit and has no sort option (measured on 17.0.0-rc.1), so there is no "oldest wins" to express. Reusing one of N is still better than creating the N+1th, which is what happened before Normalize account matching in lead conversion (split out of #598 scope 2) #626, but it is not a defined outcome.

Possible shapes (not a recommendation)

Worth knowing before picking

The reason #626 could defer this at all is the maintainer's statement that this repo's deployment shape is fresh installs only. That premise is what bounds the create_index hazard and what makes "flow-level dedupe is enough" defensible today. If it ever stops holding, re-read this issue together with the index decision in account.object.ts and docs/MAINTENANCE.md §3.3 — both were written as conditional, not universal.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestmetadataDeclarative metadata — schema, security posture, UI surfacespm:queueReady for the PM dispatch loopprio:p2Triaged backlog — no near-term schedule

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions