Skip to content

Docs promise contact emails are unique "within the same account" — the enforced rule is per organization, and the documented use case is rejected #648

Description

@os-zhuang

Found while fixing #625 (account-name uniqueness). Out of scope there — different object, different files. Filing per Prime Directive #10.

What

content/docs/sales/contacts.mdx line 62 (and its two translations) state the contact-email rule as:

An email address must be unique within the same account. The same person can appear under multiple companies (a board member, for example) but not twice in one company.

Both sentences are wrong, and the second one documents a workflow the product actively refuses.

What is actually enforced, on two independent layers:

  1. src/objects/contact.object.ts declares field-level unique: true on email. Since framework#3696 that materializes as the tenant composite (organization_id, email) — unique across the WHOLE organization, not per account. The object's own comment says so: "two orgs may each know john@acme.com" — note "orgs", not "accounts".
  2. contact_integrity in src/objects/contact.hook.ts rejects a duplicate email across accounts before the database ever sees it. There is a test named for exactly this: test/hooks-runtime-sales.test.ts"rejects a duplicate email GLOBALLY, not just within one account", whose comment records why: "A per-account lookup let a cross-account duplicate sail past the friendly check and explode on the DB's global unique index mid-conversion."

So the board-member example in the docs — the same person under two companies — is precisely the case that throws already exists. A user following the documentation gets an error the documentation says they will not get.

Affected files

  • content/docs/sales/contacts.mdx:62
  • content/docs/sales/contacts.zh-Hans.mdx:62
  • content/docs/sales/contacts.zh-Hant.mdx:62

Suggested fix

Docs-only. Restate the rule as enforced: an email address is unique within your organization — the same address cannot appear on two contacts even under different accounts; another organization on the same platform may have its own contact with that address. Drop the board-member example, or replace it with the shape the product supports.

Note the same sentence pattern was corrected for crm_account in #625 / PR #646 ("across the system (case-insensitive)" → per organization, exact match), so the wording there is a usable template.

Deliberately NOT part of this issue

Whether "one person, two companies" should be supported is a product decision, not a doc fix. If the answer is yes, it is a schema change (the contact-email constraint would have to move) and needs its own issue. This one is only about the docs describing what ships today.

Acceptance

  • The three contacts*.mdx rule lines describe the per-organization constraint that crm_contact.email + contact_integrity actually enforce.
  • No example in those files describes a write the product rejects.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationprio: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