Skip to content

CAP-MBR-STR-002Restructure units while preserving dated placement

Markdown

CAP-MBR-STR-002

Restructure units while preserving dated placement

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
Restructuring preserves valid parentage for the complete branch.Placement history identifies the effective date, actor and reason.
Surfaces
api

Controls

41 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-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-MON-001 TC-MON-002 TC-MON-004 TC-PI-001 TC-PI-002 TC-PI-003 TC-PI-004 TC-PI-005 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

14 rules, 12 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 unit can have a parent only of an allowed kind, and can have no parent only when its kind permits roots, with service and database checks on placement.
validationservice, databasetest
services-membership:tests/e2e/structure-api.e2e.spec.ts#the structure API, end to end in process › refuses a parent of a type not allowed, 409 parent_type_not_allowed
02must prove
Proposed
A move beneath the unit itself or its descendants is rejected; serialized workspace tree edits make opposing concurrent moves produce one success and one refusal.
invariantservicetest
services-membership:modules/structure/tests/integration/services/persistence/organizational-units.integration.spec.ts#organizational units in the database › the refusals › refuses a move under the unit’s own descendant as a cycle
03must prove
Proposed
Inactive and merged units cannot receive newly placed or moved child units.
validationservicetest
services-membership:modules/structure/tests/integration/services/persistence/organizational-units.integration.spec.ts#organizational units in the database › the refusals › refuses a new child under an inactive unit
04must prove
Proposed
A unit must be active to move and cannot be moved to its existing parent.
validationserviceobserved
05must prove
Proposed
A proposed branch placement or final rebuild reaching depth 32 is rejected as a whole.
invariantservicetest
services-membership:modules/structure/tests/unit/services/tree-edits.spec.ts#the tree edits › move › refuses a move that would put the subtree at the depth cap, before any write
06must prove
Proposed
A move request supplies a reason and uses the workspace’s current date by default; a supplied date cannot be in the future or precede the current parent period.
validationapi, servicetest
services-membership:modules/structure/tests/integration/services/persistence/organizational-units.integration.spec.ts#organizational units in the database › the parent history and the as-of tree › refuses a move dated before the current parent began
07must prove
Proposed
Parent periods cover dates from the first placement onward without gaps between successive periods, retaining the actor and reason for each change.
invariantserviceobserved
08must prove
Proposed
A second placement change effective on the current period’s first day updates that history row, with the earlier value retained in its versions.
policyserviceobserved
09must prove
Proposed
Tree edits recompute the workspace’s ancestor relationships and unit depths within the same transaction.
invariantservicetest
services-membership:modules/structure/tests/unit/services/tree-edits.spec.ts#the tree edits › move › locks, validates against the current closure, changes the parent, records history, rebuilds, updates depths and checks the cap, in that order
10
Proposed
Move concurrency checks compare the supplied version with the stored version only when a version is supplied.
policyserviceobserved
11must prove
Proposed
A successful move publishes the old parent, new parent and effective date within its transaction.
policyservicetest
services-membership:modules/structure/tests/unit/services/tree-edits.spec.ts#the tree edits › move › states membership.unit.reparented with the old and the new parent and the business date
12must prove
Proposed
Retrying the same completed move fails because the proposed parent is already current; moves have no retry key.
policyservicedocumented
services-membership:docs/migrations/structure/README.md#What could not be done as specified, and why
13
Proposed
Future-effective restructuring is unavailable; moves apply immediately with today’s date or an allowed earlier date.
lifecycleservicedocumented
14must prove
Proposed
Restructuring changes current regional membership visibility without rewriting affiliation records, while historical placement reads retain earlier parentage.
policyservicetest
services-membership:tests/e2e/s09-restructuring.e2e.spec.ts#scenario 9: organizational restructuring › rewrites no affiliation: Jo’s row is the same row, version and unit

Scenarios

IdGivenWhenThenProvenance
01Atlanta belongs to the Southeast Zone.Staff relocate Atlanta to the Pacific Zone and explain the change.The branch appears beneath Pacific and its placement history retains the transition.test
services-membership:tests/e2e/s09-restructuring.e2e.spec.ts#scenario 9: organizational restructuring › moves Atlanta under the Pacific Zone

Edge Cases

IdGivenWhenThenProvenance
02Two staff requests propose opposing parent relationships.Both requests attempt their moves concurrently.The first succeeds and the second fails after detecting the resulting cycle.test
services-membership:modules/structure/tests/integration/services/tree/tree-scale.integration.spec.ts#the tree at scale › serialises two concurrent moves of one tenant by the tree lock, the second validating against the first’s closure

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.