---
id: ATS-CRM-ENT-006
scope: CAP-CRM-ENT-006
product_area: crm
module: entities
revision: 1
status: proposed
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-CRM-ENT-006-01
    title: a link names the contact's affiliation and that organization's record
    level: api
    proves:
      - BR-CAP-CRM-ENT-006-02
    preconditions: Prepare a contact tied to Acme and Globex.
    steps: >-
      Link the work address through the Acme affiliation to a Globex address; to
      an Acme type Acme lacks.
    expected: 400 naming the record; 400 naming the item.
    negative: true
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-787
      - TST-CRM-ENT-786
    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
    category: validation
    action_evidence:
      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
    assertion_evidence:
      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
    test_anchors:
      - >-
        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/e2e/contact-information-sources.e2e.spec.js#refuses
        400 a type Acme has no record of, naming the item
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-006-02
    title: No link through a affiliation not in effect
    level: api
    proves:
      - BR-CAP-CRM-ENT-006-03
    preconditions: Prepare an ended and an upcoming affiliation.
    steps: Make a new link through each.
    expected: 400 naming the path each time.
    negative: true
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-787
    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
    category: validation
    action_evidence:
      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
    assertion_evidence:
      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
    test_anchors:
      - >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#refuses
        a new link through an ended affiliation, naming the path
      - >-
        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
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-006-03
    title: a linked row rejects a value of its own
    level: browser
    proves:
      - BR-CAP-CRM-ENT-006-04
      - INV-DOM-CRM-ENT-001-10
    preconditions: Prepare a linked work address.
    steps: Send it with another city; with extra spaces; with different case.
    expected: Rejected; accepted; rejected.
    negative: true
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-787
      - TST-CRM-ENT-776
    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)
    category: validation
    action_evidence:
      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)
    assertion_evidence:
      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)
    test_anchors:
      - >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#refuses
        a value sent for a linked row that differs from the organization’s,
        naming the field
      - >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#takes
        a value that differs from the organization’s only by spaces as the same
        value (A19)
      - >-
        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)
      - >-
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0204.spec.ts#CRM-ACC-0204
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-006-04
    title: >-
      a link resolves while the affiliation is in effect and the contact is not
      rewritten
    level: browser
    proves:
      - BR-CAP-CRM-ENT-006-05
    preconditions: Prepare a linked work address.
    steps: Edit the organization's address; end the affiliation.
    expected: >-
      The new value with the contact's version unmodified; then unresolved with
      the link preserved.
    negative: false
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-787
      - TST-CRM-ENT-776
    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
    category: interaction
    action_evidence:
      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
    assertion_evidence:
      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
    test_anchors:
      - >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#changes
        the contact’s resolved work address
      - >-
        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#stops
        resolving the value: the row reads as linked, unresolved, with no value
      - >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#keeps
        the link through the ended affiliation: nothing is re-pointed
      - >-
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0191.spec.ts#CRM-ACC-0191
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-006-05
    title: a removed source leaves a disconnected row
    level: browser
    proves:
      - BR-CAP-CRM-ENT-006-06
    preconditions: Prepare a work address and phone linked to an organization.
    steps: The organization removes both records.
    expected: >-
      Each row disconnected with its last value, provenance and
      needs_verification; contact version moved.
    negative: false
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-786
      - TST-CRM-ENT-787
      - TST-CRM-ENT-775
    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)
    category: transition
    action_evidence:
      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)
    assertion_evidence:
      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)
    test_anchors:
      - >-
        services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#turns
        the work address into a disconnected row, not a copy
      - >-
        services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#says
        where it came from, when and why the source went
      - >-
        services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#says
        it needs verification and that its source is disconnected, so no client
        draws it as synced
      - >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#stamps
        the contact modified once for each of its rows that became disconnected
        (the trigger runs per removed record)
      - >-
        react-console:acceptance/crm/playwright/journeys/organizations/CRM-ACC-0148.spec.ts#CRM-ACC-0148
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-006-06
    title: a client cannot disconnect a row
    level: api
    proves:
      - BR-CAP-CRM-ENT-006-07
      - INV-DOM-CRM-ENT-001-11
    preconditions: Prepare a disconnected row.
    steps: Send it back as read; ask for another row to be disconnected.
    expected: Accepted with the server's provenance; 400 naming source_mode.
    negative: true
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-786
    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
    category: validation
    action_evidence:
      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
    assertion_evidence:
      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
    test_anchors:
      - >-
        services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#takes
        the record read sent back as it is, the provenance staying the server’s
      - >-
        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
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-006-07
    title: 'Verify, relink and remove a disconnected row'
    level: api
    proves:
      - BR-CAP-CRM-ENT-006-08
    preconditions: Prepare a disconnected address and phone.
    steps: >-
      Verify one; relink one through a current affiliation; remove one; repeat a
      verify; send a stale or missing version.
    expected: Owned with provenance cleared; linked again; deleted; 409; 409 and 400.
    negative: true
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-786
    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
    category: transition
    action_evidence:
      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
    assertion_evidence:
      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
    test_anchors:
      - >-
        services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#makes
        it the contact’s own, with the value unchanged
      - >-
        services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#links
        it to the organization’s address through the affiliation
      - >-
        services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#refuses
        a request naming both the record and its type, or neither
      - >-
        services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#deletes
        the row
      - >-
        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/e2e/contacts-disconnected.e2e.spec.js#refuses
        a stale version, 409
      - >-
        services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#refuses
        a request with no version, 400, naming it
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-006-08
    title: Make Independent Copy
    level: browser
    proves:
      - BR-CAP-CRM-ENT-006-09
    preconditions: Prepare a linked row.
    steps: Save it as copied with no value of its own; then the organization moves.
    expected: >-
      The organization's value with copied_from and copied_at; unmodified after
      the move.
    negative: false
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-787
      - TST-CRM-ENT-776
    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
    category: transition
    action_evidence:
      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
    assertion_evidence:
      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
    test_anchors:
      - >-
        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#keeps
        the copied value as it was copied, the organization having moved since
      - >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#records
        where the copy came from and when, stamped by the save
      - >-
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0203.spec.ts#CRM-ACC-0203
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-006-09
    title: An affiliation that supplies a link is removed only with its rows handled
    level: browser
    proves:
      - BR-CAP-CRM-ENT-006-10
      - INV-DOM-CRM-ENT-003-12
    preconditions: Prepare a affiliation supplying a linked address and phone.
    steps: >-
      Remove the affiliation alone; remove it while copying one row and removing
      the other.
    expected: Rejected; accepted.
    negative: true
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-787
      - TST-CRM-ENT-776
    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
    category: invariant
    action_evidence:
      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
    assertion_evidence:
      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
    test_anchors:
      - >-
        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#takes
        a save that removes the affiliation and, in the same save, copies one
        row and removes the other
      - >-
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0178.spec.ts#CRM-ACC-0178
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-006-10
    title: Link When Added is honoured and never overwrites
    level: browser
    proves:
      - BR-CAP-CRM-ENT-006-11
    preconditions: Prepare an Employer type with address and phone mappings.
    steps: >-
      Create a affiliation with no choice; with an empty choice; with a choice
      naming a mapping the type lacks; for a contact with its own work address.
    expected: Every default; nothing; rejected; own address untouched.
    negative: true
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-787
      - TST-CRM-ENT-776
    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
    category: edge
    action_evidence:
      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
    assertion_evidence:
      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
    test_anchors:
      - >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#links
        every default when the choice is absent
      - >-
        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/persistence/contact-information-sources.integration.spec.js#refuses
        a choice that names a mapping the type does not have
      - >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#never
        overwrites a work address the contact already has
      - >-
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0185.spec.ts#CRM-ACC-0185
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-006-11
    title: >-
      Defaults only through affiliations in effect, on the start day, never
      rewritten
    level: browser
    proves:
      - BR-CAP-CRM-ENT-006-12
    preconditions: Prepare an upcoming and an ended affiliation of a type with mappings.
    steps: >-
      Save; run the reconciliation on the eve and on the start day; re-apply on
      the ended affiliation; change the type's mappings.
    expected: >-
      Nothing at save or eve; links on the day; skipped; no existing contact
      changed.
    negative: false
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-787
      - TST-CRM-ENT-776
    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
    category: interaction
    action_evidence:
      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
    assertion_evidence:
      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
    test_anchors:
      - >-
        services-crm:modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.follow-ups.integration.spec.js#links
        nothing at the save of an upcoming affiliation
      - >-
        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
      - >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#skips
        an ended affiliation on re-apply, without refusing
      - >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#applies
        the type’s mappings when the command names an affiliation of it
      - >-
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0190.spec.ts#CRM-ACC-0190
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-006-12
    title: Reject a stale repair after another editor resolves the detail
    category: concurrency
    level: api
    proves:
      - BR-CAP-CRM-ENT-006-08
      - BR-CAP-CRM-ENT-004-01
    preconditions: Two editors read the same disconnected address and person version.
    steps: >-
      The first keeps the retained value; the second relinks using the version
      it originally read.
    expected: The second repair conflicts and preserves the first editor’s owned value.
    negative: true
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#is
      refused 409 on a row that is no longer disconnected
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#is
        refused 409 on a row that is no longer disconnected
    assertion_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#is
        refused 409 on a row that is no longer disconnected
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-006-13
    title: Source removal leaves a person’s detail for review
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-ENT-005-10
      - BR-CAP-CRM-ENT-006-06
    preconditions: A person’s work address is linked to an organization address.
    steps: Remove the source address and read the person’s address and version.
    expected: >-
      The person retains the last value as disconnected information needing
      verification and its version advances.
    negative: false
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:docs/milestones/CRM-M1-contacts-and-organizations.plan.md#A9;
      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)
    exercises:
      - CAP-CRM-ENT-005
      - CAP-CRM-ENT-006
    workflows:
      - WF-CRM-ENT-001
      - WF-CRM-ENT-002
      - WF-CRM-ENT-003
      - WF-CRM-ENT-010
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        services-crm:docs/milestones/CRM-M1-contacts-and-organizations.plan.md#A9;
        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)
    assertion_evidence:
      provenance: proposed
      source: >-
        services-crm:docs/milestones/CRM-M1-contacts-and-organizations.plan.md#A9;
        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)
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-006-14
    title: Remove a relationship and resolve its dependent details together
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-ENT-006-10
      - BR-CAP-CRM-ENT-009-02
    preconditions: A person has one affiliation supplying a linked address and phone.
    steps: >-
      Try removing only the affiliation; then remove it while copying the
      address and removing the phone.
    expected: >-
      The incomplete removal changes nothing; the complete save removes the tie
      and handles both dependent details.
    negative: false
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to: []
    provenance: proposed
    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;
      react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0202.spec.ts#CRM-ACC-0202
    exercises:
      - CAP-CRM-ENT-006
      - CAP-CRM-ENT-009
    workflows:
      - WF-CRM-ENT-001
      - WF-CRM-ENT-002
    test_anchors: []
    action_evidence:
      provenance: proposed
      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;
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0202.spec.ts#CRM-ACC-0202
    assertion_evidence:
      provenance: proposed
      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;
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0202.spec.ts#CRM-ACC-0202
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-006-15
    title: Apply a future tie’s selected contact-point defaults
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-ENT-006-12
      - BR-CAP-CRM-ENT-010-05
    preconditions: >-
      A future affiliation has pending selected mappings and empty destination
      purposes.
    steps: >-
      Run a date pass before its start, then on its local start day; read the
      person after each pass.
    expected: >-
      The early pass makes no links; the due pass fills the selected
      destinations once.
    negative: false
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to: []
    provenance: proposed
    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;
      services-crm:modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.integration.spec.js#takes
      the organization out of compliance the next morning, with no save of the
      contact
    exercises:
      - CAP-CRM-ENT-006
      - CAP-CRM-ENT-010
    workflows:
      - WF-CRM-ENT-002
      - WF-CRM-ENT-006
    test_anchors: []
    action_evidence:
      provenance: proposed
      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;
        services-crm:modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.integration.spec.js#takes
        the organization out of compliance the next morning, with no save of the
        contact
    assertion_evidence:
      provenance: proposed
      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;
        services-crm:modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.integration.spec.js#takes
        the organization out of compliance the next morning, with no save of the
        contact
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-006-16
    title: A default mapping supplies a newly effective tie
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-ENT-006-11
      - BR-CAP-CRM-ENT-017-07
    preconditions: >-
      An affiliation type maps an organization address purpose to an empty
      person address purpose.
    steps: >-
      Add a current affiliation of that type with the mapping selected and read
      the saved person.
    expected: >-
      The new link uses the configured source and destination while preexisting
      personal values remain.
    negative: false
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to: []
    provenance: proposed
    source: >-
      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/persistence/affiliation-types.integration.spec.js#keeps
      the mappings, as an omitted collection means unchanged
    exercises:
      - CAP-CRM-ENT-006
      - CAP-CRM-ENT-017
    workflows: []
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        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/persistence/affiliation-types.integration.spec.js#keeps
        the mappings, as an omitted collection means unchanged
    assertion_evidence:
      provenance: proposed
      source: >-
        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/persistence/affiliation-types.integration.spec.js#keeps
        the mappings, as an omitted collection means unchanged
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-006-17
    title: Exercise every declared authority independently
    category: permission
    level: api
    proves:
      - BR-CAP-CRM-ENT-003-07
      - BR-CAP-CRM-ENT-003-09
    preconditions: >-
      An eligible record and configuration fixture exist for each operation; the
      caller can reach only the run’s workspace.
    steps: >-
      For each declared permission, execute its matching operation with that
      permission, then without it while retaining the other required grants.
      Read affected records after every refused mutation.
    expected: >-
      The authorized case reaches the operation; the missing-grant case is
      refused and preserves saved data. Record access alone does not authorize
      the other declared actions.
    negative: true
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:aws/crm.service.ts:ApplicationPermissions;
      services-crm:modules/entities/aws/api/entities.routes.ts
    permission_keys:
      - crm.contacts.update
      - crm.organizations.update
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        services-crm:aws/crm.service.ts:ApplicationPermissions;
        services-crm:modules/entities/aws/api/entities.routes.ts
    assertion_evidence:
      provenance: proposed
      source: >-
        services-crm:aws/crm.service.ts:ApplicationPermissions;
        services-crm:modules/entities/aws/api/entities.routes.ts
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
evidence:
  - >-
    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/e2e/contact-information-sources.e2e.spec.js#refuses
    400 a type Acme has no record of, naming the item
  - >-
    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 new link through an ended 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#refuses
    a value sent for a linked row that differs from the organization’s, naming
    the field
  - >-
    services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#takes
    a value that differs from the organization’s only by spaces as the same
    value (A19)
  - >-
    react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0204.spec.ts#CRM-ACC-0204
  - >-
    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#changes
    the contact’s resolved work address
  - >-
    services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#stops
    resolving the value: the row reads as linked, unresolved, with no value
  - >-
    services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#keeps
    the link through the ended affiliation: nothing is re-pointed
  - >-
    react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0191.spec.ts#CRM-ACC-0191
  - >-
    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#turns
    the work address into a disconnected row, not a copy
  - >-
    services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#says
    where it came from, when and why the source went
  - >-
    services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#says
    it needs verification and that its source is disconnected, so no client
    draws it as synced
  - >-
    services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#stamps
    the contact modified once for each of its rows that became disconnected (the
    trigger runs per removed record)
  - >-
    react-console:acceptance/crm/playwright/journeys/organizations/CRM-ACC-0148.spec.ts#CRM-ACC-0148
  - >-
    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#takes
    the record read sent back as it is, the provenance staying the server’s
  - >-
    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/e2e/contacts-disconnected.e2e.spec.js#makes
    it the contact’s own, with the value unchanged
  - >-
    services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#links
    it to the organization’s address through the affiliation
  - >-
    services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#refuses
    a request naming both the record and its type, or neither
  - >-
    services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#deletes
    the row
  - >-
    services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#refuses
    a stale version, 409
  - >-
    services-crm:modules/entities/tests/e2e/contacts-disconnected.e2e.spec.js#refuses
    a request with no version, 400, naming it
  - >-
    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#keeps
    the copied value as it was copied, the organization having moved since
  - >-
    services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#records
    where the copy came from and when, stamped by the save
  - >-
    react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0203.spec.ts#CRM-ACC-0203
  - >-
    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#takes
    a save that removes the affiliation and, in the same save, copies one row
    and removes the other
  - >-
    react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0178.spec.ts#CRM-ACC-0178
  - >-
    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/persistence/contact-information-sources.integration.spec.js#links
    every default when the choice is absent
  - >-
    services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#refuses
    a choice that names a mapping the type does not have
  - >-
    services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#never
    overwrites a work address the contact already has
  - >-
    react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0185.spec.ts#CRM-ACC-0185
  - >-
    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
  - >-
    services-crm:modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.follow-ups.integration.spec.js#links
    nothing at the save of an upcoming affiliation
  - >-
    services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#skips
    an ended affiliation on re-apply, without refusing
  - >-
    services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#applies
    the type’s mappings when the command names an affiliation of it
  - >-
    react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0190.spec.ts#CRM-ACC-0190
  - >-
    services-crm:docs/milestones/CRM-M1-contacts-and-organizations.plan.md#A9;
    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/integration/services/persistence/contact-information-sources.integration.spec.js#refuses
    a save that removes the affiliation and keeps the rows linked through it;
    react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0202.spec.ts#CRM-ACC-0202
  - >-
    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;
    services-crm:modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.integration.spec.js#takes
    the organization out of compliance the next morning, with no save of the
    contact
  - >-
    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/persistence/affiliation-types.integration.spec.js#keeps
    the mappings, as an omitted collection means unchanged
  - >-
    services-crm:aws/crm.service.ts:ApplicationPermissions;
    services-crm:modules/entities/aws/api/entities.routes.ts
