---
id: ATS-MBR-STR-020
scope: CAP-MBR-STR-020
product_area: membership
module: structure
revision: 2
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-membership: 5994c270e8a37a30f848e99ba5b5ee6b87c08893
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-MBR-STR-020-01
    title: Provisioning applies standard purposes only once
    level: api
    proves:
      - BR-CAP-MBR-STR-020-01
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: Invoke structure provisioning twice and inspect readiness.
    expected: The first supplies four purposes and the second adds none while readiness remains satisfied.
    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/lifecycle/structure-participant.integration.spec.ts#the
        structure participant in the database › seeds the four relationship types at provisioning
      - >-
        services-membership:modules/structure/tests/integration/services/lifecycle/structure-participant.integration.spec.ts#the
        structure participant in the database › writes nothing on a second provisioning
      - >-
        services-membership:modules/structure/tests/integration/services/lifecycle/structure-participant.integration.spec.ts#the
        structure participant in the database › reports a provisioned tenant ready
      - TST-MBR-STR-004
    provenance: test
    source: >-
      services-membership:modules/structure/tests/integration/services/lifecycle/structure-participant.integration.spec.ts#the
      structure participant in the database › seeds the four relationship types at provisioning
    category: transition
  - id: ATS-MBR-STR-020-02
    title: Purge requires deletion state and preserves other customers
    level: api
    proves:
      - BR-CAP-MBR-STR-020-02
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: 'Attempt purge for an active workspace, then drain a deleting workspace beside another.'
    expected: >-
      The active attempt deletes nothing; the deleting workspace is emptied including versions and the
      other stays intact.
    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/lifecycle/structure-participant.integration.spec.ts#the
        structure participant in the database › refuses to purge a tenant Platform is not deleting,
        before any row is removed
      - >-
        services-membership:modules/structure/tests/integration/services/lifecycle/structure-participant.integration.spec.ts#the
        structure participant in the database › refuses to purge a tenant Platform holds no row of,
        before any row is removed
      - >-
        services-membership:modules/structure/tests/integration/services/lifecycle/structure-participant.integration.spec.ts#the
        structure participant in the database › purges every table of a tenant being deleted, versions
        included, and leaves another tenant whole
      - TST-MBR-STR-004
    provenance: test
    source: >-
      services-membership:modules/structure/tests/integration/services/lifecycle/structure-participant.integration.spec.ts#the
      structure participant in the database › refuses to purge a tenant Platform is not deleting, before
      any row is removed
    category: boundary
  - id: ATS-MBR-STR-020-03
    title: Reset preserves classifications in an allowed state
    level: api
    proves:
      - BR-CAP-MBR-STR-020-03
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: Attempt active-workspace reset and then reset an allowed workspace state.
    expected: The first fails and the allowed reset removes unit data while keeping both kind catalogues.
    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/lifecycle/structure-participant.integration.spec.ts#the
        structure participant in the database › refuses to reset the tree of a tenant that is active,
        before any row is removed
      - >-
        services-membership:modules/structure/tests/integration/services/lifecycle/structure-participant.integration.spec.ts#the
        structure participant in the database › resets the tree of a tenant being reset and keeps its
        unit and relationship types
      - TST-MBR-STR-004
    provenance: test
    source: >-
      services-membership:modules/structure/tests/integration/services/lifecycle/structure-participant.integration.spec.ts#the
      structure participant in the database › refuses to reset the tree of a tenant that is active,
      before any row is removed
    category: transition
  - id: ATS-MBR-STR-020-04
    title: Bulk structure loading rebuilds and reconciles
    level: api
    proves:
      - BR-CAP-MBR-STR-020-05
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: >-
      Load parent-first records with a missing-parent case and a relocation upsert, then rebuild and
      inspect reconciliation.
    expected: >-
      The invalid parent case fails and the completed valid structure reconciles after its deferred
      rebuild.
    negative: false
    data_needs: The FAA example records or equivalent records prepared within the isolated workspace.
    bound_to:
      - TST-MBR-STR-001
      - >-
        services-membership:modules/data-jobs/tests/integration/services/operations/structure-data-operations.integration.spec.ts#rebuilds
        the closure once after the load, and reconciles the tree whole
    provenance: test
    source:
      - >-
        services-membership:docs/migrations/structure/README.md#Routes, permissions, metadata, data
        operations, lifecycle, well-known objects
      - >-
        services-membership:modules/data-jobs/tests/integration/services/operations/structure-data-operations.integration.spec.ts#rebuilds
        the closure once after the load, and reconciles the tree whole
    category: interaction
    coverage_limit: >-
      The integration case proves parent-first inserts, missing-parent rejection, code upsert and final
      reconciliation; relocation upserts need separate proof.
  - id: ATS-MBR-STR-020-05
    title: Bulk configuration classifies invalid items
    level: api
    proves:
      - BR-CAP-MBR-STR-020-06
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: 'Load dependent programs, types and packages including a malformed item and a matched upsert.'
    expected: >-
      Invalid input is classified for rejection and valid writes apply through the configuration
      processes.
    negative: true
    data_needs: The FAA example records or equivalent records prepared within the isolated workspace.
    bound_to:
      - >-
        services-membership:tests/acceptance/configuration/MBR-ACC-0110.acceptance.ts#MBR-ACC-0110: A
        migration loads programs, types and packages in bulk: an insert is the record the route would
        have made, an upsert converges by id or by the producer's source key, a package needs its product
        first, and a malformed item is rejected naming its field while the others proceed
      - TST-MBR-STR-047
    provenance: test
    source: >-
      services-membership:tests/acceptance/configuration/MBR-ACC-0110.acceptance.ts#MBR-ACC-0110: A
      migration loads programs, types and packages in bulk: an insert is the record the route would have
      made, an upsert converges by id or by the producer's source key, a package needs its product first,
      and a malformed item is rejected naming its field while the others proceed
    category: failure
  - id: ATS-MBR-STR-020-06
    title: Bulk setup omits unsupported record families
    category: boundary
    level: api
    proves:
      - BR-CAP-MBR-STR-020-07
    preconditions: An isolated workspace contains the records and current versions needed for the case.
    steps: >-
      Inspect the registered configuration load operations alongside the program, type and package
      operations.
    expected: 'There is no load operation for status reasons, policy sets or program requirements.'
    negative: false
    data_needs: Separate fixture records for the accepted and refused operations.
    bound_to: []
    provenance: proposed
    source:
      - >-
        services-membership:modules/configuration/services/data-operations/configuration-operations.ts:configurationDataOperations
  - id: ATS-MBR-STR-020-07
    title: Purged seed bookkeeping prevents reseeding
    category: edge
    level: api
    proves:
      - BR-CAP-MBR-STR-020-09
    preconditions: An isolated workspace contains the records and current versions needed for the case.
    steps: >-
      Provision a dedicated workspace, purge it in deleting state, restore a permitted provisioning state
      and provision the same identity again.
    expected: Applied seed keys remain and the four removed relationship purposes are not recreated.
    negative: true
    data_needs: Separate fixture records for the accepted and refused operations.
    bound_to: []
    provenance: proposed
    source:
      - 'react-console:acceptance/membership/journeys/structure/MBR-ACC-0028.json'
  - id: ATS-MBR-STR-020-08
    title: Closing a load refuses excessive depth
    category: failure
    level: api
    proves:
      - BR-CAP-MBR-STR-020-10
    preconditions: An isolated workspace contains the records and current versions needed for the case.
    steps: >-
      Load available kinds and parent-first units to depth 32, inspect pre-rebuild ancestry and attempt
      the closing rebuild.
    expected: >-
      The closing transaction fails; earlier loaded parent references remain and require reconciliation
      before ordinary tree reads can be trusted.
    negative: true
    data_needs: Separate fixture records for the accepted and refused operations.
    bound_to: []
    provenance: proposed
    source:
      - 'services-membership:modules/structure/services/tree/tree-loads.ts:loadUnit'
  - id: ATS-MBR-STR-020-09
    title: Provisioning preserves customer relationship purposes
    category: interaction
    level: api
    proves:
      - BR-CAP-MBR-STR-007-06
      - BR-CAP-MBR-STR-020-01
    preconditions: An isolated workspace contains the records and current versions needed for the case.
    steps: 'Provision, add a customer relationship purpose and provision again.'
    expected: The standard purposes remain present once and the customer purpose retains its values.
    negative: false
    data_needs: Separate fixture records for the accepted and refused operations.
    bound_to: []
    provenance: proposed
    source:
      - >-
        services-membership:tests/e2e/structure-api.e2e.spec.ts#the structure API, end to end in process
        › creates a relationship type with an id derived from its name
      - >-
        services-membership:modules/structure/tests/integration/services/lifecycle/structure-participant.integration.spec.ts#the
        structure participant in the database › seeds the four relationship types at provisioning
    exercises:
      - CAP-MBR-STR-020
      - CAP-MBR-STR-007
