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:
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".
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.
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.mdxline 62 (and its two translations) state the contact-email rule as:Both sentences are wrong, and the second one documents a workflow the product actively refuses.
What is actually enforced, on two independent layers:
src/objects/contact.object.tsdeclares field-levelunique: trueonemail. 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".contact_integrityinsrc/objects/contact.hook.tsrejects 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:62content/docs/sales/contacts.zh-Hans.mdx:62content/docs/sales/contacts.zh-Hant.mdx:62Suggested 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_accountin #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
contacts*.mdxrule lines describe the per-organization constraint thatcrm_contact.email+contact_integrityactually enforce.