---
id: CAP-CRM-ENT-006
title: Share organization contact points with affiliated people
product_area: crm
module: entities
revision: 1
status: approved
product_intent: proposed
implementation_evidence: partially-observed
source_sha:
  services-crm: 7ea48a414c42eade10d60753b8bcc323b1dd726f
  react-console: da63075876b2c5f4a6af07d457bb24ea8bf4c0c7
intent_sources:
  - 'services-crm:docs/milestones/CRM-M1-contacts-and-organizations.md#D-01'
  - 'services-crm:docs/milestones/CRM-M1-contacts-and-organizations.plan.md#A11'
  - 'services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.plan.md#A9'
  - >-
    services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.plan.md#A19
  - >-
    services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.plan.md#A22
  - 'services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.md#M2-D1'
  - 'services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.md#M2-D4'
  - 'services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.md#M2-D11'
purpose: >-
  Staff share organization details with affiliated people and handle links whose
  sources disappear.
outcomes:
  - >-
    A linked row always displays the organization's current value while the
    affiliation is in effect, without rewriting the contact.
  - No contact silently loses a value or preserves an unmarked stale one.
  - A staff member chooses which of a affiliation's default links are made.
actors:
  - ACT-CRM-001
  - ACT-CRM-003
  - ACT-CRM-004
  - ACT-CRM-005
surfaces:
  - console
  - api
  - job
preconditions: []
postconditions: []
permissions:
  - key: crm.contacts.update
    where_checked: api
    scope: tenant
  - key: crm.organizations.update
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-CRM-ENT-006-01
    proved_by: []
    statement: >-
      Contact addresses and phone numbers identify whether their values are
      owned, deliberately copied from an organization, linked to its current
      record or disconnected with the last value after their linked source
      disappears.
    kind: invariant
    enforced_at:
      - service
      - database
    must_prove: false
    provenance: documented
    source: 'services-crm:docs/disconnected-information.md#What changed'
    origin: 'services-crm:docs/milestones/CRM-M1-contacts-and-organizations.plan.md#A11'
  - id: BR-CAP-CRM-ENT-006-02
    proved_by: [ATS-CRM-ENT-006-01, TST-CRM-ENT-786, TST-CRM-ENT-790]
    statement: >-
      A contact-information link must use an affiliation present after the save
      and a record or record type of that affiliation’s organization; another
      organization’s record or a missing source type is rejected.
    kind: validation
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      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
    origin: none
  - id: BR-CAP-CRM-ENT-006-03
    proved_by: [ATS-CRM-ENT-006-02, TST-CRM-ENT-790]
    statement: >-
      Creating or redirecting a contact-information link requires an affiliation
      effective on the workspace’s current day.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      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
    origin: >-
      services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.plan.md#A22
  - id: BR-CAP-CRM-ENT-006-04
    proved_by: [ATS-CRM-ENT-006-03, TST-CRM-ENT-776, TST-CRM-ENT-790]
    statement: >-
      A linked element cannot store a value different from its organization
      source; whitespace-only differences are accepted and differences in letter
      case are rejected.
    kind: validation
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      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)
    origin: >-
      services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.plan.md#A19
  - id: BR-CAP-CRM-ENT-006-05
    proved_by: [ATS-CRM-ENT-006-04, TST-CRM-ENT-776, TST-CRM-ENT-790]
    statement: >-
      An effective link resolves to the organization’s current value without
      changing the contact on an organization edit; an ineffective affiliation
      retains an unresolved link without a value.
    kind: calculation
    enforced_at:
      - database
      - service
    must_prove: true
    provenance: test
    source: >-
      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
    origin: >-
      services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.plan.md#A9
  - id: BR-CAP-CRM-ENT-006-06
    proved_by: [ATS-CRM-ENT-005-15, ATS-CRM-ENT-006-05, ATS-CRM-ENT-006-13, TST-CRM-ENT-775, TST-CRM-ENT-786, TST-CRM-ENT-790]
    statement: >-
      Removing a shared organization address or phone disconnects its contact
      links in the same transaction, preserves the last value with source, time
      and reason, marks verification as needed and advances the affected
      contacts’ versions.
    kind: lifecycle
    enforced_at:
      - database
    must_prove: true
    provenance: test
    source: >-
      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)
    origin: 'services-crm:docs/milestones/CRM-M1-contacts-and-organizations.plan.md#A11'
  - id: BR-CAP-CRM-ENT-006-07
    proved_by: [ATS-CRM-ENT-006-06, TST-CRM-ENT-786]
    statement: >-
      Clients cannot create disconnected elements, and returning an existing
      disconnected element preserves its server-recorded provenance.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      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
    origin: 'services-crm:docs/milestones/CRM-M1-contacts-and-organizations.plan.md#A11'
  - id: BR-CAP-CRM-ENT-006-08
    proved_by: [ATS-CRM-ENT-006-07, ATS-CRM-ENT-006-12, TST-CRM-ENT-786]
    statement: >-
      Version-checked verify, relink and remove actions respectively convert a
      disconnected element to an owned value, link it to exactly one
      current-affiliation source by id or type, or delete it; they reject a
      non-disconnected row, an unknown element and missing or stale versions.
    kind: lifecycle
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#is
      refused 409 on a row that is no longer disconnected
    origin: 'services-crm:docs/milestones/CRM-M1-contacts-and-organizations.plan.md#A11'
  - id: BR-CAP-CRM-ENT-006-09
    proved_by: [ATS-CRM-ENT-006-08, TST-CRM-ENT-776, TST-CRM-ENT-790]
    statement: >-
      Making a linked element independent stores a copy of its resolved
      organization value with the source organization and copy time, and
      subsequent source edits do not change it.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      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
    origin: none
  - id: BR-CAP-CRM-ENT-006-10
    proved_by: [ATS-CRM-ENT-006-09, ATS-CRM-ENT-006-14, ATS-CRM-ENT-009-20, TST-CRM-ENT-776, TST-CRM-ENT-790]
    statement: >-
      Removing an affiliation requires handling every information link it
      supplies in the same save, whereas ending it is allowed and leaves
      unresolved links.
    kind: invariant
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      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
    origin: >-
      services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.plan.md#3.
      How it works for the user
  - id: BR-CAP-CRM-ENT-006-11
    proved_by: [ATS-CRM-ENT-006-10, ATS-CRM-ENT-006-16, ATS-CRM-ENT-017-12, TST-CRM-ENT-776, TST-CRM-ENT-790]
    statement: >-
      A new effective affiliation fills empty destination types from its
      selected default mappings without replacing existing values, uses every
      mapping when selection is omitted and uses none for an explicitly empty
      selection.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#links
      nothing when the choice is an empty list
    origin: 'services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.md#M2-D1'
  - id: BR-CAP-CRM-ENT-006-12
    proved_by: [ATS-CRM-ENT-006-11, ATS-CRM-ENT-006-15, ATS-CRM-ENT-010-09, TST-CRM-ENT-776, TST-CRM-ENT-790]
    statement: >-
      Default mappings apply only through effective affiliations, including
      pending choices on a future affiliation’s start day and explicit
      reapplication to a current affiliation; ended affiliations create no links
      and changing type defaults does not rewrite existing contacts.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      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
    origin: 'services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.md#M2-D4'
  - id: BR-CAP-CRM-ENT-006-13
    proved_by: []
    statement: >-
      The product should show the number of affected people before an
      organization removes an address they share.
    kind: policy
    enforced_at: []
    must_prove: true
    provenance: unknown
    source: FND-CRM-ENT-010
    origin: >-
      services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.md#M2-D11