coverage:
  rule: 'gap: FND-CRM-ENT-054'
  transition: covered
  validation: covered
  permission: covered
  edge: covered
  failure: 'gap: FND-CRM-ENT-054'
  boundary: 'gap: FND-CRM-ENT-054'
  concurrency: covered
  invariant: covered
  interaction: covered
previous_approval:
  revision: 1
  approved_by: Andrew
  approved_at: '2026-10-22T00:00:00.000Z'
transition_coverage:
  - state_model: STATE-CRM-ENT-006
    from: owned
    to: linked
    scenarios:
      - ATS-CRM-ENT-006-01
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-006-shared-contact-detail-source.md:transitions
  - state_model: STATE-CRM-ENT-006
    from: linked
    to: copied
    scenarios:
      - ATS-CRM-ENT-006-08
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-006-shared-contact-detail-source.md:transitions
  - state_model: STATE-CRM-ENT-006
    from: linked
    to: linked unresolved
    scenarios:
      - ATS-CRM-ENT-006-04
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-006-shared-contact-detail-source.md:transitions
  - state_model: STATE-CRM-ENT-006
    from: linked
    to: disconnected
    scenarios:
      - ATS-CRM-ENT-006-05
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-006-shared-contact-detail-source.md:transitions
  - state_model: STATE-CRM-ENT-006
    from: disconnected
    to: owned
    scenarios:
      - ATS-CRM-ENT-006-07
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-006-shared-contact-detail-source.md:transitions
  - state_model: STATE-CRM-ENT-006
    from: disconnected
    to: linked
    scenarios:
      - ATS-CRM-ENT-006-07
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-006-shared-contact-detail-source.md:transitions
  - state_model: STATE-CRM-ENT-006
    from: disconnected
    to: removed
    scenarios:
      - ATS-CRM-ENT-006-07
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-006-shared-contact-detail-source.md:transitions
coverage_notes:
  rule:
    reason: >-
      No detailed rule scenario currently specifies this aspect; the coverage
      finding records the required follow-through.
    provenance: unknown
    source: FND-CRM-ENT-054
  failure:
    reason: >-
      No detailed failure scenario currently specifies this aspect; the coverage
      finding records the required follow-through.
    provenance: unknown
    source: FND-CRM-ENT-054
  boundary:
    reason: >-
      No detailed boundary scenario currently specifies this aspect; the
      coverage finding records the required follow-through.
    provenance: unknown
    source: FND-CRM-ENT-054
