---
id: ATS-MBR-STR-008
scope: CAP-MBR-STR-008
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-008-01
    title: Dues extensions require the appropriate product
    level: api
    proves:
      - BR-CAP-MBR-STR-008-01
      - AS-JNY-MBR-STR-001-03
      - INV-DOM-MBR-STR-002-06
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: >-
      Create Atlanta’s extension from a chapter-dues product, then try a missing product and a
      membership-package product.
    expected: The valid extension retains product identity and shared fields; invalid products fail.
    negative: true
    data_needs: The FAA example records or equivalent records prepared within the isolated workspace.
    bound_to:
      - >-
        services-membership:tests/e2e/packages-as-products.e2e.spec.ts#packages as products, through the
        API › extends a product of type chapter_dues as a unit’s dues product, under the product’s id,
        with the product’s name
      - >-
        services-membership:modules/structure/tests/unit/accounting-products.spec.ts#the Accounting
        products port › refuses an extension on a missing product or on a product of another type, naming
        the field
      - TST-MBR-STR-096
      - TST-MBR-STR-009
    provenance: test
    source: >-
      services-membership:tests/e2e/packages-as-products.e2e.spec.ts#packages as products, through the
      API › extends a product of type chapter_dues as a unit’s dues product, under the product’s id, with
      the product’s name
    category: validation
  - id: ATS-MBR-STR-008-02
    title: Package and catch-all dues choices are unique
    level: api
    proves:
      - BR-CAP-MBR-STR-008-02
      - INV-DOM-MBR-STR-002-05
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: Attempt duplicate package-specific dues offerings and duplicate catch-all offerings.
    expected: The second offering in each context is refused.
    negative: true
    data_needs: The FAA example records or equivalent records prepared within the isolated workspace.
    bound_to: []
    provenance: proposed
    source: >-
      services-membership:modules/structure/services/persistence/organizational-unit-dues-products.ts:createDuesProduct
    category: invariant
  - id: ATS-MBR-STR-008-03
    title: Dues reads track current product state
    level: unit
    proves:
      - BR-CAP-MBR-STR-008-03
    preconditions: Explicit inputs or a recording fixture represent the cases exercised below.
    steps: Read an extension after its product is inactive and after the product is unavailable.
    expected: 'Shared fields reflect inactivity, with missing-product defaults of hidden and inactive.'
    negative: false
    data_needs: 'Literal term, state or declaration fixtures for the described cases.'
    bound_to:
      - >-
        services-membership:modules/structure/tests/unit/accounting-products.spec.ts#the Accounting
        products port › answers the product’s common fields under the names the package wire kept:
        inactive is not active and not portal visible
      - >-
        services-membership:modules/structure/tests/unit/accounting-products.spec.ts#the Accounting
        products port › answers a product Accounting no longer has as its id, inactive, hidden, with no
        product status
      - TST-MBR-STR-009
    provenance: test
    source: >-
      services-membership:modules/structure/tests/unit/accounting-products.spec.ts#the Accounting
      products port › answers the product’s common fields under the names the package wire kept: inactive
      is not active and not portal visible
    category: edge
  - id: ATS-MBR-STR-008-04
    title: Repointing preserves product identity
    level: api
    proves:
      - BR-CAP-MBR-STR-008-04
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: Replace the dues package association using the current version and then the earlier version.
    expected: The first advances the extension version and the stale replacement fails.
    negative: true
    data_needs: The FAA example records or equivalent records prepared within the isolated workspace.
    bound_to:
      - >-
        services-membership:tests/e2e/packages-as-products.e2e.spec.ts#packages as products, through the
        API › re-points a unit’s dues product at another package at the version just read, 200 with the
        next version
      - TST-MBR-STR-096
    provenance: test
    source: >-
      services-membership:tests/e2e/packages-as-products.e2e.spec.ts#packages as products, through the
      API › re-points a unit’s dues product at another package at the version just read, 200 with the
      next version
    category: concurrency
  - id: ATS-MBR-STR-008-05
    title: Financial settings distinguish first and later saves
    level: api
    proves:
      - BR-CAP-MBR-STR-008-06
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: >-
      Read absent settings, create them without a version and compare later saves with absent, current
      and stale versions.
    expected: Absent reads fail; creation succeeds and later replacement requires the current version.
    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-0023.acceptance.ts#MBR-ACC-0023 a
        chapter's financial settings
      - TST-MBR-STR-082
    provenance: test
    source: >-
      services-membership:tests/acceptance/structure/MBR-ACC-0023.acceptance.ts#MBR-ACC-0023 a chapter's
      financial settings
    category: rule
  - id: ATS-MBR-STR-008-06
    title: Profile choices are stored without duplicating checkout
    level: api
    proves:
      - BR-CAP-MBR-STR-008-07
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: 'Save an explicit ordering profile, clear it and attempt an invalid profile shape.'
    expected: 'The explicit pointer and cleared choice round-trip, while invalid shape fails.'
    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-0023.acceptance.ts#MBR-ACC-0023 a
        chapter's financial settings
      - TST-MBR-STR-082
    provenance: test
    source: >-
      services-membership:tests/acceptance/structure/MBR-ACC-0023.acceptance.ts#MBR-ACC-0023 a chapter's
      financial settings
    category: rule
  - id: ATS-MBR-STR-008-07
    title: Merge leaves local dues and settlement work on the source
    category: interaction
    level: api
    proves:
      - BR-CAP-MBR-STR-003-07
      - BR-CAP-MBR-STR-008-09
    preconditions: An isolated workspace contains the records and current versions needed for the case.
    steps: >-
      Prepare source dues and financial settings, merge the source, inspect the returned follow-up list
      and reread the source facets.
    expected: >-
      The result identifies the source’s dues and settings as follow-up work; both remain readable on the
      source.
    negative: false
    data_needs: Separate fixture records for the accepted and refused operations.
    bound_to:
      - TST-MBR-STR-077
      - >-
        services-membership:tests/acceptance/structure/MBR-ACC-0018.acceptance.ts#not_moved: the dues
        product, the settings, the legal-entity link
    provenance: test
    source:
      - >-
        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
      - >-
        services-membership:modules/structure/services/persistence/organizational-unit-dues-products.ts:createDuesProduct
      - >-
        services-membership:tests/acceptance/structure/MBR-ACC-0018.acceptance.ts#not_moved: the dues
        product, the settings, the legal-entity link
    exercises:
      - CAP-MBR-STR-008
      - CAP-MBR-STR-003
  - id: ATS-MBR-STR-008-08
    title: Clearing a local profile exposes program fallback
    category: interaction
    level: api
    proves:
      - BR-CAP-MBR-STR-008-07
      - BR-CAP-MBR-STR-009-12
    preconditions: An isolated workspace contains the records and current versions needed for the case.
    steps: >-
      Save different local and program ordering-profile choices; resolve the sales context, clear the
      local choice and resolve again.
    expected: The local choice is used first and the program choice is used after clearing.
    negative: false
    data_needs: Separate fixture records for the accepted and refused operations.
    bound_to: []
    provenance: proposed
    source:
      - >-
        services-membership:docs/migrations/packages-as-products/README.md#Ordering profiles (added the
        same day, from Commerce's decision Andrew approved at about 15:45 UTC)
      - >-
        services-membership:docs/migrations/packages-as-products/README.md#Ordering profiles (added the
        same day, from Commerce's decision Andrew approved at about 15:45 UTC)
    exercises:
      - CAP-MBR-STR-008
      - CAP-MBR-STR-009
  - id: ATS-MBR-STR-008-09
    title: Workspace authority gates this capability
    category: permission
    level: api
    proves:
      - BR-CAP-MBR-STR-019-01
    preconditions: An isolated workspace contains the records and current versions needed for the case.
    steps: >-
      Exercise the capability’s exposed operations with its read-only and management callers, then repeat
      with application access removed, an unlicensed workspace and an unavailable workspace.
    expected: >-
      Each named operation requires its declared authority; admission failures occur before any record or
      calculated result is exposed.
    negative: true
    data_needs: Separate fixture records for the accepted and refused operations.
    bound_to: []
    provenance: proposed
    source:
      - >-
        services-membership:tests/unit/route-authorization.spec.ts#route authorization: every Membership
        operation names its permission › requires membership.structure.read of every structure read and
        membership.structure.manage of every change
      - >-
        services-membership:modules/configuration/aws/api/configuration.routes.ts:configurationModuleRoutes
      - >-
        services-membership:tests/e2e/terms-api.e2e.spec.ts#the terms API, end to end in process ›
        refuses a caller who holds no key in the tenant
    exercises:
      - CAP-MBR-STR-008
      - CAP-MBR-STR-019
