---
id: ATS-CRM-DQ-018
scope: CAP-CRM-DQ-018
product_area: crm
module: data-quality
revision: 1
status: proposed
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-CRM-DQ-018-01
    title: Absorbed participants create distinct aliases
    level: api
    proves:
      - BR-CAP-CRM-DQ-018-01
    preconditions: Prepare a four-contact merge.
    steps: 'Execute and inspect each alias, then duplicate one.'
    expected: >-
      Three aliases retain survivor, merge and original numbers and the repeated
      alias is refused.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-181
    provenance: test
    source: >-
      services-crm:modules/merges/tests/integration/services/merges/worked-example.integration.spec.js#writes
      one alias per deleted id, each naming the survivor
    category: invariant
    execution_sources:
      - >-
        services-crm:modules/merges/tests/integration/services/merges/worked-example.integration.spec.js#writes
        one alias per deleted id, each naming the survivor
      - >-
        services-crm:modules/merges/tests/integration/services/merges/worked-example.integration.spec.js#names
        the merge that wrote each alias
      - >-
        services-crm:modules/merges/tests/integration/db/merged-record-aliases.table.integration.spec.js#takes
        the merged record’s number, which a lookup by number resolves through
      - >-
        services-crm:modules/merges/tests/integration/db/merged-record-aliases.table.integration.spec.js#refuses
        a second alias of the same merged id, so following one is never a choice
      - >-
        services-crm:modules/merges/tests/integration/services/persistence/merged-record-aliases.integration.spec.js#records
        the aliases in the transaction the caller opened, so they commit with
        the merge or not at all
  - id: ATS-CRM-DQ-018-02
    title: Alias chains resolve directly to the final survivor
    level: api
    proves:
      - BR-CAP-CRM-DQ-018-02
    preconditions: Merge a first record into a second and then the second into a third.
    steps: Write the later aliases.
    expected: Both old identities point to the third survivor.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-181
    provenance: test
    source: >-
      services-crm:modules/merges/tests/integration/services/persistence/merged-record-aliases.integration.spec.js#answers
      the alias it repointed, which is A’s
    category: transition
    execution_sources:
      - >-
        services-crm:modules/merges/tests/integration/services/persistence/merged-record-aliases.integration.spec.js#answers
        the alias it repointed, which is A’s
      - >-
        services-crm:modules/merges/tests/integration/services/persistence/merged-record-aliases.integration.spec.js#leaves
        B naming C
      - >-
        services-crm:modules/merges/tests/integration/services/persistence/merged-record-aliases.integration.spec.js#leaves
        C holding both aliases, so the survivor can say what it is made of
  - id: ATS-CRM-DQ-018-03
    title: Absorbed identities cannot be recreated
    level: api
    proves:
      - BR-CAP-CRM-DQ-018-03
    preconditions: Prepare contact and organization aliases.
    steps: Create records under their absorbed identities and under fresh ones.
    expected: >-
      Absorbed identities fail for their own type while fresh identities
      succeed.
    negative: true
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-181
    provenance: test
    source: >-
      services-crm:modules/merges/tests/integration/db/merged-id-reuse.integration.spec.js#refuses
      a contact under it, naming the id and what became of it
    category: invariant
    execution_sources:
      - >-
        services-crm:modules/merges/tests/integration/db/merged-id-reuse.integration.spec.js#refuses
        a contact under it, naming the id and what became of it
      - >-
        services-crm:modules/merges/tests/integration/db/merged-id-reuse.integration.spec.js#refuses
        the contact a client asks to create under it, which is the path a chosen
        id arrives by
      - >-
        services-crm:modules/merges/tests/integration/db/merged-id-reuse.integration.spec.js#takes
        a contact id nothing was merged under, so the refusals below are the
        guard’s doing
      - >-
        services-crm:modules/merges/tests/integration/db/merged-record-aliases.table.integration.spec.js#takes
        the same id as an alias of another object type, because the two are
        different records
  - id: ATS-CRM-DQ-018-04
    title: Alias lookup distinguishes absorbed and unused identities
    level: api
    proves:
      - BR-CAP-CRM-DQ-018-04
    preconditions: A merge has completed.
    steps: Resolve an absorbed identity and an identity never merged.
    expected: 'The first returns survivor, merge and time and the second is not found.'
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-183
    provenance: test
    source: >-
      services-crm:modules/merges/tests/e2e/merges.e2e.spec.js#says where an id
      the merge took away went, and through which merge
    category: rule
    execution_sources:
      - >-
        services-crm:modules/merges/tests/e2e/merges.e2e.spec.js#says where an
        id the merge took away went, and through which merge
      - >-
        services-crm:modules/merges/tests/e2e/merges.e2e.spec.js#answers 404
        from the alias route for a record no merge took away
  - id: ATS-CRM-DQ-018-05
    title: Workspace isolation applies to aliases
    level: api
    proves:
      - BR-CAP-CRM-DQ-018-05
    preconditions: An identity was absorbed in another workspace.
    steps: Read it locally and try writing an alias into that workspace.
    expected: Local lookup returns not found and the foreign write is rejected.
    negative: true
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-183
      - TST-CRM-DQ-181
    provenance: test
    source: >-
      services-crm:modules/merges/tests/e2e/merged-records.e2e.spec.js#answers
      404 in this tenant for an id merged away in another, whose merge is not
      ours to disclose
    category: boundary
    execution_sources:
      - >-
        services-crm:modules/merges/tests/e2e/merged-records.e2e.spec.js#answers
        404 in this tenant for an id merged away in another, whose merge is not
        ours to disclose
      - >-
        services-crm:modules/merges/tests/integration/db/merged-record-aliases.table.integration.spec.js#may
        not append an alias to another tenant, the policy refusing the statement
  - id: ATS-CRM-DQ-018-06
    title: Numbers and origins retrieve their aliases
    level: api
    proves:
      - BR-CAP-CRM-DQ-018-06
    preconditions: Prepare aliases with original numbers and source pairs.
    steps: Look up valid and unknown numbers and source pairs.
    expected: >-
      Valid lookups return their alias; unknown numbers and mismatched origin
      services return none.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-181
    provenance: test
    source: >-
      services-crm:modules/merges/tests/integration/services/persistence/merged-record-aliases.queries.integration.spec.js#answers
      the alias of the record that had that number, whole
    category: rule
    execution_sources:
      - >-
        services-crm:modules/merges/tests/integration/services/persistence/merged-record-aliases.queries.integration.spec.js#answers
        the alias of the record that had that number, whole
      - >-
        services-crm:modules/merges/tests/integration/services/persistence/merged-record-aliases.queries.integration.spec.js#answers
        nothing for a number no merged record had
      - >-
        services-crm:modules/merges/tests/integration/services/persistence/merged-record-aliases.queries.integration.spec.js#answers
        the most recently merged record that carried the pair, whose survivor
        holds the data now
  - id: ATS-CRM-DQ-018-07
    title: Alias mutation is limited to survivor redirection
    level: api
    proves:
      - BR-CAP-CRM-DQ-018-07
    preconditions: Prepare an existing alias.
    steps: >-
      As the application, change identity, delete, truncate and redirect its
      survivor.
    expected: Only survivor redirection succeeds.
    negative: true
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-181
    provenance: test
    source: >-
      services-crm:modules/merges/tests/integration/db/merged-record-aliases.table.integration.spec.js#repoints
      the survivor, which chain compression does when a survivor is itself
      merged away
    category: invariant
    execution_sources:
      - >-
        services-crm:modules/merges/tests/integration/db/merged-record-aliases.table.integration.spec.js#repoints
        the survivor, which chain compression does when a survivor is itself
        merged away
      - >-
        services-crm:modules/merges/tests/integration/db/merged-record-aliases.table.integration.spec.js#may
        not rewrite the id that was merged away, which is the whole of what the
        table records
      - >-
        services-crm:modules/merges/tests/integration/db/merged-record-aliases.table.integration.spec.js#may
        not erase an alias, which would make a merged id answerable and reusable
        again
  - id: ATS-CRM-DQ-018-08
    title: Stale console entry points resolve or report failure
    level: browser
    proves:
      - BR-CAP-CRM-DQ-018-08
    preconditions: >-
      Retain explorer, recent, bookmark, search and saved-view links to an
      absorbed member.
    steps: Open each link.
    expected: >-
      Each reaches the survivor with an explanation or reports its failure
      accurately.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-176
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0267.spec.ts#CRM-ACC-0267
    category: interaction
    execution_sources:
      - >-
        react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0267.spec.ts#CRM-ACC-0267
      - >-
        react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0261.spec.ts#CRM-ACC-0261
      - >-
        react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0268.spec.ts#CRM-ACC-0268
  - id: ATS-CRM-DQ-018-09
    title: >-
      Observe live record becoming absorbed after a successful merge removes
      this participant
    category: transition
    level: api
    proves:
      - BR-CAP-CRM-DQ-018-01
    transition:
      model: STATE-CRM-DQ-006
      index: 1
      from: live record
      to: absorbed
      guard: The alias is written in the committing merge transaction.
      side_effects:
        - >-
          retain destination and merge attribution with prior integration
          identity
        - deny later identity reuse
    preconditions: >-
      Arrange live record standing with the transition guard satisfied: The
      alias is written in the committing merge transaction.
    steps: A successful merge removes this participant.
    expected: >-
      Read the absorbed standing and inspect the associated changes: retain
      destination and merge attribution with prior integration identity; deny
      later identity reuse.
    negative: false
    data_needs: >-
      Fixtures for live record, the guard and the affected records; a fixed
      clock for time-dependent changes.
    source: >-
      services-crm:modules/merges/tests/integration/db/merged-record-aliases.table.integration.spec.js#refuses
      a second alias of the same merged id, so following one is never a choice
    design_sources:
      - STATE-CRM-DQ-006
    note: >-
      The design supplies this transition obligation. A runtime binding requires
      assertions for its guard, destination and associated writes in one
      sequence.
    bound_to: []
    provenance: proposed
    execution_sources: []
  - id: ATS-CRM-DQ-018-10
    title: >-
      Observe absorbed becoming absorbed after a later merge absorbs the
      existing survivor
    category: transition
    level: api
    proves:
      - BR-CAP-CRM-DQ-018-02
    transition:
      model: STATE-CRM-DQ-006
      index: 2
      from: absorbed
      to: absorbed
      guard: The later merge transaction applies alias compression.
      side_effects:
        - redirect the alias while retaining its original merge attribution
    preconditions: >-
      Arrange absorbed standing with the transition guard satisfied: The later
      merge transaction applies alias compression.
    steps: A later merge absorbs the existing survivor.
    expected: >-
      Read the absorbed standing and inspect the associated changes: redirect
      the alias while retaining its original merge attribution.
    negative: false
    data_needs: >-
      Fixtures for absorbed, the guard and the affected records; a fixed clock
      for time-dependent changes.
    source: >-
      services-crm:modules/merges/tests/integration/services/persistence/merged-record-aliases.integration.spec.js#leaves
      C holding both aliases, so the survivor can say what it is made of
    design_sources:
      - STATE-CRM-DQ-006
    note: >-
      The design supplies this transition obligation. A runtime binding requires
      assertions for its guard, destination and associated writes in one
      sequence.
    bound_to: []
    provenance: proposed
    execution_sources: []
  - id: ATS-CRM-DQ-018-11
    title: >-
      Observe absorbed becoming dangling after ordinary deletion removes the
      survivor
    category: transition
    level: api
    proves:
      - BR-CAP-CRM-DQ-018-09
    transition:
      model: STATE-CRM-DQ-006
      index: 3
      from: absorbed
      to: dangling
      guard: No implemented destination-liveness guard prevents this.
      side_effects:
        - retain a pointer to a missing destination
    preconditions: >-
      Arrange absorbed standing with the transition guard satisfied: No
      implemented destination-liveness guard prevents this.
    steps: Ordinary deletion removes the survivor.
    expected: >-
      Read the dangling standing and inspect the associated changes: retain a
      pointer to a missing destination.
    negative: true
    data_needs: >-
      Fixtures for absorbed, the guard and the affected records; a fixed clock
      for time-dependent changes.
    source: FND-CRM-DQ-022
    design_sources:
      - STATE-CRM-DQ-006
    note: >-
      The design supplies this transition obligation. A runtime binding requires
      assertions for its guard, destination and associated writes in one
      sequence.
    bound_to: []
    provenance: proposed
    defect_observation: true
    finding: FND-CRM-DQ-022
    intent_alignment: >-
      A dangling destination demonstrates the known violation of the proposed
      live-destination requirement.
    execution_sources: []
  - id: ATS-CRM-DQ-018-12
    title: >-
      Observe absorbed becoming purged after workspace lifecycle removes
      absorbed identity history
    category: transition
    level: api
    proves:
      - BR-CAP-CRM-DQ-018-07
    transition:
      model: STATE-CRM-DQ-006
      index: 4
      from: absorbed
      to: purged
      guard: Privileged purge capability performs the deletion.
      side_effects:
        - remove aliases before their merge history
    preconditions: >-
      Arrange absorbed standing with the transition guard satisfied: Privileged
      purge capability performs the deletion.
    steps: Workspace lifecycle removes absorbed identity history.
    expected: >-
      Read the purged standing and inspect the associated changes: remove
      aliases before their merge history.
    negative: false
    data_needs: >-
      Fixtures for absorbed, the guard and the affected records; a fixed clock
      for time-dependent changes.
    source: >-
      services-crm:modules/merges/tests/integration/db/merged-record-aliases.table.integration.spec.js#may
      not erase an alias, which would make a merged id answerable and reusable
      again
    design_sources:
      - STATE-CRM-DQ-006
    note: >-
      The design supplies this transition obligation. A runtime binding requires
      assertions for its guard, destination and associated writes in one
      sequence.
    bound_to: []
    provenance: proposed
    execution_sources: []
  - id: ATS-CRM-DQ-018-13
    title: >-
      Observe dangling becoming purged after workspace lifecycle removes a
      dangling alias
    category: transition
    level: api
    proves:
      - BR-CAP-CRM-DQ-018-07
    transition:
      model: STATE-CRM-DQ-006
      index: 5
      from: dangling
      to: purged
      guard: Deletion requires the privileged workspace capability.
      side_effects:
        - remove the retained pointer
    preconditions: >-
      Arrange dangling standing with the transition guard satisfied: Deletion
      requires the privileged workspace capability.
    steps: Workspace lifecycle removes a dangling alias.
    expected: >-
      Read the purged standing and inspect the associated changes: remove the
      retained pointer.
    negative: false
    data_needs: >-
      Fixtures for dangling, the guard and the affected records; a fixed clock
      for time-dependent changes.
    source: >-
      services-crm:modules/merges/tests/integration/db/merged-record-aliases.table.integration.spec.js#may
      not erase an alias, which would make a merged id answerable and reusable
      again
    design_sources:
      - STATE-CRM-DQ-006
    note: >-
      The design supplies this transition obligation. A runtime binding requires
      assertions for its guard, destination and associated writes in one
      sequence.
    bound_to: []
    provenance: proposed
    execution_sources: []
  - id: ATS-CRM-DQ-018-14
    title: An absorbed identity cannot receive a second alias
    category: invariant
    level: api
    proves:
      - INV-DOM-CRM-DQ-004-06
    preconditions: A stored alias for one absorbed identity.
    steps: >-
      Attempt a second alias for that same identity in the same workspace and
      record type.
    expected: The duplicate alias is refused.
    negative: false
    data_needs: >-
      Records, versions and caller contexts owned by the run; transaction
      failure injection when the invariant concerns rollback.
    bound_to:
      - TST-CRM-DQ-181
    source: >-
      services-crm:modules/merges/tests/integration/db/merged-record-aliases.table.integration.spec.js#refuses
      a second alias of the same merged id, so following one is never a choice
    design_sources:
      - DOM-CRM-DQ-004
    execution_sources:
      - >-
        services-crm:modules/merges/tests/integration/db/merged-record-aliases.table.integration.spec.js#refuses
        a second alias of the same merged id, so following one is never a choice
    provenance: test
  - id: ATS-CRM-DQ-018-15
    title: A second absorption redirects the oldest alias
    category: invariant
    level: api
    proves:
      - INV-DOM-CRM-DQ-004-07
    preconditions: >-
      A contact absorbed into a survivor that is later absorbed into a third
      contact.
    steps: >-
      Insert the later merge’s aliases and read the final survivor’s incoming
      aliases.
    expected: Both absorbed contacts resolve directly to the third contact.
    negative: false
    data_needs: >-
      Records, versions and caller contexts owned by the run; transaction
      failure injection when the invariant concerns rollback.
    bound_to:
      - TST-CRM-DQ-181
    source: >-
      services-crm:modules/merges/tests/integration/services/persistence/merged-record-aliases.integration.spec.js#leaves
      C holding both aliases, so the survivor can say what it is made of
    design_sources:
      - DOM-CRM-DQ-004
    execution_sources:
      - >-
        services-crm:modules/merges/tests/integration/services/persistence/merged-record-aliases.integration.spec.js#leaves
        C holding both aliases, so the survivor can say what it is made of
    provenance: test
  - id: ATS-CRM-DQ-018-16
    title: Chosen contact identity cannot reuse an absorbed identity
    category: invariant
    level: api
    proves:
      - INV-DOM-CRM-DQ-004-08
    preconditions: A contact identity already recorded as absorbed in this workspace.
    steps: Create another contact explicitly naming that identity.
    expected: Creation is refused without another live contact at the old identity.
    negative: false
    data_needs: >-
      Records, versions and caller contexts owned by the run; transaction
      failure injection when the invariant concerns rollback.
    bound_to:
      - TST-CRM-DQ-181
    source: >-
      services-crm:modules/merges/tests/integration/db/merged-id-reuse.integration.spec.js#refuses
      the contact a client asks to create under it, which is the path a chosen
      id arrives by
    design_sources:
      - DOM-CRM-DQ-004
    execution_sources:
      - >-
        services-crm:modules/merges/tests/integration/db/merged-id-reuse.integration.spec.js#refuses
        the contact a client asks to create under it, which is the path a chosen
        id arrives by
    provenance: test
  - id: ATS-CRM-DQ-018-17
    title: An application cannot erase an alias
    category: invariant
    level: api
    proves:
      - INV-DOM-CRM-DQ-004-09
    preconditions: A retained alias and the ordinary application database role.
    steps: Attempt deletion through that role.
    expected: The alias remains and the operation is refused.
    negative: false
    data_needs: >-
      Records, versions and caller contexts owned by the run; transaction
      failure injection when the invariant concerns rollback.
    bound_to:
      - TST-CRM-DQ-181
    source: >-
      services-crm:modules/merges/tests/integration/db/merged-record-aliases.table.integration.spec.js#may
      not erase an alias, which would make a merged id answerable and reusable
      again
    design_sources:
      - DOM-CRM-DQ-004
    execution_sources:
      - >-
        services-crm:modules/merges/tests/integration/db/merged-record-aliases.table.integration.spec.js#may
        not erase an alias, which would make a merged id answerable and reusable
        again
    provenance: test
  - id: ATS-CRM-DQ-018-18
    title: Old identities reach readable records and retained history
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-DQ-018-01
      - BR-CAP-CRM-DQ-018-02
      - BR-CAP-CRM-DQ-018-03
      - BR-CAP-CRM-DQ-018-04
      - BR-CAP-CRM-DQ-018-05
      - BR-CAP-CRM-DQ-018-06
      - BR-CAP-CRM-DQ-018-07
      - BR-CAP-CRM-DQ-018-08
    exercises:
      - CAP-CRM-DQ-018
      - CAP-CRM-ENT-003
      - CAP-CRM-ENT-014
      - CAP-CRM-ENT-016
    workflow_sources:
      - WF-CRM-DQ-006
      - WF-CRM-DQ-009
    preconditions: >-
      Run-owned contact and organization records, the relevant staff permissions
      and the related state described by the sequence.
    steps: >-
      Merge a contact twice, open the oldest link, query by its former number
      and inspect its lineage under record-read authority.
    expected: >-
      Each identity resolves as specified and the reader sees the corresponding
      retained history.
    negative: false
    data_needs: >-
      An isolated workspace with related records and fixed timestamps; owned
      participant failure injection where requested.
    source: >-
      CAP-CRM-DQ-018; CAP-CRM-ENT-003; CAP-CRM-ENT-014; CAP-CRM-ENT-016;
      WF-CRM-DQ-006; WF-CRM-DQ-009
    note: >-
      This cumulative seam scenario remains proposed until one executable
      sequence establishes all of its outcomes.
    bound_to: []
    provenance: proposed
    workflow_coverage_note: >-
      The workflows identify the handoffs under review. Separate assertions
      leave recovery and failure ordering unproved; the capability coverage
      finding records that limit.
    execution_sources: []