evidence:
  - >-
    services-membership:modules/structure/tests/integration/services/lifecycle/structure-participant.integration.spec.ts
  - 'services-membership:tests/acceptance/configuration/MBR-ACC-0110.acceptance.ts'
  - >-
    services-membership:modules/structure/tests/integration/services/lifecycle/structure-participant.integration.spec.ts#the
    structure participant in the database › seeds the four relationship types at provisioning
  - >-
    services-membership:modules/structure/tests/integration/services/lifecycle/structure-participant.integration.spec.ts#the
    structure participant in the database › refuses to purge a tenant Platform is not deleting, before
    any row is removed
  - >-
    services-membership:modules/structure/tests/integration/services/lifecycle/structure-participant.integration.spec.ts#the
    structure participant in the database › resets the tree of a tenant being reset and keeps its unit
    and relationship types
  - 'services-membership:modules/structure/services/well-known/well-known-structure.ts'
  - >-
    services-membership:docs/migrations/structure/README.md#Routes, permissions, metadata, data
    operations, lifecycle, well-known objects
  - >-
    services-membership:modules/configuration/services/data-operations/configuration-operations.ts:configurationDataOperations
  - >-
    services-membership:modules/structure/services/lifecycle/structure-participant.ts:structureParticipant
  - 'react-console:acceptance/membership/journeys/structure/MBR-ACC-0028.json'
  - 'services-membership:modules/structure/services/tree/tree-loads.ts:loadUnit'
  - >-
    services-membership:modules/structure/tests/integration/services/lifecycle/structure-participant.integration.spec.ts#the
    structure participant in the database › refuses to reset the tree of a tenant that is active, before
    any row is removed
  - >-
    services-membership:tests/acceptance/configuration/MBR-ACC-0110.acceptance.ts#MBR-ACC-0110: A
    migration loads programs, types and packages in bulk: an insert is the record the route would have
    made, an upsert converges by id or by the producer's source key, a package needs its product first,
    and a malformed item is rejected naming its field while the others proceed
  - >-
    services-membership:tests/e2e/structure-api.e2e.spec.ts#the structure API, end to end in process ›
    creates a relationship type with an id derived from its name
