---
id: CON-CRM-ENT-034
name: Contact Details and Communication Preferences
feature: FEAT-CRM-ENT-03
product_area: crm
module: entities
revision: 1
status: draft
product_intent: proposed
implementation_evidence: observed
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
definition: >-
  Contact details are ways to reach people and organizations; communication preferences record a
  person’s choices about contact channels and subscriptions.
owned_by: MOD-CRM-ENT
facets:
  - name: Contact points
    meaning: Typed addresses and phones and ordered person e-mail addresses.
    used_for: Reaching people and organizations.
  - name: Source states
    meaning: 'Owned, copied, linked and disconnected details distinguish origin.'
    used_for: Sharing organization values and recovering removed sources.
  - name: Preferences
    meaning: Contact-wide restrictions and per-type choices.
    used_for: Recording communication instructions separately from sending.
acted_on_by:
  - CAP-CRM-ENT-005
  - CAP-CRM-ENT-006
  - CAP-CRM-ENT-007
visible_to:
  - ACT-CRM-001
  - ACT-CRM-002
  - ACT-CRM-003
  - ACT-CRM-005
narrative:
  status: verified
  review: NARRATIVE-REVIEW-2026-10-23
narrative_sources:
  - section: Why It Exists
    provenance: inferred
    source: >-
      services-crm:modules/entities/tests/integration/services/persistence/contacts.integration.spec.js#refuses
      a fourth e-mail address;
      services-crm:modules/entities/tests/integration/db/contact-email-addresses.table.integration.spec.js#refuses
      to make an inactive contact active while another contact holds its primary address;
      services-crm:modules/entities/tests/integration/services/persistence/contacts.integration.spec.js#refuses
      two numbers of the same type;
      services-crm:modules/entities/tests/integration/services/persistence/contacts.integration.spec.js#formats
      a valid US number, drops a blank one and marks the default preferred number;
      services-crm:modules/entities/tests/integration/services/persistence/contacts.integration.spec.js#marks
      the first address of the tenant’s display order as preferred, never one with a seasonal
      period;
      services-crm:modules/entities/tests/integration/services/persistence/contacts.field-rules.integration.spec.js#refuses
      an unknown country, naming the address’s country;
      services-crm:modules/entities/tests/integration/services/persistence/contacts.field-rules.integration.spec.js#leaves
      a contact saveable after the type of an address it holds became organizations-only;
      services-crm:modules/entities/tests/unit/services/contacts/seasonal-addresses.spec.js#refuses
      overlapping seasons naming both addresses;
      services-crm:modules/entities/tests/e2e/contacts.e2e.spec.js#answers the seasonal address in
      season when the contact marks it, with the workspace date;
      services-crm:docs/milestones/CRM-M1-contacts-and-organizations.plan.md#A9;
      services-crm:docs/disconnected-information.md#What changed;
      services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#refuses
      a link to a record of an organization other than the affiliation’s;
      services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#refuses
      a new link through an upcoming affiliation, naming the path;
      services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#refuses
      a value that differs from the organization’s in letter case, naming the field (A19);
      services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#writes
      nothing to the contact: its version is the one before;
      services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#turns
      the linked work address into a disconnected row holding its last value, not a copy (D-25);
      services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#refuses a client
      that asks for a row to be disconnected, naming the field;
      services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#is refused 409 on a
      row that is no longer disconnected;
      services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#makes
      an independent copy of the resolved value when the row is saved as copied with no value of its
      own;
      services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#refuses
      a save that removes the affiliation and keeps the rows linked through it;
      services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#links
      nothing when the choice is an empty list;
      services-crm:modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.follow-ups.integration.spec.js#links
      every default of its type on the start day when the save stated no choice; FND-CRM-ENT-010;
      services-crm:modules/entities/db/contacts.table.ts:do_not_mail;
      services-crm:modules/entities/tests/integration/services/persistence/contacts.integration.spec.js#refuses
      a communication type listed twice, naming the second entry;
      services-crm:modules/entities/tests/integration/db/contact-communication-preferences.table.integration.spec.js#refuses
      a subscription value that is not shaped like an address by the domain’s
      email_address_format_check;
      services-crm:modules/entities/tests/integration/db/contact-communication-preferences.table.integration.spec.js#refuses
      a subscription status outside the closed list by
      contact_communication_preferences_status_check;
      services-crm:modules/entities/services/persistence/contacts.ts:communicationPreferenceProblems;
      services-crm:docs/milestones/CRM-M1-contacts-and-organizations.plan.md#2. Scope
    note: Business need inferred from the sourced behavior; no historical motivation is attributed.
  - section: What It Controls
    provenance: observed
    source: >-
      services-crm:modules/entities/tests/integration/services/persistence/contacts.integration.spec.js#refuses
      a fourth e-mail address;
      services-crm:modules/entities/tests/integration/db/contact-email-addresses.table.integration.spec.js#refuses
      to make an inactive contact active while another contact holds its primary address;
      services-crm:modules/entities/tests/integration/services/persistence/contacts.integration.spec.js#refuses
      two numbers of the same type;
      services-crm:modules/entities/tests/integration/services/persistence/contacts.integration.spec.js#formats
      a valid US number, drops a blank one and marks the default preferred number;
      services-crm:modules/entities/tests/integration/services/persistence/contacts.integration.spec.js#marks
      the first address of the tenant’s display order as preferred, never one with a seasonal
      period;
      services-crm:modules/entities/tests/integration/services/persistence/contacts.field-rules.integration.spec.js#refuses
      an unknown country, naming the address’s country;
      services-crm:modules/entities/tests/integration/services/persistence/contacts.field-rules.integration.spec.js#leaves
      a contact saveable after the type of an address it holds became organizations-only;
      services-crm:modules/entities/tests/unit/services/contacts/seasonal-addresses.spec.js#refuses
      overlapping seasons naming both addresses;
      services-crm:modules/entities/tests/e2e/contacts.e2e.spec.js#answers the seasonal address in
      season when the contact marks it, with the workspace date;
      services-crm:docs/milestones/CRM-M1-contacts-and-organizations.plan.md#A9;
      services-crm:docs/disconnected-information.md#What changed;
      services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#refuses
      a link to a record of an organization other than the affiliation’s;
      services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#refuses
      a new link through an upcoming affiliation, naming the path;
      services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#refuses
      a value that differs from the organization’s in letter case, naming the field (A19);
      services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#writes
      nothing to the contact: its version is the one before;
      services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#turns
      the linked work address into a disconnected row holding its last value, not a copy (D-25);
      services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#refuses a client
      that asks for a row to be disconnected, naming the field;
      services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#is refused 409 on a
      row that is no longer disconnected;
      services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#makes
      an independent copy of the resolved value when the row is saved as copied with no value of its
      own;
      services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#refuses
      a save that removes the affiliation and keeps the rows linked through it;
      services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#links
      nothing when the choice is an empty list;
      services-crm:modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.follow-ups.integration.spec.js#links
      every default of its type on the start day when the save stated no choice; FND-CRM-ENT-010;
      services-crm:modules/entities/db/contacts.table.ts:do_not_mail;
      services-crm:modules/entities/tests/integration/services/persistence/contacts.integration.spec.js#refuses
      a communication type listed twice, naming the second entry;
      services-crm:modules/entities/tests/integration/db/contact-communication-preferences.table.integration.spec.js#refuses
      a subscription value that is not shaped like an address by the domain’s
      email_address_format_check;
      services-crm:modules/entities/tests/integration/db/contact-communication-preferences.table.integration.spec.js#refuses
      a subscription status outside the closed list by
      contact_communication_preferences_status_check;
      services-crm:modules/entities/services/persistence/contacts.ts:communicationPreferenceProblems;
      services-crm:docs/milestones/CRM-M1-contacts-and-organizations.plan.md#2. Scope