evidence:
  - 'services-membership:modules/structure/tests/unit/accounting-products.spec.ts'
  - 'services-membership:tests/acceptance/structure/MBR-ACC-0023.acceptance.ts'
  - 'services-membership:tests/e2e/packages-as-products.e2e.spec.ts'
  - >-
    services-membership:tests/e2e/packages-as-products.e2e.spec.ts#packages as products, through the API
    › extends a product of type chapter_dues as a unit’s dues product, under the product’s id, with the
    product’s name
  - >-
    services-membership:modules/structure/services/persistence/organizational-unit-dues-products.ts:createDuesProduct
  - >-
    services-membership:modules/structure/tests/unit/accounting-products.spec.ts#the Accounting products
    port › answers a product Accounting no longer has as its id, inactive, hidden, with no product status
  - >-
    services-membership:tests/e2e/packages-as-products.e2e.spec.ts#packages as products, through the API
    › re-points a unit’s dues product at another package at the version just read, 200 with the next
    version
  - >-
    services-membership:modules/structure/services/persistence/organizational-unit-financial-settings.ts:setFinancialSettings
  - >-
    services-membership:docs/migrations/packages-as-products/README.md#Ordering profiles (added the same
    day, from Commerce's decision Andrew approved at about 15:45 UTC)
  - >-
    services-membership:modules/structure/services/finance/accounting-references.ts:checkAccountingReferenceShapes
  - >-
    services-membership:modules/structure/tests/unit/accounting-products.spec.ts#the Accounting products
    port › answers the product’s common fields under the names the package wire kept: inactive is not
    active and not portal visible
  - >-
    services-membership:tests/acceptance/structure/MBR-ACC-0023.acceptance.ts#MBR-ACC-0023 a chapter's
    financial settings
  - >-
    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
  - membership.structure.read
  - membership.structure.manage
  - membership.application.access
  - >-
    services-membership:tests/unit/route-authorization.spec.ts#route authorization: every Membership
    operation names its permission › requires membership.structure.read of every structure read and
    membership.structure.manage of every change
  - 'services-membership:modules/configuration/aws/api/configuration.routes.ts:configurationModuleRoutes'
  - >-
    services-membership:tests/e2e/terms-api.e2e.spec.ts#the terms API, end to end in process › refuses a
    caller who holds no key in the tenant
