---
id: ATS-MBR-STR-002
scope: CAP-MBR-STR-002
product_area: membership
module: structure
revision: 1
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-membership: 5994c270e8a37a30f848e99ba5b5ee6b87c08893
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-MBR-STR-002-01
    title: Placement checks also guard direct writes
    level: api
    proves:
      - BR-CAP-MBR-STR-002-01
      - AS-JNY-MBR-STR-001-01
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: >-
      Try a chapter under a disallowed region and as a disallowed root, then attempt invalid parentage through
      the database.
    expected: Both service cases fail and the database rejects the direct placement.
    negative: true
    data_needs: The FAA example records or equivalent records prepared within the isolated workspace.
    bound_to:
      - >-
        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
      - >-
        services-membership:modules/structure/tests/integration/services/persistence/organizational-units.integration.spec.ts#organizational
        units in the database › the refusals › refuses a root of a type that may not be one
      - >-
        services-membership:modules/structure/tests/integration/services/persistence/organizational-units.integration.spec.ts#organizational
        units in the database › the refusals › refuses, in the database itself, a parent of a type not allowed
        (the constraint trigger)
      - >-
        services-membership:tests/acceptance/structure/MBR-ACC-0010.acceptance.ts#MBR-ACC-0010 every illegal
        placement of a new unit is refused
    provenance: test
    source: >-
      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
  - id: ATS-MBR-STR-002-02
    title: Opposing concurrent moves preserve an acyclic tree
    level: api
    proves:
      - BR-CAP-MBR-STR-002-02
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: 'Try moving a region beneath its chapter, then submit opposing moves concurrently.'
    expected: The cycle fails; one concurrent move succeeds and the final ancestry matches a fresh parent walk.
    negative: true
    data_needs: The FAA example records or equivalent records prepared within the isolated workspace.
    bound_to:
      - >-
        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
      - >-
        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 itself as a cycle
      - >-
        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
      - >-
        services-membership:tests/e2e/structure-api.e2e.spec.ts#the structure API, end to end in process ›
        refuses a move under the unit’s own descendant, 409 move_creates_cycle
      - >-
        services-membership:tests/acceptance/structure/MBR-ACC-0016.acceptance.ts#MBR-ACC-0016 two staff
        reorganise the same chapters at once
    provenance: test
    source: >-
      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
  - id: ATS-MBR-STR-002-03
    title: Closed parents reject incoming children
    level: api
    proves:
      - BR-CAP-MBR-STR-002-03
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: Try creation below an inactive unit and relocation below a merged unit.
    expected: Each attempt returns an inactive-parent refusal.
    negative: true
    data_needs: The FAA example records or equivalent records prepared within the isolated workspace.
    bound_to:
      - >-
        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
      - >-
        services-membership:modules/structure/tests/unit/services/tree-edits.spec.ts#the tree edits › move ›
        refuses an inactive parent
      - >-
        services-membership:tests/acceptance/structure/MBR-ACC-0014.acceptance.ts#MBR-ACC-0014 every move the
        tree refuses
    provenance: test
    source: >-
      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
  - id: ATS-MBR-STR-002-04
    title: Only eligible units can change parent
    level: api
    proves:
      - BR-CAP-MBR-STR-002-04
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: Attempt relocation of inactive and merged units and relocation to an unchanged parent.
    expected: All attempts fail with the corresponding structural refusal and preserve earlier records.
    negative: true
    data_needs: The FAA example records or equivalent records prepared within the isolated workspace.
    bound_to:
      - >-
        services-membership:tests/acceptance/structure/MBR-ACC-0014.acceptance.ts#MBR-ACC-0014 every move the
        tree refuses
    provenance: test
    source: >-
      services-membership:tests/acceptance/structure/MBR-ACC-0014.acceptance.ts#MBR-ACC-0014 every move the
      tree refuses
  - id: ATS-MBR-STR-002-05
    title: Depth checks reject the complete edit
    level: unit
    proves:
      - BR-CAP-MBR-STR-002-05
    preconditions: Explicit inputs or a recording fixture represent the cases exercised below.
    steps: Propose a branch reaching depth 32 and separately simulate a rebuild at that depth.
    expected: Both paths reject the excessive depth.
    negative: true
    data_needs: Recording tree-store fixtures and controlled operation inputs.
    bound_to:
      - >-
        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
      - >-
        services-membership:modules/structure/tests/unit/services/tree-edits.spec.ts#the tree edits › move ›
        refuses the whole edit when the rebuilt tree reaches depth 32 (a cycle past validation)
      - >-
        services-membership:tests/acceptance/structure/MBR-ACC-0015.acceptance.ts#MBR-ACC-0015 thirty-one
        levels, a moved subtree and a second root
    provenance: test
    source: >-
      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
  - id: ATS-MBR-STR-002-06
    title: Move dates use the workspace calendar
    level: api
    proves:
      - BR-CAP-MBR-STR-002-06
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: Compare omitted dates with a date before current placement and a date after today.
    expected: Omission selects the workspace date and the out-of-range dates fail.
    negative: true
    data_needs: The FAA example records or equivalent records prepared within the isolated workspace.
    bound_to:
      - >-
        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
      - >-
        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 after today
      - >-
        services-membership:modules/structure/tests/unit/services/tree-edits.spec.ts#the tree edits › move ›
        records the history from the tenant’s business date
      - >-
        services-membership:tests/acceptance/structure/MBR-ACC-0033.acceptance.ts#MBR-ACC-0033 today is New
        York's today
    provenance: test
    source: >-
      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
  - id: ATS-MBR-STR-002-07
    title: Successive parent periods meet without overlap
    level: api
    proves:
      - BR-CAP-MBR-STR-002-07
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: Relocate a unit after its current placement’s first day.
    expected: The earlier period finishes the preceding day and one open attributed period remains.
    negative: false
    data_needs: The FAA example records or equivalent records prepared within the isolated workspace.
    bound_to:
      - >-
        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 › closes the open row at the day before
        the new one and keeps one open row per unit
      - >-
        services-membership:tests/acceptance/structure/MBR-ACC-0013.acceptance.ts#MBR-ACC-0013 a backdated
        move and a same-day correction
    provenance: test
    source: >-
      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 › closes the open row at the day before
      the new one and keeps one open row per unit
  - id: ATS-MBR-STR-002-08
    title: Same-day corrections retain one current period
    level: api
    proves:
      - BR-CAP-MBR-STR-002-08
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: Submit two parent changes effective on the same date.
    expected: Current history names the later parent and retained versions explain the earlier change.
    negative: false
    data_needs: The FAA example records or equivalent records prepared within the isolated workspace.
    bound_to:
      - >-
        services-membership:tests/acceptance/structure/MBR-ACC-0013.acceptance.ts#MBR-ACC-0013 a backdated
        move and a same-day correction
    provenance: test
    source: >-
      services-membership:tests/acceptance/structure/MBR-ACC-0013.acceptance.ts#MBR-ACC-0013 a backdated move
      and a same-day correction
  - id: ATS-MBR-STR-002-09
    title: Large branch moves leave coherent ancestry
    level: api
    proves:
      - BR-CAP-MBR-STR-002-09
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: Relocate a 68-unit branch within a 500-unit structure and compare the result with a parent walk.
    expected: The edit preserves its checked operation order and the rebuilt ancestry matches the independent walk.
    negative: false
    data_needs: The FAA example records or equivalent records prepared within the isolated workspace.
    bound_to:
      - >-
        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
      - >-
        services-membership:modules/structure/tests/integration/services/tree/tree-scale.integration.spec.ts#the
        tree at scale › leaves a closure equal to a fresh walk of the parents after the concurrent moves
      - >-
        services-membership:modules/structure/tests/integration/services/tree/tree-scale.integration.spec.ts#the
        tree at scale › answers the moved subtree under its new parent
      - >-
        services-membership:modules/structure/tests/unit/services/tree-statements.spec.ts#the tree statements
        › the closure rebuild › walks every unit down from itself at depth 0, one level per step, under the
        cap of 32, in every statement but the depths
      - >-
        services-membership:modules/structure/tests/unit/services/tree-statements.spec.ts#the tree statements
        › the closure rebuild › removes the tenant’s pairs the walk no longer has, at their depth, and only
        the tenant’s
      - >-
        services-membership:tests/acceptance/structure/MBR-ACC-0034.acceptance.ts#MBR-ACC-0034 a 500-unit,
        six-level structure
    provenance: test
    source: >-
      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
  - id: ATS-MBR-STR-002-10
    title: Parent changes publish their context
    level: unit
    proves:
      - BR-CAP-MBR-STR-002-11
    preconditions: Explicit inputs or a recording fixture represent the cases exercised below.
    steps: Submit a valid unit relocation and inspect its business event.
    expected: 'The event identifies the unit, previous and new parents, effective date and attribution.'
    negative: false
    data_needs: Recording tree-store fixtures and controlled operation inputs.
    bound_to:
      - >-
        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
      - >-
        services-membership:modules/structure/tests/unit/services/tree-edits.spec.ts#the tree edits › move ›
        builds the reparented payload from the move and the transaction’s attribution
    provenance: test
    source: >-
      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
  - id: ATS-MBR-STR-002-11
    title: Regional membership views follow placement
    level: api
    proves:
      - BR-CAP-MBR-STR-002-14
      - AS-JNY-MBR-STR-002-01
      - AS-JNY-MBR-STR-002-02
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: Move Atlanta from Southeast to Pacific and inspect Jo’s affiliation and regional views.
    expected: The affiliation is unchanged while current and period-end views use their respective regions.
    negative: false
    data_needs: The FAA example records or equivalent records prepared within the isolated workspace.
    bound_to:
      - >-
        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
      - >-
        services-membership:tests/e2e/s09-restructuring.e2e.spec.ts#scenario 9: organizational restructuring ›
        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#scenario 9: organizational restructuring ›
        still holds Atlanta among the Eastern Region’s descendants as of the period end
      - >-
        services-membership:tests/acceptance/structure/MBR-ACC-0012.acceptance.ts#MBR-ACC-0012 scenario 9:
        Atlanta moves to the Pacific Zone
    provenance: test
    source: >-
      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