evidence:
  - repository: services-crm
    source_sha: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
    paths:
      - modules/merges/tests/e2e/merged-records.e2e.spec.js
      - modules/merges/tests/e2e/merges.e2e.spec.js
      - modules/merges/tests/integration/db/merged-id-reuse.integration.spec.js
      - >-
        modules/merges/tests/integration/db/merged-record-aliases.table.integration.spec.js
      - >-
        modules/merges/tests/integration/services/merges/worked-example.integration.spec.js
      - >-
        modules/merges/tests/integration/services/persistence/merged-record-aliases.integration.spec.js
      - >-
        modules/merges/tests/integration/services/persistence/merged-record-aliases.queries.integration.spec.js
    note: >-
      Bindings identify authored proof; empty bindings remain proposed and
      findings record known limitations.
  - repository: react-console
    source_sha: baf6dae382d6f41dce976c7f848667ccc37e076f
    paths:
      - acceptance/crm/playwright/journeys/merging/CRM-ACC-0261.spec.ts
      - acceptance/crm/playwright/journeys/merging/CRM-ACC-0267.spec.ts
      - acceptance/crm/playwright/journeys/merging/CRM-ACC-0268.spec.ts
    note: >-
      Bindings identify authored proof; empty bindings remain proposed and
      findings record known limitations.