---

# Contact Details and Communication Preferences

## What It Is

Contact Details and Communication Preferences combines the ways staff can reach people and organizations with a person's recorded choices about communication. It includes ordered person e-mail addresses, typed phone numbers and addresses, preferred and seasonal selection, and source states for organization-supplied details. Preferences include broad channel restrictions and per-communication-type subscription information.

These details belong to their contact or organization, rather than existing as independent identities staff manage separately. Each address or phone element retains an identity for corrections and protection. Its type describes the purpose, while a source relationship explains whether the value is independent, copied, linked, or disconnected.

## Why It Exists

Our reading is that a reachable value needs context before staff can use it responsibly. A work address may belong to an affiliated firm, a seasonal residence may apply only part of the year, and a subscription destination may differ from the person's primary e-mail. Keeping those distinctions explicit prevents a plausible stored string from being mistaken for current, independently confirmed information.

## What It Is Not

A phone or address type is a purpose within contact information, not a separate person or organization classification. A preferred address is not automatically the mailing answer when explicitly enabled seasonal information applies. A live link is not a copy, and a disconnected value is not a deliberate independent copy. Recording a communication restriction also does not prove that every sender honors it.

## What It Controls

Ordering determines the person's primary e-mail, while preferred choices and type order supply supported phone and address selection. Seasonal periods and explicit use can change the mailing answer on the workspace calendar. Type applicability constrains new contact-point choices, and primary-address uniqueness depends on the contact's status under the contact-point rules.

A linked value resolves its current organization source through an eligible affiliation. Source removal preserves the last value as disconnected, records provenance, and advances affected person versions. Staff recovery can confirm it as owned, relink it, or remove it. Broad restrictions and subscription choices control stored preference information here; the downstream sender's interpretation remains a separate contract and unresolved enforcement boundary where not established.

## How It Is Used

The CRM Editor adds and corrects contact points, selects preferred or seasonal use, and records a member's communication instructions. The CRM Administrator maintains address and phone types and default sharing choices. The CRM Reader interprets values with their sources and restrictions. Good use investigates disconnected information and treats a change to an existing element as a correction unless staff actually intend replacement.

Shared-details work connects to Configure an affiliation type and use it on a contact and to the employer-change journey. Staff should check whether an old organization's address is unresolved because the tie ended or disconnected because the source was removed; those states explain different events and have different recovery behavior.

## Example

Ruth has an independent home address, a seasonal winter residence, and a work address linked to her member firm's main location. She asks for postal restrictions and a newsletter digest at a chosen subscription address. Staff can record all those distinctions on one person without claiming that the digest sender has been tested here.

When the firm moves, the work link resolves the new value on read. Removing its source instead leaves disconnected information for review. A coordinator reads Ruth's current version and relinks the work entry to the firm's replacement, while the independent home address and seasonal choices remain unchanged.

## How It Relates

Contact and Organization own the values, while Affiliation supplies the relationship permitting live sharing. Affiliation Type carries default mappings between source and destination type facets. Contact Role and Organization Compliance use effective people and primary e-mail for their separate responsibilities. Record Protection and History governs aggregate edits and element locks. Platform notifications owns sending and Platform metadata owns presentation and definition systems.