coverage:
  rule: 'gap: FND-MBR-STR-073'
  transition: covered
  validation: 'gap: FND-MBR-STR-073'
  permission: 'gap: FND-MBR-STR-073'
  edge: covered
  failure: covered
  boundary: covered
  concurrency: 'gap: FND-MBR-STR-073'
  invariant: 'gap: FND-MBR-STR-073'
  interaction: covered
coverage_notes:
  rule: >-
    No dedicated scenario establishes this category across the capability’s declared operations and
    design obligations.
  validation: >-
    No dedicated scenario establishes this category across the capability’s declared operations and
    design obligations.
  permission: >-
    No dedicated scenario establishes this category across the capability’s declared operations and
    design obligations.
  concurrency: >-
    No dedicated scenario establishes this category across the capability’s declared operations and
    design obligations.
  invariant: >-
    No dedicated scenario establishes this category across the capability’s declared operations and
    design obligations.
unproved_rules: []
coverage_obligations:
  permissions:
    - key: membership.structure.manage
      scenario_ids:
        - ATS-MBR-STR-019-01
      local_scenario_ids: []
      coverage: partial
      gap: FND-MBR-STR-073
      provenance: unknown
      source: FND-MBR-STR-073
      note: >-
        These cases establish declared authority or representative admission; exhaustive operation and
        caller combinations remain open.
    - key: membership.programs.manage
      scenario_ids:
        - ATS-MBR-STR-019-02
      local_scenario_ids: []
      coverage: partial
      gap: FND-MBR-STR-073
      provenance: unknown
      source: FND-MBR-STR-073
      note: >-
        These cases establish declared authority or representative admission; exhaustive operation and
        caller combinations remain open.
    - key: membership.configuration.manage
      scenario_ids:
        - ATS-MBR-STR-019-02
      local_scenario_ids: []
      coverage: partial
      gap: FND-MBR-STR-073
      provenance: unknown
      source: FND-MBR-STR-073
      note: >-
        These cases establish declared authority or representative admission; exhaustive operation and
        caller combinations remain open.
  state_models: []
  related:
    - capability: CAP-MBR-STR-007
      scenario: ATS-MBR-STR-020-09
      provenance: proposed
  invariants:
    - id: INV-DOM-MBR-STR-006-01
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-073
      provenance: unknown
      source: FND-MBR-STR-073
    - id: INV-DOM-MBR-STR-006-02
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-073
      provenance: unknown
      source: FND-MBR-STR-073
    - id: INV-DOM-MBR-STR-006-03
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-073
      provenance: unknown
      source: FND-MBR-STR-073
    - id: INV-DOM-MBR-STR-006-04
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-073
      provenance: unknown
      source: FND-MBR-STR-073
    - id: INV-DOM-MBR-STR-006-05
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-073
      provenance: unknown
      source: FND-MBR-STR-073
    - id: INV-DOM-MBR-STR-006-06
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-073
      provenance: unknown
      source: FND-MBR-STR-073
    - id: INV-DOM-MBR-STR-006-07
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-073
      provenance: unknown
      source: FND-MBR-STR-073
    - id: INV-DOM-MBR-STR-006-08
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-073
      provenance: unknown
      source: FND-MBR-STR-073
  workflows:
    - id: WF-MBR-STR-007
      scenarios:
        - ATS-MBR-STR-020-04
        - ATS-MBR-STR-020-05
        - ATS-MBR-STR-020-08
        - ATS-MBR-STR-020-09
      unproved_failure_and_concurrency: FND-MBR-STR-073
      provenance: unknown
      source: FND-MBR-STR-073
    - id: WF-MBR-STR-008
      scenarios:
        - ATS-MBR-STR-020-04
        - ATS-MBR-STR-020-05
        - ATS-MBR-STR-020-08
        - ATS-MBR-STR-020-09
      unproved_failure_and_concurrency: FND-MBR-STR-073
      provenance: unknown
      source: FND-MBR-STR-073
  workflow_interactions: []