coverage_findings:
  - FND-CRM-ENT-054
  - FND-CRM-ENT-075
permission_coverage:
  - key: crm.contacts.update
    where_checked: api
    scenario: ATS-CRM-ENT-006-17
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-006-share-an-organization-s-addresses-and-phone-numbers-with-its.md
  - key: crm.organizations.update
    where_checked: api
    scenario: ATS-CRM-ENT-006-17
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-006-share-an-organization-s-addresses-and-phone-numbers-with-its.md
related_coverage:
  - capability: CAP-CRM-ENT-005
    scenarios:
      - ATS-CRM-ENT-006-13
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-006-share-an-organization-s-addresses-and-phone-numbers-with-its.md:related
  - capability: CAP-CRM-ENT-009
    scenarios:
      - ATS-CRM-ENT-006-14
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-006-share-an-organization-s-addresses-and-phone-numbers-with-its.md:related
  - capability: CAP-CRM-ENT-010
    scenarios:
      - ATS-CRM-ENT-006-15
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-006-share-an-organization-s-addresses-and-phone-numbers-with-its.md:related
  - capability: CAP-CRM-ENT-017
    scenarios:
      - ATS-CRM-ENT-006-16
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-006-share-an-organization-s-addresses-and-phone-numbers-with-its.md:related
examination_evidence:
  provenance: documented
  source: 'rhythm-v2-docs:specs/crm/entities/reports/EXAMINATION-2026-10-23.md'
  heading_conflict: FND-CRM-ENT-075