coverage:
  rule: covered
  transition: covered
  validation: 'gap: FND-CRM-DQ-069'
  permission: 'gap: FND-CRM-DQ-069'
  edge: 'gap: FND-CRM-DQ-069'
  failure: 'gap: FND-CRM-DQ-069'
  boundary: covered
  concurrency: 'gap: FND-CRM-DQ-069'
  invariant: covered
  interaction: covered
coverage_notes:
  validation: >-
    No complete scenario currently isolates this category; the finding lists the
    remaining proof obligation.
  permission: >-
    No complete scenario currently isolates this category; the finding lists the
    remaining proof obligation.
  edge: >-
    No complete scenario currently isolates this category; the finding lists the
    remaining proof obligation.
  failure: >-
    No complete scenario currently isolates this category; the finding lists the
    remaining proof obligation.
  concurrency: >-
    No complete scenario currently isolates this category; the finding lists the
    remaining proof obligation.
permission_coverage:
  - key: crm.merges.read
    scenario_ids: []
    finding: FND-CRM-DQ-069
proof_matrix:
  - rule: BR-CAP-CRM-DQ-018-01
    scenarios:
      - ATS-CRM-DQ-018-01
      - ATS-CRM-DQ-018-09
      - ATS-CRM-DQ-018-18
  - rule: BR-CAP-CRM-DQ-018-02
    scenarios:
      - ATS-CRM-DQ-018-02
      - ATS-CRM-DQ-018-10
      - ATS-CRM-DQ-018-18
  - rule: BR-CAP-CRM-DQ-018-03
    scenarios:
      - ATS-CRM-DQ-018-03
      - ATS-CRM-DQ-018-18
  - rule: BR-CAP-CRM-DQ-018-04
    scenarios:
      - ATS-CRM-DQ-018-04
      - ATS-CRM-DQ-018-18
  - rule: BR-CAP-CRM-DQ-018-05
    scenarios:
      - ATS-CRM-DQ-018-05
      - ATS-CRM-DQ-018-18
  - rule: BR-CAP-CRM-DQ-018-06
    scenarios:
      - ATS-CRM-DQ-018-06
      - ATS-CRM-DQ-018-18
  - rule: BR-CAP-CRM-DQ-018-07
    scenarios:
      - ATS-CRM-DQ-018-07
      - ATS-CRM-DQ-018-12
      - ATS-CRM-DQ-018-13
      - ATS-CRM-DQ-018-18
  - rule: BR-CAP-CRM-DQ-018-08
    scenarios:
      - ATS-CRM-DQ-018-08
      - ATS-CRM-DQ-018-18
  - rule: BR-CAP-CRM-DQ-018-09
    scenarios:
      - ATS-CRM-DQ-018-11
