---
id: ATS-MBR-MEM-008
scope: CAP-MBR-MEM-008
product_area: membership
module: memberships
revision: 2
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-membership: 5994c270e8a37a30f848e99ba5b5ee6b87c08893
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-MBR-MEM-008-01
    title: Continue an affiliation in the target unit
    level: api
    proves:
      - BR-CAP-MBR-MEM-008-01
    preconditions: Jo has a primary Atlanta affiliation and a target without dues.
    steps:
      - do: >-
          Transfer the Atlanta row on a future date and inspect both rows and
          the lifecycle event.
        expect: >-
          The original ends the preceding day; the successor begins on the
          selected date as primary and retains lineage, with a transfer event.
        provenance: test
        source:
          - >-
            services-membership:modules/memberships/tests/integration/services/affiliations.integration.spec.ts#transfers
            to a chapter that sells no dues: the old row ends the day before,
            the new one continues it as primary
          - >-
            services-membership:tests/acceptance/affiliations/MBR-ACC-0265.acceptance.ts#MBR-ACC-0265:
            Scenario 6 without dues: Jo moves from Atlanta to San Francisco from
            a future date, the old row ends the day before, the new row inherits
            her primary flag, and rosters read correctly on both sides of the
            date
    expected: >-
      The original ends the preceding day; the successor begins on the selected
      date as primary and retains lineage, with a transfer event.
    negative: false
    data_needs: >-
      Dated affiliations, merge cases, identity-bound memberships and officer
      grants required by the selected operation.
    bound_to:
      - TST-MBR-MEM-024
      - TST-MBR-MEM-049
    provenance: test
    source: >-
      services-membership:modules/memberships/tests/integration/services/affiliations.integration.spec.ts#transfers
      to a chapter that sells no dues: the old row ends the day before, the new
      one continues it as primary
    category: interaction
    binding_evidence:
      - suite: TST-MBR-MEM-024
        source: >-
          services-membership:modules/memberships/tests/integration/services/affiliations.integration.spec.ts#transfers
          to a chapter that sells no dues: the old row ends the day before, the
          new one continues it as primary
      - suite: TST-MBR-MEM-049
        source: >-
          services-membership:tests/acceptance/affiliations/MBR-ACC-0265.acceptance.ts#MBR-ACC-0265:
          Scenario 6 without dues: Jo moves from Atlanta to San Francisco from a
          future date, the old row ends the day before, the new row inherits her
          primary flag, and rosters read correctly on both sides of the date
  - id: ATS-MBR-MEM-008-02
    title: Reject direct transfers requiring dues
    level: api
    proves:
      - BR-CAP-MBR-MEM-008-02
    preconditions: San Francisco charges dues for Jo’s selected package.
    steps:
      - do: Request a direct transfer into San Francisco.
        expect: >-
          The refusal identifies the component-change amendment and leaves the
          original affiliation intact.
        provenance: test
        source:
          - >-
            services-membership:tests/e2e/s06-midterm-transfer.e2e.spec.ts#refuses
            the console’s transfer 409 requires_amendment, naming the
            component_change amendment
          - >-
            services-membership:modules/memberships/tests/integration/services/affiliations.integration.spec.ts#refuses
            to transfer to a chapter that sells dues for the package
            (requires_amendment)
    expected: >-
      The refusal identifies the component-change amendment and leaves the
      original affiliation intact.
    negative: true
    data_needs: >-
      Dated affiliations, merge cases, identity-bound memberships and officer
      grants required by the selected operation.
    bound_to:
      - TST-MBR-MEM-249
      - TST-MBR-MEM-024
    provenance: test
    source: >-
      services-membership:tests/e2e/s06-midterm-transfer.e2e.spec.ts#refuses the
      console’s transfer 409 requires_amendment, naming the component_change
      amendment
    category: failure
    binding_evidence:
      - suite: TST-MBR-MEM-249
        source: >-
          services-membership:tests/e2e/s06-midterm-transfer.e2e.spec.ts#refuses
          the console’s transfer 409 requires_amendment, naming the
          component_change amendment
      - suite: TST-MBR-MEM-024
        source: >-
          services-membership:modules/memberships/tests/integration/services/affiliations.integration.spec.ts#refuses
          to transfer to a chapter that sells dues for the package
          (requires_amendment)
  - id: ATS-MBR-MEM-008-03
    title: Read affiliations and rosters across the transfer date
    level: api
    proves:
      - BR-CAP-MBR-MEM-008-03
    preconditions: >-
      Jo has completed a dated transfer from Atlanta to San Francisco and
      retains Savannah.
    steps:
      - do: >-
          Inspect dated affiliation views and unit rosters before and after the
          effective date.
        expect: >-
          Atlanta is replaced by San Francisco on the transfer date; Savannah
          and its ancestor coverage remain.
        provenance: test
        source:
          - >-
            services-membership:tests/e2e/s06-midterm-transfer.e2e.spec.ts#answers
            Atlanta and Savannah as of 2026-10-15, San Francisco and Savannah as
            of 2027-02-01, the primary moving
          - >-
            services-membership:tests/e2e/s06-midterm-transfer.e2e.spec.ts#takes
            Jo out of Atlanta’s roster from 2027-01-01 and into the Pacific
            Zone’s, keeping them in the Southeast Zone’s through Savannah
    expected: >-
      Atlanta is replaced by San Francisco on the transfer date; Savannah and
      its ancestor coverage remain.
    negative: false
    data_needs: >-
      Dated affiliations, merge cases, identity-bound memberships and officer
      grants required by the selected operation.
    bound_to:
      - TST-MBR-MEM-249
    provenance: test
    source: >-
      services-membership:tests/e2e/s06-midterm-transfer.e2e.spec.ts#answers
      Atlanta and Savannah as of 2026-10-15, San Francisco and Savannah as of
      2027-02-01, the primary moving
    category: boundary
    binding_evidence:
      - suite: TST-MBR-MEM-249
        source: >-
          services-membership:tests/e2e/s06-midterm-transfer.e2e.spec.ts#answers
          Atlanta and Savannah as of 2026-10-15, San Francisco and Savannah as
          of 2027-02-01, the primary moving
      - suite: TST-MBR-MEM-249
        source: >-
          services-membership:tests/e2e/s06-midterm-transfer.e2e.spec.ts#takes
          Jo out of Atlanta’s roster from 2027-01-01 and into the Pacific
          Zone’s, keeping them in the Southeast Zone’s through Savannah
  - id: ATS-MBR-MEM-008-04
    title: Account for each affiliation during a unit merge
    level: api
    proves:
      - BR-CAP-MBR-MEM-008-04
    preconditions: >-
      Savannah holds begun, future, duplicate and already closed affiliation
      cases.
    steps:
      - do: >-
          Merge into Atlanta and inspect action counts, resulting rows and
          lifecycle events.
        expect: >-
          Begun ties transfer, future ties repoint, duplicates end and closed
          ties remain; the counts and lifecycle records describe the actions.
        provenance: test
        source:
          - >-
            services-membership:modules/memberships/tests/integration/services/affiliations-unit-merge.integration.spec.ts#answers
            what it did: one moved, one ended on the survivor, one left closed
          - >-
            services-membership:modules/memberships/tests/integration/services/affiliations-unit-merge.integration.spec.ts#ends
            Pat’s Savannah affiliation the day before and continues it in
            Atlanta as primary
          - >-
            services-membership:modules/memberships/tests/integration/services/affiliations-unit-merge.integration.spec.ts#keeps
            Jo’s Atlanta affiliation as it was and ends her Savannah one, with
            no new row
          - >-
            services-membership:modules/memberships/tests/integration/services/affiliations-unit-merge.integration.spec.ts#leaves
            Lee’s Savannah affiliation, closed in August, as it was
          - >-
            services-membership:modules/memberships/tests/unit/unit-merge.spec.ts#re-points
            an affiliation that begins on or after the merge’s date
          - >-
            services-membership:tests/acceptance/affiliations/MBR-ACC-0277.acceptance.ts#MBR-ACC-0277:
            Savannah Chapter is merged into Atlanta: Pat's row is transferred,
            Kim's not-yet-begun row is re-pointed, Jo's duplicate is ended
            without carrying her primary flag, closed rows and a section's rows
            are left, and Savannah can be deactivated but never deleted
    expected: >-
      Begun ties transfer, future ties repoint, duplicates end and closed ties
      remain; the counts and lifecycle records describe the actions.
    negative: false
    data_needs: >-
      Dated affiliations, merge cases, identity-bound memberships and officer
      grants required by the selected operation.
    bound_to:
      - TST-MBR-MEM-023
      - TST-MBR-MEM-037
      - TST-MBR-MEM-060
    provenance: test
    source: >-
      services-membership:modules/memberships/tests/integration/services/affiliations-unit-merge.integration.spec.ts#answers
      what it did: one moved, one ended on the survivor, one left closed
    category: transition
    binding_evidence:
      - suite: TST-MBR-MEM-023
        source: >-
          services-membership:modules/memberships/tests/integration/services/affiliations-unit-merge.integration.spec.ts#answers
          what it did: one moved, one ended on the survivor, one left closed
      - suite: TST-MBR-MEM-023
        source: >-
          services-membership:modules/memberships/tests/integration/services/affiliations-unit-merge.integration.spec.ts#ends
          Pat’s Savannah affiliation the day before and continues it in Atlanta
          as primary
      - suite: TST-MBR-MEM-023
        source: >-
          services-membership:modules/memberships/tests/integration/services/affiliations-unit-merge.integration.spec.ts#keeps
          Jo’s Atlanta affiliation as it was and ends her Savannah one, with no
          new row
      - suite: TST-MBR-MEM-023
        source: >-
          services-membership:modules/memberships/tests/integration/services/affiliations-unit-merge.integration.spec.ts#leaves
          Lee’s Savannah affiliation, closed in August, as it was
      - suite: TST-MBR-MEM-037
        source: >-
          services-membership:modules/memberships/tests/unit/unit-merge.spec.ts#re-points
          an affiliation that begins on or after the merge’s date
      - suite: TST-MBR-MEM-060
        source: >-
          services-membership:tests/acceptance/affiliations/MBR-ACC-0277.acceptance.ts#MBR-ACC-0277:
          Savannah Chapter is merged into Atlanta: Pat's row is transferred,
          Kim's not-yet-begun row is re-pointed, Jo's duplicate is ended without
          carrying her primary flag, closed rows and a section's rows are left,
          and Savannah can be deactivated but never deleted
  - id: ATS-MBR-MEM-008-05
    title: Refuse an incompatible merge without writing
    level: api
    proves:
      - BR-CAP-MBR-MEM-008-05
    preconditions: >-
      The merge would require a different survivor type or introduce a new
      minimum-count violation.
    steps:
      - do: >-
          Attempt the incompatible merge and inspect the reported rules and
          retained rows.
        expect: >-
          The merge reports affected memberships and rules without changing
          units or affiliations.
        provenance: proposed
        source: >-
          services-membership:modules/memberships/services/affiliations/unit-merge.ts:decideMergedTerm
    expected: >-
      The merge reports affected memberships and rules without changing units or
      affiliations.
    negative: true
    data_needs: >-
      Dated affiliations, merge cases, identity-bound memberships and officer
      grants required by the selected operation.
    bound_to: []
    provenance: proposed
    source: >-
      services-membership:modules/memberships/services/affiliations/unit-merge.ts:decideMergedTerm
    category: validation
  - id: ATS-MBR-MEM-008-06
    title: Move identity-bound holdings or report collisions
    level: api
    proves:
      - BR-CAP-MBR-MEM-008-06
    preconditions: >-
      Kim has a merged-unit identity and another owner already holds the
      surviving identity in the same program.
    steps:
      - do: >-
          Merge the identity unit for Kim, then attempt a merge with a duplicate
          surviving holding.
        expect: >-
          Kim’s identity changes at the next version; a duplicate surviving
          holding causes a refusal without changes.
        provenance: proposed
        source: >-
          services-membership:modules/memberships/services/affiliations/unit-merge.ts:decideIdentityBound
    expected: >-
      Kim’s identity changes at the next version; a duplicate surviving holding
      causes a refusal without changes.
    negative: false
    data_needs: >-
      Dated affiliations, merge cases, identity-bound memberships and officer
      grants required by the selected operation.
    bound_to: []
    provenance: proposed
    source: >-
      services-membership:modules/memberships/services/affiliations/unit-merge.ts:decideIdentityBound
    category: invariant
  - id: ATS-MBR-MEM-008-07
    title: Preserve a unit referenced by historical affiliations
    level: api
    proves:
      - BR-CAP-MBR-MEM-008-07
      - INV-DOM-MBR-MEM-003-08
    preconditions: Savannah has been merged but affiliation history still names it.
    steps:
      - do: Request deletion of the referenced merged unit.
        expect: >-
          Deletion is rejected because affiliation rows still reference the
          unit.
        provenance: test
        source:
          - >-
            services-membership:tests/e2e/s13-unit-merge.e2e.spec.ts#refuses to
            delete Savannah while affiliations name it (unit_has_affiliations)
    expected: Deletion is rejected because affiliation rows still reference the unit.
    negative: true
    data_needs: >-
      Dated affiliations, merge cases, identity-bound memberships and officer
      grants required by the selected operation.
    bound_to:
      - TST-MBR-MEM-256
    provenance: test
    source: >-
      services-membership:tests/e2e/s13-unit-merge.e2e.spec.ts#refuses to delete
      Savannah while affiliations name it (unit_has_affiliations)
    category: invariant
    binding_evidence:
      - suite: TST-MBR-MEM-256
        source: >-
          services-membership:tests/e2e/s13-unit-merge.e2e.spec.ts#refuses to
          delete Savannah while affiliations name it (unit_has_affiliations)
  - id: ATS-MBR-MEM-008-08
    title: Expose moved members to surviving-unit officers
    level: api
    proves:
      - BR-CAP-MBR-MEM-008-08
    preconditions: >-
      Alex’s officer grant reaches Atlanta while Pat initially belongs only to
      Savannah.
    steps:
      - do: Read Pat with Alex’s grant before and after the unit merge.
        expect: >-
          Pat is outside Alex’s scope before the merge and readable through
          Atlanta afterward.
        provenance: test
        source:
          - >-
            services-membership:tests/e2e/s13-unit-merge.e2e.spec.ts#shows Alex
            Jo and not Pat before the merge
          - >-
            services-membership:tests/e2e/s13-unit-merge.e2e.spec.ts#shows Alex
            Pat now, with Pat’s Atlanta affiliation in scope
    expected: >-
      Pat is outside Alex’s scope before the merge and readable through Atlanta
      afterward.
    negative: false
    data_needs: >-
      Dated affiliations, merge cases, identity-bound memberships and officer
      grants required by the selected operation.
    bound_to:
      - TST-MBR-MEM-256
    provenance: test
    source: >-
      services-membership:tests/e2e/s13-unit-merge.e2e.spec.ts#shows Alex Jo and
      not Pat before the merge
    category: interaction
    binding_evidence:
      - suite: TST-MBR-MEM-256
        source: >-
          services-membership:tests/e2e/s13-unit-merge.e2e.spec.ts#shows Alex Jo
          and not Pat before the merge
      - suite: TST-MBR-MEM-256
        source: >-
          services-membership:tests/e2e/s13-unit-merge.e2e.spec.ts#shows Alex
          Pat now, with Pat’s Atlanta affiliation in scope
  - id: ATS-MBR-MEM-008-09
    title: Use a new tree without changing affiliation identity
    level: api
    proves:
      - BR-CAP-MBR-MEM-008-12
    preconditions: >-
      Atlanta has a membership affiliation and is moved from the Eastern Region
      to the Pacific Zone.
    steps:
      - do: >-
          Inspect Jo’s affiliation identity and current rosters, then query
          ancestry before the move.
        expect: >-
          The affiliation keeps its id, version and unit; current ancestry
          reaches the West, while historical ancestry still reaches the East.
        provenance: test
        source:
          - >-
            services-membership:tests/e2e/s09-restructuring.e2e.spec.ts#rewrites
            no affiliation: Jo’s row is the same row, version and unit
          - >-
            services-membership:tests/e2e/s09-restructuring.e2e.spec.ts#shows Jo
            under the Western Region and the Pacific Zone today, and no longer
            under the Eastern Region
          - >-
            services-membership:tests/e2e/s09-restructuring.e2e.spec.ts#still
            holds Atlanta among the Eastern Region’s descendants as of the
            period end
    expected: >-
      The affiliation keeps its id, version and unit; current ancestry reaches
      the West, while historical ancestry still reaches the East.
    negative: false
    data_needs: >-
      Dated affiliations, merge cases, identity-bound memberships and officer
      grants required by the selected operation.
    bound_to:
      - TST-MBR-MEM-252
    provenance: test
    source: >-
      services-membership:tests/e2e/s09-restructuring.e2e.spec.ts#rewrites no
      affiliation: Jo’s row is the same row, version and unit
    category: interaction
    binding_evidence:
      - suite: TST-MBR-MEM-252
        source: >-
          services-membership:tests/e2e/s09-restructuring.e2e.spec.ts#rewrites
          no affiliation: Jo’s row is the same row, version and unit
      - suite: TST-MBR-MEM-252
        source: >-
          services-membership:tests/e2e/s09-restructuring.e2e.spec.ts#shows Jo
          under the Western Region and the Pacific Zone today, and no longer
          under the Eastern Region
      - suite: TST-MBR-MEM-252
        source: >-
          services-membership:tests/e2e/s09-restructuring.e2e.spec.ts#still
          holds Atlanta among the Eastern Region’s descendants as of the period
          end
  - id: ATS-MBR-MEM-008-10
    title: Protect transfer lineage when ending its predecessor
    category: interaction
    level: api
    proves:
      - BR-CAP-MBR-MEM-007-08
      - BR-CAP-MBR-MEM-008-01
    interacts_with:
      - CAP-MBR-MEM-007
    workflows:
      - WF-MBR-MEM-009
    relies_on:
      - ATS-MBR-MEM-007-08
      - ATS-MBR-MEM-008-01
    preconditions: An affiliation has a successor created by transfer.
    steps:
      - do: 'Attempt to withdraw the predecessor, then end it on a day it held.'
        expect: >-
          Withdrawal is refused naming the successor; an allowed end preserves
          the lineage.
        provenance: proposed
        source: &ref_0
          - >-
            services-membership:modules/memberships/tests/integration/services/affiliation-withdrawal-continued.integration.spec.ts#refuses
            to withdraw the continued row, naming the affiliation that continues
            it, and keeps the row
          - >-
            services-membership:modules/memberships/tests/integration/services/affiliations.integration.spec.ts#transfers
            to a chapter that sells no dues: the old row ends the day before,
            the new one continues it as primary
    expected: >-
      Withdrawal is refused naming the successor; an allowed end preserves the
      lineage.
    negative: false
    data_needs: >-
      An isolated workspace with the specified membership, package, chapter and
      partner-port fixtures.
    bound_to: []
    provenance: proposed
    source: *ref_0
  - id: ATS-MBR-MEM-008-11
    title: Preserve coverage when a paid chapter move needs amendment
    category: interaction
    level: api
    proves:
      - BR-CAP-MBR-MEM-008-02
      - BR-CAP-MBR-MEM-009-06
    interacts_with:
      - CAP-MBR-MEM-009
    workflows: []
    relies_on:
      - ATS-MBR-MEM-008-02
      - ATS-MBR-MEM-009-06
    preconditions: A member has a chapter affiliation and the target chapter charges dues.
    steps:
      - do: >-
          Try the direct transfer and checkout preparation for an immediate
          chapter change.
        expect: >-
          Both identify the amendment requirement and leave the existing period
          and chapter rows unchanged.
        provenance: proposed
        source: &ref_1
          - >-
            services-membership:tests/e2e/s06-midterm-transfer.e2e.spec.ts#refuses
            the console’s transfer 409 requires_amendment, naming the
            component_change amendment
          - >-
            services-membership:modules/commerce-participant/tests/unit/eligibility.spec.ts#refuses
            an immediate upgrade as requires_amendment, naming prepare_change
    expected: >-
      Both identify the amendment requirement and leave the existing period and
      chapter rows unchanged.
    negative: false
    data_needs: >-
      An isolated workspace with the specified membership, package, chapter and
      partner-port fixtures.
    bound_to: []
    provenance: proposed
    source: *ref_1
  - id: ATS-MBR-MEM-008-12
    title: Change officer visibility through the surviving unit
    category: interaction
    level: api
    proves:
      - BR-CAP-MBR-MEM-008-08
      - BR-CAP-MBR-MEM-015-04
    interacts_with:
      - CAP-MBR-MEM-015
    workflows:
      - WF-MBR-MEM-009
    relies_on:
      - ATS-MBR-MEM-008-08
      - ATS-MBR-MEM-015-04
    preconditions: The surviving chapter officer cannot read a source-chapter member.
    steps:
      - do: >-
          Merge the source chapter into the survivor, then read the moved member
          and list both chapters.
        expect: >-
          The surviving officer can read the moved member and the current
          survivor roster includes that member.
        provenance: proposed
        source: &ref_2
          - >-
            services-membership:tests/e2e/s13-unit-merge.e2e.spec.ts#shows Alex
            Jo and not Pat before the merge
          - >-
            services-membership:modules/memberships/tests/integration/services/unit-scope.integration.spec.ts#reads
            Jo for the Atlanta officer, the Savannah affiliation marked out of
            scope
    expected: >-
      The surviving officer can read the moved member and the current survivor
      roster includes that member.
    negative: false
    data_needs: >-
      An isolated workspace with the specified membership, package, chapter and
      partner-port fixtures.
    bound_to: []
    provenance: proposed
    source: *ref_2