evidence:
  - >-
    services-membership:modules/structure/tests/integration/services/persistence/organizational-units.integration.spec.ts
  - 'services-membership:modules/structure/tests/integration/services/tree/tree-scale.integration.spec.ts'
  - 'services-membership:modules/structure/tests/unit/services/tree-edits.spec.ts'
  - 'services-membership:modules/structure/tests/unit/services/tree-statements.spec.ts'
  - 'services-membership:tests/acceptance/structure/MBR-ACC-0010.acceptance.ts'
  - 'services-membership:tests/acceptance/structure/MBR-ACC-0012.acceptance.ts'
  - 'services-membership:tests/acceptance/structure/MBR-ACC-0013.acceptance.ts'
  - 'services-membership:tests/acceptance/structure/MBR-ACC-0014.acceptance.ts'
  - 'services-membership:tests/acceptance/structure/MBR-ACC-0015.acceptance.ts'
  - 'services-membership:tests/acceptance/structure/MBR-ACC-0016.acceptance.ts'
  - 'services-membership:tests/acceptance/structure/MBR-ACC-0033.acceptance.ts'
  - 'services-membership:tests/acceptance/structure/MBR-ACC-0034.acceptance.ts'
  - 'services-membership:tests/e2e/s09-restructuring.e2e.spec.ts'
  - 'services-membership:tests/e2e/structure-api.e2e.spec.ts'