interaction_coverage:
  related:
    - CAP-CRM-ENT-003
    - CAP-CRM-ENT-014
    - CAP-CRM-ENT-016
  workflow_sources:
    - WF-CRM-DQ-006
    - WF-CRM-DQ-009
  scenarios:
    - ATS-CRM-DQ-018-08
    - ATS-CRM-DQ-018-18
---

# Resolve identities absorbed by a merge: Capability Test Specification

## Coverage

The rule matrix names the authored checks. A covered category means that a scenario exists; it does not report a passing execution. The coverage notes and findings identify missing checks, while execution sources retain the exact assertions inspected.

| Required Rule | Scenarios |
|---|---|
| `BR-CAP-CRM-DQ-018-01` | `ATS-CRM-DQ-018-01`, `ATS-CRM-DQ-018-09`, `ATS-CRM-DQ-018-18` |
| `BR-CAP-CRM-DQ-018-02` | `ATS-CRM-DQ-018-02`, `ATS-CRM-DQ-018-10`, `ATS-CRM-DQ-018-18` |
| `BR-CAP-CRM-DQ-018-03` | `ATS-CRM-DQ-018-03`, `ATS-CRM-DQ-018-18` |
| `BR-CAP-CRM-DQ-018-04` | `ATS-CRM-DQ-018-04`, `ATS-CRM-DQ-018-18` |
| `BR-CAP-CRM-DQ-018-05` | `ATS-CRM-DQ-018-05`, `ATS-CRM-DQ-018-18` |
| `BR-CAP-CRM-DQ-018-06` | `ATS-CRM-DQ-018-06`, `ATS-CRM-DQ-018-18` |
| `BR-CAP-CRM-DQ-018-07` | `ATS-CRM-DQ-018-07`, `ATS-CRM-DQ-018-12`, `ATS-CRM-DQ-018-13`, `ATS-CRM-DQ-018-18` |
| `BR-CAP-CRM-DQ-018-08` | `ATS-CRM-DQ-018-08`, `ATS-CRM-DQ-018-18` |
| `BR-CAP-CRM-DQ-018-09` | `ATS-CRM-DQ-018-11` |

## Interactions With Related Capabilities

Open each link. Merge a contact twice, open the oldest link, query by its former number and inspect its lineage under record-read authority.

These sequences test the handoffs named in the interaction coverage record. A proposed sequence remains unbound until an executable run checks its combined outcome; component assertions alone leave that obligation open.
