Skip to content

CAP-MBR-STR-003Combine units and continue their memberships

Markdown

CAP-MBR-STR-003

Combine units and continue their memberships

Markdown
  • DocumentDraft
  • Product intentProposed
  • ImplementationObserved

KindCapabilityProduct areaMembershipModuleOrganizational Structure, Membership Configuration and TermsRevision1

Read atservices-membership 5994c270react-console baf6dae3

The Formal Contract

The narrative above explains; the sections below are authoritative — the rules, scenarios and tests this document binds.

Outcomes
Eligible memberships continue under the surviving unit through one coordinated merge.The result identifies financial and organizational records requiring follow-up.
Surfaces
api
Intent sources
services-membership:docs/migrations/unit-merge/README.md#P2c: a unit merge moves its members' affiliations (Andrew's decision of 2026-10-18, guided build acceptance decision 1: build the move now)

Controls

46 controls apply, from the corpus control catalogue.

TC-AVL-002 TC-AVL-003 TC-AVL-004 TC-AZ-001 TC-AZ-002 TC-AZ-003 TC-AZ-004 TC-AZ-005 TC-AZ-006 TC-CHG-001 TC-CHG-002 TC-CHG-003 TC-CHG-004 TC-CRY-001 TC-CRY-002 TC-CRY-003 TC-DAT-001 TC-DAT-002 TC-DAT-003 TC-DAT-007 TC-IAM-001 TC-IAM-002 TC-IAM-004 TC-IAM-005 TC-IAM-006 TC-LOG-001 TC-LOG-002 TC-LOG-003 TC-LOG-004 TC-LOG-005 TC-MON-001 TC-MON-002 TC-MON-004 TC-PI-001 TC-PI-002 TC-PI-003 TC-PI-004 TC-PI-005 TC-PRV-001 TC-PRV-002 TC-SEC-001 TC-SEC-004 TC-TEN-001 TC-TEN-002 TC-TEN-003 TC-TEN-004

Permissions

KeyChecked atScope
membership.structure.manageapitenant
membership.application.accessapitenant

Business Rules

12 rules, 7 to be proved before approval. A rule's product intent is derived from its origin: 0 confirmed by a product decision, the rest inheriting this capability's proposed.

IdRuleKindEnforced atProvenance
01must prove
Proposed
A merge requires an active survivor outside the source unit’s own branch, and rejects a source already marked merged.
validationservicetest
services-membership:modules/structure/tests/unit/services/tree-edits.spec.ts#the tree edits › merge › refuses a survivor below the merged unit
02must prove
Proposed
All source children relocate to the survivor subject to placement checks, with the complete merge rolled back if any child cannot move.
invariantservicetest
services-membership:modules/structure/tests/integration/services/persistence/organizational-units.integration.spec.ts#organizational units in the database › merge › moves the children under the survivor, marks the unit merged and lists what it left
03must prove
Proposed
The source unit receives merged status and a reference to its survivor.
lifecycleservice, databasetest
services-membership:modules/structure/tests/integration/services/persistence/organizational-units.integration.spec.ts#organizational units in the database › merge › moves the children under the survivor, marks the unit merged and lists what it left
04must prove
Proposed
Effective affiliations transfer or end when the member already overlaps the survivor; unstarted affiliations are re-pointed or withdrawn, and earlier closed periods and cancelled terms remain unchanged.
origin: services-membership:docs/migrations/unit-merge/README.md#P2c: a unit merge moves its members' affiliations (Andrew's decision of 2026-10-18, guided build acceptance decision 1: build the move now)
policyservicedocumented
05must prove
Proposed
Any newly introduced affiliation-rule violation rejects the complete merge and identifies affected memberships and rules.
origin: services-membership:docs/migrations/unit-merge/README.md#P2c: a unit merge moves its members' affiliations (Andrew's decision of 2026-10-18, guided build acceptance decision 1: build the move now)
validationservicetest
services-membership:modules/structure/tests/integration/services/tree/unit-merge.integration.spec.ts#the tree edits affiliations bind › a merge an affiliation cannot follow › is refused 409 affiliations_not_movable, naming the membership and unit_minimum
06must prove
Proposed
Identity-bound memberships replace the source identity with the survivor, with a conflict rejected when the owner already holds the survivor’s membership.
policyservicetest
services-membership:modules/memberships/tests/integration/services/identity-unit-merge.integration.spec.ts#a unit merge moves the identity of identity-bound memberships › the merge of Macon into Atlanta › makes Atlanta the identity of Kim’s membership, at the next version
07
Proposed
The merge retains dues products, financial settings, organization links and committee attachments on the source and identifies follow-up work.
policyservicetest
services-membership:modules/structure/tests/integration/services/persistence/organizational-units.integration.spec.ts#organizational units in the database › merge › moves the children under the survivor, marks the unit merged and lists what it left
08
Proposed
A merge defaults to today, accepts an earlier effective date and rejects future dates; an omitted reason is generated from the source and survivor.
validationapi, serviceobserved
09must prove
Proposed
Merged units reject moves, detail replacements, deactivation and further merges, while their links, financial settings and dues products remain separately writable.
lifecycleserviceobserved
10
Proposed
Merging leaves the source’s parent, current tree placement and open parent-history period unchanged.
policyserviceobserved
11
Proposed
Each relocated child publishes a parent-change event identifying the merged source.
policyservicetest
services-membership:modules/structure/tests/unit/services/tree-edits.spec.ts#the tree edits › merge › states membership.unit.reparented for each child that moved under the survivor, naming the merged unit
12
Proposed
An inactive source can merge into an active survivor.
policyserviceobserved

Scenarios

IdGivenWhenThenProvenance
01The association decides to absorb Savannah Chapter into Atlanta.Staff submit Savannah’s merge with Atlanta as survivor.The eligible section and memberships continue at Atlanta while Savannah retains merged status.test
services-membership:tests/e2e/s13-unit-merge.e2e.spec.ts#a unit merge moves its members: Savannah into Atlanta › merges Savannah, counting one affiliation moved and one ended on the survivor

Edge Cases

IdGivenWhenThenProvenance
02The combination would introduce a shortfall against a member’s package minimum.Staff attempt the unit combination.The complete operation fails and all earlier records remain intact.test
services-membership:modules/structure/tests/integration/services/tree/unit-merge.integration.spec.ts#the tree edits affiliations bind › a merge an affiliation cannot follow › is refused 409 affiliations_not_movable, naming the membership and unit_minimum

The Markdown files under specs/ in rhythmsoftware/rhythm-v2-docs are the canonical source of truth. This reader is a generated, read-only projection of them.