scenarios:
  - id: SC-CAP-CRM-ENT-006-01
    given: >-
      Daniel's work address is linked to Bayview's main address through his
      Employer affiliation.
    when: Bayview's address is edited.
    then: >-
      Daniel's next read displays the new address and his record has no new
      revision.
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#changes
      the contact’s resolved work address
  - id: SC-CAP-CRM-ENT-006-02
    given: Harbor Society removes the address three members link to.
    when: The members are read.
    then: >-
      Each preserves the last address, disconnected, needing verification,
      naming Harbor and the moment.
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/organizations/CRM-ACC-0118.spec.ts#CRM-ACC-0118
edge_cases:
  - id: SC-CAP-CRM-ENT-006-03
    given: >-
      A staff member unticks the work-phone link when adding an Employer
      affiliation.
    when: The contact is saved.
    then: The work address is linked and the work phone is not.
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0185.spec.ts#CRM-ACC-0185
constraints: []
depends_on:
  - CAP-CRM-ENT-009
  - CAP-CRM-ENT-017
related:
  - CAP-CRM-ENT-005
  - CAP-CRM-ENT-009
  - CAP-CRM-ENT-010
  - CAP-CRM-ENT-017
journeys:
  - JNY-CRM-ENT-002
  - JNY-CRM-ENT-004
open_questions: []
feature: FEAT-CRM-ENT-03
concepts:
  - CON-CRM-ENT-001
  - CON-CRM-ENT-002
  - CON-CRM-ENT-003
evidence:
  - >-
    `services-crm` at `7ea48a414c42eade10d60753b8bcc323b1dd726f`: examined
    `services/persistence/contacts.ts` (sources, defaults, reapply),
    `aws/api/disconnected-information.ts`, `aws/api/contacts.routes.ts` (verify, relink, remove),
    `services/affiliations/affiliation-default-link-reconciliation.ts`,
    `db/contact-addresses.table.ts`, `db/contact-phone-numbers.table.ts`,
    `db/contact-information-effective.view.ts`, `docs/disconnected-information.md`,
    `docs/affiliations/README.md` §0b, §5.6b; tests `e2e/contact-information-sources.e2e.spec.js`,
    `e2e/contacts-disconnected.e2e.spec.js`,
    `integration/services/persistence/contact-information-sources.integration.spec.js`,
    `integration/services/affiliations/affiliation-date-reconciliation.follow-ups.integration.spec.js`.
  - >-
    `react-console` at `da63075876b2c5f4a6af07d457bb24ea8bf4c0c7`: examined
    `components/affiliations/linked-source.tsx`, `disconnected-source.tsx`,
    `change-source-dialog.tsx`, `affiliation-editor.tsx`; inventory RUL-CRM-AFF-042 to 051,
    RUL-CRM-ORG-040, 041; journeys CRM-ACC-0024, 0118, 0119, 0148, 0185, 0190, 0191, 0203, 0204.