rule_coverage:
  - rule: BR-CAP-MBR-STR-020-01
    scenarios:
      - ATS-MBR-STR-020-01
      - ATS-MBR-STR-020-09
    gap: null
    provenance: documented
    source:
      - >-
        services-membership:modules/structure/tests/integration/services/lifecycle/structure-participant.integration.spec.ts#the
        structure participant in the database › seeds the four relationship types at provisioning
      - >-
        services-membership:tests/e2e/structure-api.e2e.spec.ts#the structure API, end to end in process
        › creates a relationship type with an id derived from its name
      - >-
        services-membership:modules/structure/tests/integration/services/lifecycle/structure-participant.integration.spec.ts#the
        structure participant in the database › seeds the four relationship types at provisioning
  - rule: BR-CAP-MBR-STR-020-02
    scenarios:
      - ATS-MBR-STR-020-02
    gap: null
    provenance: documented
    source:
      - >-
        services-membership:modules/structure/tests/integration/services/lifecycle/structure-participant.integration.spec.ts#the
        structure participant in the database › refuses to purge a tenant Platform is not deleting,
        before any row is removed
  - rule: BR-CAP-MBR-STR-020-03
    scenarios:
      - ATS-MBR-STR-020-03
    gap: null
    provenance: documented
    source:
      - >-
        services-membership:modules/structure/tests/integration/services/lifecycle/structure-participant.integration.spec.ts#the
        structure participant in the database › refuses to reset the tree of a tenant that is active,
        before any row is removed
  - rule: BR-CAP-MBR-STR-020-05
    scenarios:
      - ATS-MBR-STR-020-04
    gap: null
    provenance: documented
    source:
      - >-
        services-membership:docs/migrations/structure/README.md#Routes, permissions, metadata, data
        operations, lifecycle, well-known objects
      - >-
        services-membership:modules/data-jobs/tests/integration/services/operations/structure-data-operations.integration.spec.ts#rebuilds
        the closure once after the load, and reconciles the tree whole
  - rule: BR-CAP-MBR-STR-020-06
    scenarios:
      - ATS-MBR-STR-020-05
    gap: null
    provenance: documented
    source:
      - >-
        services-membership:tests/acceptance/configuration/MBR-ACC-0110.acceptance.ts#MBR-ACC-0110: A
        migration loads programs, types and packages in bulk: an insert is the record the route would
        have made, an upsert converges by id or by the producer's source key, a package needs its product
        first, and a malformed item is rejected naming its field while the others proceed
  - rule: BR-CAP-MBR-STR-020-07
    scenarios:
      - ATS-MBR-STR-020-06
    gap: null
    provenance: documented
    source:
      - >-
        services-membership:modules/configuration/services/data-operations/configuration-operations.ts:configurationDataOperations
  - rule: BR-CAP-MBR-STR-020-09
    scenarios:
      - ATS-MBR-STR-020-07
    gap: null
    provenance: documented
    source:
      - 'react-console:acceptance/membership/journeys/structure/MBR-ACC-0028.json'
  - rule: BR-CAP-MBR-STR-020-10
    scenarios:
      - ATS-MBR-STR-020-08
    gap: null
    provenance: documented
    source:
      - 'services-membership:modules/structure/services/tree/tree-loads.ts:loadUnit'