---

# Restructure units while preserving dated placement: Acceptance Test Set

## Coverage

| Rule | Proof Scenario or Open Finding |
|---|---|
| `BR-CAP-MBR-STR-002-01` | `ATS-MBR-STR-002-01` |
| `BR-CAP-MBR-STR-002-02` | `ATS-MBR-STR-002-02` |
| `BR-CAP-MBR-STR-002-03` | `ATS-MBR-STR-002-03` |
| `BR-CAP-MBR-STR-002-04` | `ATS-MBR-STR-002-04` |
| `BR-CAP-MBR-STR-002-05` | `ATS-MBR-STR-002-05` |
| `BR-CAP-MBR-STR-002-06` | `ATS-MBR-STR-002-06` |
| `BR-CAP-MBR-STR-002-07` | `ATS-MBR-STR-002-07` |
| `BR-CAP-MBR-STR-002-08` | `ATS-MBR-STR-002-08` |
| `BR-CAP-MBR-STR-002-09` | `ATS-MBR-STR-002-09` |
| `BR-CAP-MBR-STR-002-11` | `ATS-MBR-STR-002-10` |
| `BR-CAP-MBR-STR-002-12` | no scenario: `FND-MBR-STR-036` |
| `BR-CAP-MBR-STR-002-14` | `ATS-MBR-STR-002-11` |