---

# Share organization contact points with affiliated people
## Coverage

The category map separates specified cases from recorded gaps. A proposed case describes proof to implement; a binding identifies the assertions supplied by an existing executable file. The permission and transition ledgers record the individual checks needed for the capability.

| Required rule | Scenario or finding |
|---|---|
| `BR-CAP-CRM-ENT-006-02` | `ATS-CRM-ENT-006-01` |
| `BR-CAP-CRM-ENT-006-03` | `ATS-CRM-ENT-006-02` |
| `BR-CAP-CRM-ENT-006-04` | `ATS-CRM-ENT-006-03` |
| `BR-CAP-CRM-ENT-006-05` | `ATS-CRM-ENT-006-04` |
| `BR-CAP-CRM-ENT-006-06` | `ATS-CRM-ENT-006-05`, `ATS-CRM-ENT-006-13` |
| `BR-CAP-CRM-ENT-006-07` | `ATS-CRM-ENT-006-06` |
| `BR-CAP-CRM-ENT-006-08` | `ATS-CRM-ENT-006-07`, `ATS-CRM-ENT-006-12` |
| `BR-CAP-CRM-ENT-006-09` | `ATS-CRM-ENT-006-08` |
| `BR-CAP-CRM-ENT-006-10` | `ATS-CRM-ENT-006-09`, `ATS-CRM-ENT-006-14` |
| `BR-CAP-CRM-ENT-006-11` | `ATS-CRM-ENT-006-10`, `ATS-CRM-ENT-006-16` |
| `BR-CAP-CRM-ENT-006-12` | `ATS-CRM-ENT-006-11`, `ATS-CRM-ENT-006-15` |
| `BR-CAP-CRM-ENT-006-13` | Gap: `FND-CRM-ENT-054` |

## Interactions With Related Capabilities

The interaction scenarios exercise maintain reliable contact points; maintain a person’s organizational relationships; keep dated relationships current; configure affiliation types and contact roles. They change one part of a prepared record and inspect the dependent outcome. Unbound interactions remain proposed rather than implying an existing end-to-end implementation.

## Source Evidence

The frontmatter pins the repositories and identifies the source anchors for each scenario. Bindings record inspected assertions, while unbound cases remain proposed. Source inspection supplies no execution result or product approval.