narrative_sources:
  - section: Coverage
    provenance: documented
    source:
      - CAP-MBR-STR-020
      - FND-MBR-STR-073
  - section: Interactions With Related Capabilities
    provenance: proposed
    source:
      - ATS-MBR-STR-020-04
      - ATS-MBR-STR-020-09
---

# Provision, migrate and remove membership setup: Capability Test Specification

## Coverage

The coverage map distinguishes specified examples from missing proof. A covered category means an expected case is specified; executable bindings and their run results remain separate evidence. Each required rule has a proof link or an explicit coverage finding in the structured rule ledger.

| Required Rule | Scenario or Finding |
|---|---|
| `BR-CAP-MBR-STR-020-01` | `ATS-MBR-STR-020-01`, `ATS-MBR-STR-020-09` |
| `BR-CAP-MBR-STR-020-02` | `ATS-MBR-STR-020-02` |
| `BR-CAP-MBR-STR-020-03` | `ATS-MBR-STR-020-03` |
| `BR-CAP-MBR-STR-020-05` | `ATS-MBR-STR-020-04` |
| `BR-CAP-MBR-STR-020-06` | `ATS-MBR-STR-020-05` |
| `BR-CAP-MBR-STR-020-07` | `ATS-MBR-STR-020-06` |
| `BR-CAP-MBR-STR-020-09` | `ATS-MBR-STR-020-07` |
| `BR-CAP-MBR-STR-020-10` | `ATS-MBR-STR-020-08` |

## Interactions With Related Capabilities

Provisioning preserves customer relationship purposes. Provision, add a customer relationship purpose and provision again.