coverage:
  rule: covered
  transition: not-applicable
  validation: covered
  permission: covered
  edge: covered
  failure: 'gap: FND-MBR-STR-061'
  boundary: 'gap: FND-MBR-STR-061'
  concurrency: covered
  invariant: covered
  interaction: covered
coverage_notes:
  transition: >-
    This capability reads or changes facets without owning a standing transition; the owning lifecycle
    specification carries those transitions.
  failure: >-
    No dedicated scenario establishes this category across the capability’s declared operations and
    design obligations.
  boundary: >-
    No dedicated scenario establishes this category across the capability’s declared operations and
    design obligations.
unproved_rules: []
coverage_obligations:
  permissions:
    - key: membership.structure.read
      scenario_ids:
        - ATS-MBR-STR-019-01
      local_scenario_ids:
        - ATS-MBR-STR-008-09
      coverage: partial
      gap: FND-MBR-STR-061
      provenance: unknown
      source: FND-MBR-STR-061
      note: >-
        These cases establish declared authority or representative admission; exhaustive operation and
        caller combinations remain open.
    - key: membership.structure.manage
      scenario_ids:
        - ATS-MBR-STR-019-01
      local_scenario_ids:
        - ATS-MBR-STR-008-09
      coverage: partial
      gap: FND-MBR-STR-061
      provenance: unknown
      source: FND-MBR-STR-061
      note: >-
        These cases establish declared authority or representative admission; exhaustive operation and
        caller combinations remain open.
    - key: membership.application.access
      scenario_ids:
        - ATS-MBR-STR-019-04
      local_scenario_ids:
        - ATS-MBR-STR-008-09
      coverage: partial
      gap: FND-MBR-STR-061
      provenance: unknown
      source: FND-MBR-STR-061
      note: >-
        These cases establish declared authority or representative admission; exhaustive operation and
        caller combinations remain open.
  state_models: []
  related:
    - capability: CAP-MBR-STR-003
      scenario: ATS-MBR-STR-008-07
      provenance: proposed
    - capability: CAP-MBR-STR-009
      scenario: ATS-MBR-STR-008-08
      provenance: proposed
  invariants:
    - id: INV-DOM-MBR-STR-002-01
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-061
      provenance: unknown
      source: FND-MBR-STR-061
    - id: INV-DOM-MBR-STR-002-02
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-061
      provenance: unknown
      source: FND-MBR-STR-061
    - id: INV-DOM-MBR-STR-002-03
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-061
      provenance: unknown
      source: FND-MBR-STR-061
    - id: INV-DOM-MBR-STR-002-04
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-061
      provenance: unknown
      source: FND-MBR-STR-061
    - id: INV-DOM-MBR-STR-002-05
      scenario_ids:
        - ATS-MBR-STR-008-02
      coverage: specified
      gap: null
      provenance: documented
      source:
        - >-
          services-membership:modules/structure/services/persistence/organizational-unit-dues-products.ts:createDuesProduct
    - id: INV-DOM-MBR-STR-002-06
      scenario_ids:
        - ATS-MBR-STR-008-01
      coverage: specified
      gap: null
      provenance: documented
      source:
        - >-
          services-membership:tests/e2e/packages-as-products.e2e.spec.ts#packages as products, through
          the API › extends a product of type chapter_dues as a unit’s dues product, under the product’s
          id, with the product’s name
    - id: INV-DOM-MBR-STR-002-07
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-061
      provenance: unknown
      source: FND-MBR-STR-061
    - id: INV-DOM-MBR-STR-002-08
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-061
      provenance: unknown
      source: FND-MBR-STR-061
    - id: INV-DOM-MBR-STR-002-09
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-061
      provenance: unknown
      source: FND-MBR-STR-061
  workflows:
    - id: WF-MBR-STR-004
      scenarios:
        - ATS-MBR-STR-008-04
        - ATS-MBR-STR-008-07
        - ATS-MBR-STR-008-08
      unproved_failure_and_concurrency: FND-MBR-STR-061
      provenance: unknown
      source: FND-MBR-STR-061
  workflow_interactions:
    - workflow: WF-MBR-STR-004
      capability: CAP-MBR-STR-012
      scenario_ids:
        - ATS-MBR-STR-012-14
      coverage: specified
      gap: null
      provenance: documented
      source:
        - ATS-MBR-STR-012-14
      note: Cross-capability examples are cited from their owning specifications.
    - workflow: WF-MBR-STR-004
      capability: CAP-MBR-STR-013
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-061
      provenance: unknown
      source: FND-MBR-STR-061
      note: >-
        The shared workflow names both capabilities, but a concrete interaction oracle is not established
        for this pairing.