evidence:
  - >-
    services-membership at 5994c270e8a37a30f848e99ba5b5ee6b87c08893: reviewed
    transfer writes, merge decisions and lifecycle effects, the recorded merge
    approval, and the cited transfer, identity-merge, roster and
    historical-ancestry assertions.
  - >-
    rhythm-v2-docs:specs/membership/memberships/design/: domain objects, state
    models and workflows reviewed for coverage.
coverage:
  rule: 'gap: FND-MBR-MEM-090'
  transition: 'gap: FND-MBR-MEM-090'
  validation: covered
  permission: 'gap: FND-MBR-MEM-090'
  edge: 'gap: FND-MBR-MEM-090'
  failure: covered
  boundary: covered
  concurrency: 'gap: FND-MBR-MEM-090'
  invariant: 'gap: FND-MBR-MEM-090'
  interaction: covered
coverage_notes:
  transition: >-
    The scenarios do not enumerate every applicable object transition; the
    finding preserves the remaining transition matrix.
  permission: >-
    The finding records named permissions without a complete positive and
    negative proof.
  invariant: >-
    Existing invariant examples do not cover every applicable domain-object
    constraint.
  interaction: >-
    Every related capability and each cross-capability workflow has an explicit
    composite scenario. Unbound composites remain proposed.
