---
id: CAP-CRM-DQ-017
title: Combine organizations and their connections safely
feature: FEAT-CRM-DQ-04
product_area: crm
module: data-quality
revision: 1
status: draft
product_intent: confirmed
implementation_evidence: observed
supersedes:
  - CAP-CRM-MRG-023
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - 'services-crm:docs/merging/decisions.md#D7 (decided 2026-10-12), D9 and D10 (decided 2026-10-14)'
  - >-
    services-crm:docs/merging/conflict-resolution.md#4. Collection rules (organization merge re-points links,
    Andrew 2026-10-13)
  - >-
    services-crm:docs/merging/experience/functional-requirements.md#ORG-2 to ORG-8 (package approved by Andrew
    2026-10-13)
purpose: Administrators can combine organizations while preserving a valid hierarchy and the people linked to it.
outcomes:
  - People from both organizations retain affiliations to the survivor.
  - Parent and child movements preserve an acyclic hierarchy.
  - Size refusals and warnings make unusually large work visible.
concepts:
  - CON-CRM-DQ-004
actors:
  - ACT-CRM-009
surfaces:
  - console
  - api
permissions:
  - key: crm.organizations.merge
    where_checked: api
    scope: tenant
  - key: crm.organizations.read
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-CRM-DQ-017-01
    proved_by: [ATS-CRM-DQ-017-01, ATS-CRM-DQ-017-09, ATS-CRM-DQ-017-11]
    statement: >-
      The survivor's parent can only be outside participants and their descendants; internal parent links are
      removed with a cycle warning and children of absorbed organizations re-parent to the survivor.
    kind: validation
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/merges/tests/unit/services/planning/organization-hierarchy.spec.js#says the link it
      removed would have made a cycle
    origin: 'services-crm:docs/merging/experience/functional-requirements.md#ORG-2'
  - id: BR-CAP-CRM-DQ-017-02
    proved_by: [ATS-CRM-DQ-017-02, ATS-CRM-DQ-017-09, ATS-CRM-DQ-017-11]
    statement: >-
      One primary domain remains, defaulting to the survivor's, distinct remaining domains become alternates
      and boolean flags combine automatically.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/merges/tests/unit/services/planning/organization-fields.spec.js#unions every other
      distinct domain into the alternate domain names
    origin: 'services-crm:docs/merging/experience/functional-requirements.md#ORG-5'
  - id: BR-CAP-CRM-DQ-017-03
    proved_by: [ATS-CRM-DQ-017-03, ATS-CRM-DQ-017-11]
    statement: >-
      Different organization types create a type question and a warning about separate branches without
      blocking execution.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/merges/tests/unit/services/planning/organization-decisions.spec.js#asks which type
      the survivor keeps and warns that they may not be duplicates at all
    origin: 'services-crm:docs/merging/experience/functional-requirements.md#ORG-7'
  - id: BR-CAP-CRM-DQ-017-04
    proved_by: [ATS-CRM-DQ-017-04, ATS-CRM-DQ-017-09, ATS-CRM-DQ-017-11, TST-CRM-DQ-181]
    statement: >-
      Affiliations and roles move to the survivor, equivalent stays combine into its affiliation with primary
      status if either held it and discarded details are listed.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/merges/tests/integration/services/merges/organization-merge-execution.integration.spec.js#combines
      the two stays of somebody who worked at both into the survivor’s own affiliation
    origin: 'services-crm:docs/merging/experience/functional-requirements.md#ORG-6'
  - id: BR-CAP-CRM-DQ-017-05
    proved_by: [ATS-CRM-DQ-017-05, ATS-CRM-DQ-017-09, ATS-CRM-DQ-017-11]
    statement: >-
      Organization merges above 100,000 affiliation writes, including combined-away rows, are rejected; large
      plans explain affected people, duration and editing waits.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/merges/tests/unit/services/planning/organization-decisions.spec.js#refuses a merge
      of 100,001 affiliations
    origin: 'services-crm:docs/merging/decisions.md#D7 (decided 2026-10-12: a ceiling of 100,000 employees)'
  - id: BR-CAP-CRM-DQ-017-06
    proved_by: [ATS-CRM-DQ-017-06, ATS-CRM-DQ-017-09, ATS-CRM-DQ-017-11, TST-CRM-DQ-181]
    statement: >-
      Linked employee details retain kept source records, redirect discarded slots to the retained same-type
      detail or copy their last value when no detail of that type remains, with each changed link recorded.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/merges/tests/integration/services/merges/organization-merge-execution.integration.spec.js#re-points
      a link to a record that lost its slot to the record of its type the merge kept
    origin: >-
      services-crm:docs/merging/conflict-resolution.md#4. Collection rules (organization merge re-points
      links, Andrew 2026-10-13)
  - id: BR-CAP-CRM-DQ-017-07
    proved_by: [ATS-CRM-DQ-017-07, ATS-CRM-DQ-017-11, TST-CRM-DQ-181]
    statement: >-
      The result keeps one address and phone per type, lists discarded items and retains exactly one preferred
      address selected by the plan.
    kind: calculation
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/merges/tests/integration/services/merges/organization-merge-preferred-address.integration.spec.js#carries
      the merge out, rather than failing on the preferred-address index
    origin: none
  - id: BR-CAP-CRM-DQ-017-08
    proved_by: [ATS-CRM-DQ-017-10, ATS-CRM-DQ-017-11]
    statement: >-
      Organization role compliance and region assignment are recomputed after merging rather than offered as
      choices.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/merges/tests/unit/services/planning/organization-fields.spec.js#never offers the
      contact role compliance status and recomputes it after the merge
    origin: 'services-crm:docs/merging/experience/functional-requirements.md#ORG-8'
  - id: BR-CAP-CRM-DQ-017-09
    proved_by: [ATS-CRM-DQ-017-08, ATS-CRM-DQ-017-11]
    statement: >-
      Adding, removing or editing an affiliation that the merge moves invalidates the approved preview, even
      without an affiliation combination.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: observed
    source: 'services-crm:modules/merges/services/planning/merge-engine.ts:materialPlanHash'
    origin: 'services-crm:docs/milestones/CRM-M4-duplicates-and-merge.md#D-31'
  - id: BR-CAP-CRM-DQ-017-10
    proved_by: []
    statement: An organization locked against changes cannot participate in a merge.
    kind: validation
    enforced_at:
      - service
    must_prove: false
    provenance: test
    source: >-
      services-crm:modules/merges/tests/unit/services/planning/organization-decisions.spec.js#blocks a merge
      of a locked organization
    origin: none