approved_by: Andrew
approved_at: 2026-10-22
controls: [TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-006, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-LOG-004, TC-LOG-005, TC-PI-001, TC-PI-003, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-TEN-001, TC-TEN-002, TC-TEN-003]
narrative:
  status: verified
  review: NARRATIVE-REVIEW-2026-10-23
narrative_sources:
  - section: Why It Works This Way
    provenance: inferred
    source: >-
      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
    note: >-
      Operational rationale inferred from the cited behavior; no personal motive
      or historical decision is asserted.
repositories:
  - repo: services-crm
    role: owner
    paths:
      - modules/entities/
      - docs/disconnected-information.md
      - modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js
      - >-
        modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.follow-ups.integration.spec.js
      - >-
        modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js
  - repo: react-console
    role: console
    paths:
      - 'app/(console)/console/[tenantId]/crm/contacts/'
      - acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0185.spec.ts
      - acceptance/crm/playwright/journeys/organizations/CRM-ACC-0118.spec.ts
exercised_by: [FAS-CRM-ENT-03-01, FAS-CRM-ENT-03-02, FAS-CRM-ENT-03-03, FAS-CRM-ENT-03-04, FAS-CRM-ENT-03-05]
suites: [TST-CRM-ENT-775, TST-CRM-ENT-776, TST-CRM-ENT-786, TST-CRM-ENT-790]
---

# Share organization contact points with affiliated people

## Purpose

A person may use a member firm's address or telephone rather than maintain an independent work contact point. This capability keeps the source relationship explicit, lets a live value follow the organization, and gives staff a recovery process when removed source information can no longer be treated as reliably shared.

## How It Works

Addresses and phones distinguish owned values, intentional copies, live links, and disconnected values. A link names an affiliation and a source belonging to that affiliation's organization. New or redirected links need an affiliation effective today. The service prevents a linked row from carrying a competing value; reads resolve the current organization source without saving the person when the source changes.

An affiliation that is no longer effective leaves its link unresolved. Removing the organization source has a different effect: in the same transaction, affected contact entries become disconnected, retain the last value and source provenance, require verification, and advance their contacts' versions. Clients cannot manufacture that server-recorded state.

With the current contact version, staff can verify a disconnected value as independently owned, relink it to one eligible source, or remove it. A deliberate independent copy also stops following later source changes. Removing an affiliation requires dealing with all its supplied links in the same save, while ending it can retain unresolved links.

Default mappings fill empty destination types on eligible affiliations and respect the saved selection. An omitted selection and an explicitly empty selection differ. Future choices wait for the start, and changing type defaults does not rewrite existing people.

## Example

Ruth's work address links to Harbor Engineering's main address through her current employer affiliation. A move updates the value Ruth sees without a contact edit. Later the firm removes the source address. Ruth retains the last address with a disconnected state and a newer record version. A coordinator reads that version and relinks the work entry to the firm's billing address, resolving the uncertainty without losing the explanation of the old source's removal.

Ruth's coordinator reads her latest version after the firm's source removal. An editor opened before that removal is stale because disconnection advanced the affected contact. She then chooses one recovery, verifies its returned state and reads the record again: verification leaves an independent owned value; relinking uses a currently effective affiliation and one eligible source; removal leaves no element. Merely sending back the disconnected row does not erase its server provenance. If Ruth's affiliation ended instead of the source being removed, the resulting unresolved link is a different starting state and cannot be treated as a disconnected element requiring the same recovery action.

## Why It Works This Way

Our reading is that live resolution prevents synchronization copies from drifting while preserving which organization supplies the detail. Restricting new links to effective affiliations prevents a future or former employer from becoming a current source. Refusing competing linked values keeps the link from meaning two things at once.

Disconnection differs from a deliberate copy because source removal is evidence that reliability needs review, not evidence that the person wants an independent address. Preserving the last value supports investigation without silently treating it as confirmed. Versioned recovery prevents a coordinator from resolving an entry that someone else already changed. Empty-destination defaults avoid overwriting independent information, and nonretroactive configuration respects decisions already made on existing contacts. Handling link removal together with affiliation removal prevents dangling explanations of source ownership.

## Relationships

Maintain a person’s organizational relationships owns the affiliation that authorizes sharing. Configure affiliation types and contact roles supplies default mappings, and Keep dated relationships current applies pending choices on eligible starts. Maintain reliable contact points owns value validation. Platform metadata supplies display; organization and contact persistence coordinate source-removal changes transactionally rather than relying on a later synchronization copy.