---

# Preserve member connections through transfers and unit merges: Capability Test Specification

## Coverage

| Rule | Scenario or Finding |
|---|---|
| `BR-CAP-MBR-MEM-008-01` | `ATS-MBR-MEM-008-01`, `ATS-MBR-MEM-008-10` |
| `BR-CAP-MBR-MEM-008-02` | `ATS-MBR-MEM-008-02`, `ATS-MBR-MEM-008-11` |
| `BR-CAP-MBR-MEM-008-03` | `ATS-MBR-MEM-008-03` |
| `BR-CAP-MBR-MEM-008-04` | `ATS-MBR-MEM-008-04` |
| `BR-CAP-MBR-MEM-008-05` | `ATS-MBR-MEM-008-05` |
| `BR-CAP-MBR-MEM-008-06` | `ATS-MBR-MEM-008-06` |
| `BR-CAP-MBR-MEM-008-07` | `ATS-MBR-MEM-008-07` |
| `BR-CAP-MBR-MEM-008-08` | `ATS-MBR-MEM-008-08`, `ATS-MBR-MEM-008-12` |
| `BR-CAP-MBR-MEM-008-09` | no scenario: `FND-MBR-MEM-028` |
| `BR-CAP-MBR-MEM-008-10` | no scenario: `FND-MBR-MEM-027` |
| `BR-CAP-MBR-MEM-008-12` | `ATS-MBR-MEM-008-09` |

## Interactions With Related Capabilities

The interaction cases test how a shared holding, period, chapter connection or recorded change affects related work. Each case names its related capabilities and workflows in frontmatter. A composite case remains proposed until executable assertions establish every part of its expected outcome.