scenarios:
  - id: SC-CAP-CRM-DQ-017-01
    given: 'Two organizations have children, employees, domains and a person affiliated to both.'
    when: An administrator combines them.
    then: 'The absorbed domain becomes an alternate, children and people move and the overlapping stay combines.'
    provenance: test
    source: 'react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0270.spec.ts#CRM-ACC-0270'
  - id: SC-CAP-CRM-DQ-017-02
    given: Employees link work addresses from the absorbed organization.
    when: The plan retains the survivor's address of that type.
    then: Employee links redirect to that address and each change is recorded.
    provenance: test
    source: 'react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0282.spec.ts#CRM-ACC-0282'
edge_cases:
  - id: SC-CAP-CRM-DQ-017-03
    given: An organization and its descendant participate together.
    when: The administrator opens their preview.
    then: >-
      Neither an excluded descendant nor the internal link can become the survivor's parent, and the removed
      link is explained.
    provenance: test
    source: 'react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0271.spec.ts#CRM-ACC-0271'
constraints:
  - 'Near the affiliation ceiling, execution can take several minutes within the durable job limit.'
depends_on:
  - CAP-CRM-DQ-016
related:
  - CAP-CRM-DQ-014
  - CAP-CRM-ENT-002
  - CAP-CRM-ENT-006
  - CAP-CRM-ENT-009
journeys:
  - JNY-CRM-DQ-004
open_questions: []
evidence:
  - repository: services-crm
    source_sha: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
    paths:
      - docs/merging/conflict-resolution.md
      - docs/merging/decisions.md
      - docs/merging/experience/functional-requirements.md
      - docs/milestones/CRM-M4-duplicates-and-merge.md
      - modules/merges/services/planning/merge-engine.ts
      - modules/merges/services/planning/organization-merge-model.ts
      - modules/merges/services/planning/organization-merge-planner.ts
      - modules/merges/tests/integration/services/merges/organization-merge-execution.integration.spec.js
      - >-
        modules/merges/tests/integration/services/merges/organization-merge-preferred-address.integration.spec.js
      - modules/merges/tests/unit/services/planning/organization-decisions.spec.js
      - modules/merges/tests/unit/services/planning/organization-fields.spec.js
      - modules/merges/tests/unit/services/planning/organization-hierarchy.spec.js
    note: 'Static examination connects rule claims to implementation, declared checks and the cited tests.'
  - repository: react-console
    source_sha: baf6dae382d6f41dce976c7f848667ccc37e076f
    paths:
      - acceptance/crm/playwright/journeys/merging/CRM-ACC-0270.spec.ts
      - acceptance/crm/playwright/journeys/merging/CRM-ACC-0271.spec.ts
      - acceptance/crm/playwright/journeys/merging/CRM-ACC-0282.spec.ts
    note: 'Static examination connects rule claims to implementation, declared checks and the cited tests.'
preconditions: []
postconditions: []
controls: [TC-AVL-004, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-005, TC-AZ-006, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-MON-002, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-PRV-003, TC-TEN-001, TC-TEN-002, TC-TEN-003]
exercised_by: [FAS-CRM-DQ-04-02]
suites: [TST-CRM-DQ-181]
---

# Combine organizations and their connections safely

## Purpose

Administrators can combine organizations while preserving a valid hierarchy and the people linked to it.

## How It Works

The organization preview compares names, domains, types and contact details. It excludes participants and their descendants from possible survivor parents. Existing parent links between participants disappear with a warning rather than creating a cycle. Children move to the survivor. The plan retains one primary domain and combines distinct alternatives. Different organization types create a choice and a caution about whether the records describe the same organization. Affiliations move with their roles, combining equivalent stays where needed. Linked employee contact details follow retained organization details or become copies if no source of that type remains. The plan enforces size limits and warns when people may wait for edits. Compliance and automatic region assignment are recalculated after execution. Approval includes the affiliations that move, not merely their count.

## Relationships

Decision review governs organization choices. Related-record policies cover child and affiliation references. Atomic execution applies the same safety boundary as contact merging.