rule_coverage:
  - rule: BR-CAP-MBR-STR-008-01
    scenarios:
      - ATS-MBR-STR-008-01
    gap: null
    provenance: documented
    source:
      - >-
        services-membership:tests/e2e/packages-as-products.e2e.spec.ts#packages as products, through the
        API › extends a product of type chapter_dues as a unit’s dues product, under the product’s id,
        with the product’s name
  - rule: BR-CAP-MBR-STR-008-02
    scenarios:
      - ATS-MBR-STR-008-02
    gap: null
    provenance: documented
    source:
      - >-
        services-membership:modules/structure/services/persistence/organizational-unit-dues-products.ts:createDuesProduct
  - rule: BR-CAP-MBR-STR-008-03
    scenarios:
      - ATS-MBR-STR-008-03
    gap: null
    provenance: documented
    source:
      - >-
        services-membership:modules/structure/tests/unit/accounting-products.spec.ts#the Accounting
        products port › answers the product’s common fields under the names the package wire kept:
        inactive is not active and not portal visible
  - rule: BR-CAP-MBR-STR-008-04
    scenarios:
      - ATS-MBR-STR-008-04
    gap: null
    provenance: documented
    source:
      - >-
        services-membership:tests/e2e/packages-as-products.e2e.spec.ts#packages as products, through the
        API › re-points a unit’s dues product at another package at the version just read, 200 with the
        next version
  - rule: BR-CAP-MBR-STR-008-06
    scenarios:
      - ATS-MBR-STR-008-05
    gap: null
    provenance: documented
    source:
      - >-
        services-membership:tests/acceptance/structure/MBR-ACC-0023.acceptance.ts#MBR-ACC-0023 a
        chapter's financial settings
  - rule: BR-CAP-MBR-STR-008-07
    scenarios:
      - ATS-MBR-STR-008-06
      - ATS-MBR-STR-008-08
    gap: null
    provenance: documented
    source:
      - >-
        services-membership:tests/acceptance/structure/MBR-ACC-0023.acceptance.ts#MBR-ACC-0023 a
        chapter's financial settings
      - >-
        services-membership:docs/migrations/packages-as-products/README.md#Ordering profiles (added the
        same day, from Commerce's decision Andrew approved at about 15:45 UTC)
      - >-
        services-membership:docs/migrations/packages-as-products/README.md#Ordering profiles (added the
        same day, from Commerce's decision Andrew approved at about 15:45 UTC)
narrative_sources:
  - section: Coverage
    provenance: documented
    source:
      - CAP-MBR-STR-008
      - FND-MBR-STR-061
  - section: Interactions With Related Capabilities
    provenance: proposed
    source:
      - ATS-MBR-STR-008-07
      - ATS-MBR-STR-008-08
---

# Connect unit dues to products and settlement choices: 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-008-01` | `ATS-MBR-STR-008-01` |
| `BR-CAP-MBR-STR-008-02` | `ATS-MBR-STR-008-02` |
| `BR-CAP-MBR-STR-008-03` | `ATS-MBR-STR-008-03` |
| `BR-CAP-MBR-STR-008-04` | `ATS-MBR-STR-008-04` |
| `BR-CAP-MBR-STR-008-06` | `ATS-MBR-STR-008-05` |
| `BR-CAP-MBR-STR-008-07` | `ATS-MBR-STR-008-06`, `ATS-MBR-STR-008-08` |

## Interactions With Related Capabilities

Merge leaves local dues and settlement work on the source. Prepare source dues and financial settings, merge the source, inspect the returned follow-up list and reread the source facets.

Clearing a local profile exposes program fallback. Save different local and program ordering-profile choices; resolve the sales context, clear the local choice and resolve again.
