---
id: ATS-COM-CAT-010
scope: CAP-COM-CAT-010
product_area: commerce
module: catalog
revision: 2
status: proposed
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-COM-CAT-010-01
    title: Built-in audiences retain identity and kind
    level: api
    proves:
      - BR-CAP-COM-CAT-010-01
      - INV-DOM-COM-CAT-004-01
    preconditions: A fresh workspace initializes audiences
    steps: 'List audiences, change Member’s kind and delete Standard'
    expected: Built-in ranks are present and both prohibited mutations fail
    negative: true
    data_needs: none
    bound_to:
      - TST-COM-CAT-061
    provenance: test
    source: >-
      services-commerce:modules/pricing/tests/e2e/pricing-audiences.e2e.spec.js#lists standard for
      everyone at rank 0 and member by eligibility at rank 10, built in, member shown to visitors,
      with no binding yet
    category: invariant
    binding_evidence:
      - >-
        services-commerce:modules/pricing/tests/e2e/pricing-audiences.e2e.spec.js#lists standard for
        everyone at rank 0 and member by eligibility at rank 10, built in, member shown to visitors,
        with no binding yet
      - >-
        services-commerce:modules/pricing/tests/e2e/pricing-audiences.e2e.spec.js#renames a built-in
        and keeps it built in, and refuses it another kind, 409 audience_built_in
      - >-
        services-commerce:modules/pricing/tests/e2e/pricing-audiences.e2e.spec.js#deletes a tenant’s
        own audience, after which it reads 404; refuses a built-in’s delete, 409 audience_built_in
    step_evidence:
      - do: 'List audiences, change Member’s kind and delete Standard'
        provenance: test
        source: >-
          services-commerce:modules/pricing/tests/e2e/pricing-audiences.e2e.spec.js#lists standard
          for everyone at rank 0 and member by eligibility at rank 10, built in, member shown to
          visitors, with no binding yet
    assertions:
      - expect: Built-in ranks are present and both prohibited mutations fail
        provenance: test
        source: >-
          services-commerce:modules/pricing/tests/e2e/pricing-audiences.e2e.spec.js#lists standard
          for everyone at rank 0 and member by eligibility at rank 10, built in, member shown to
          visitors, with no binding yet
  - id: ATS-COM-CAT-010-02
    title: Audience rank and normalized name conflicts are refused
    level: api
    proves:
      - BR-CAP-COM-CAT-010-02
      - BR-CAP-COM-CAT-010-03
      - INV-DOM-COM-CAT-004-02
    preconditions: Member occupies rank ten and its name
    steps: Create another audience at ten and under a spaced case variant of Member
    expected: Both refusals identify the conflict
    negative: true
    data_needs: none
    bound_to:
      - TST-COM-CAT-061
      - TST-COM-CAT-073
    provenance: test
    source: >-
      services-commerce:modules/pricing/tests/e2e/pricing-audiences.e2e.spec.js#answers 400 with the
      problem code audience_rank_taken to a rank another audience holds, creating nothing
    category: validation
    binding_evidence:
      - >-
        services-commerce:modules/pricing/tests/e2e/pricing-audiences.e2e.spec.js#answers 400 with
        the problem code audience_rank_taken to a rank another audience holds, creating nothing
      - >-
        services-commerce:modules/pricing/tests/integration/services/persistence/pricing-audiences.integration.spec.js#refuses
        a create to the same name in other letter case and spacing, 409 audience_name_taken naming
        the existing audience
      - >-
        services-commerce:modules/pricing/tests/integration/services/persistence/pricing-audiences.integration.spec.js#treats
        repeated inner spaces as one space
    step_evidence:
      - do: Create another audience at ten and under a spaced case variant of Member
        provenance: test
        source: >-
          services-commerce:modules/pricing/tests/e2e/pricing-audiences.e2e.spec.js#answers 400 with
          the problem code audience_rank_taken to a rank another audience holds, creating nothing
    assertions:
      - expect: Both refusals identify the conflict
        provenance: test
        source: >-
          services-commerce:modules/pricing/tests/e2e/pricing-audiences.e2e.spec.js#answers 400 with
          the problem code audience_rank_taken to a rank another audience holds, creating nothing
  - id: ATS-COM-CAT-010-03
    title: Audience qualification fields follow the chosen kind
    level: api
    proves:
      - BR-CAP-COM-CAT-010-04
    preconditions: Audience creation can select different kinds
    steps: Omit operations for an operation audience and bind eligibility to an everyone audience
    expected: Both inconsistent definitions fail
    negative: true
    data_needs: none
    bound_to:
      - TST-COM-CAT-066
    provenance: test
    source: >-
      services-commerce:modules/pricing/tests/integration/db/member-pricing-tables.table.integration.spec.js#refuses
      an operation audience without an operation, and operations on another kind, by
      pricing_audiences_operations_check
    category: validation
    binding_evidence:
      - >-
        services-commerce:modules/pricing/tests/integration/db/member-pricing-tables.table.integration.spec.js#refuses
        an operation audience without an operation, and operations on another kind, by
        pricing_audiences_operations_check
      - >-
        services-commerce:modules/pricing/tests/integration/db/member-pricing-tables.table.integration.spec.js#refuses
        a binding on an audience that is not an eligibility one, by pricing_audiences_binding_check
    step_evidence:
      - do: Omit operations for an operation audience and bind eligibility to an everyone audience
        provenance: test
        source: >-
          services-commerce:modules/pricing/tests/integration/db/member-pricing-tables.table.integration.spec.js#refuses
          an operation audience without an operation, and operations on another kind, by
          pricing_audiences_operations_check
    assertions:
      - expect: Both inconsistent definitions fail
        provenance: test
        source: >-
          services-commerce:modules/pricing/tests/integration/db/member-pricing-tables.table.integration.spec.js#refuses
          an operation audience without an operation, and operations on another kind, by
          pricing_audiences_operations_check
  - id: ATS-COM-CAT-010-04
    title: Deactivation preserves prices while removing qualification
    level: api
    proves:
      - BR-CAP-COM-CAT-010-05
      - BR-CAP-COM-CAT-010-06
      - AS-JNY-COM-CAT-002-01
    preconditions: Retiree is referenced by a product price
    steps: 'Attempt deletion, deactivate the audience and price the buyer'
    expected: Deletion reports usage; deactivation succeeds and pricing excludes the inactive audience
    negative: true
    data_needs: A product price row
    bound_to:
      - TST-COM-CAT-061
      - TST-COM-CAT-070
    provenance: test
    source: >-
      services-commerce:modules/pricing/tests/e2e/pricing-audiences.e2e.spec.js#refuses the delete
      409 audience_in_use with the sentence and the details
    category: transition
    binding_evidence:
      - >-
        services-commerce:modules/pricing/tests/e2e/pricing-audiences.e2e.spec.js#refuses the delete
        409 audience_in_use with the sentence and the details
      - >-
        services-commerce:modules/pricing/tests/e2e/pricing-audiences.e2e.spec.js#still deactivates
        the audience
      - >-
        services-commerce:modules/pricing/tests/integration/services/inputs/pricing-inputs.integration.spec.js#loads
        the active audiences in rank order, the inactive left out, and the period each schedule is
        in at the instant
    step_evidence:
      - do: 'Attempt deletion, deactivate the audience and price the buyer'
        provenance: test
        source: >-
          services-commerce:modules/pricing/tests/e2e/pricing-audiences.e2e.spec.js#refuses the
          delete 409 audience_in_use with the sentence and the details
    assertions:
      - expect: Deletion reports usage; deactivation succeeds and pricing excludes the inactive audience
        provenance: test
        source: >-
          services-commerce:modules/pricing/tests/e2e/pricing-audiences.e2e.spec.js#refuses the
          delete 409 audience_in_use with the sentence and the details
  - id: ATS-COM-CAT-010-05
    title: Unbound eligibility produces a warning rather than qualification
    level: unit
    proves:
      - BR-CAP-COM-CAT-010-07
    preconditions: An eligibility audience has no binding selected
    steps: Resolve qualification for a buyer
    expected: The audience is absent from qualification and identified in a warning
    negative: false
    data_needs: none
    bound_to:
      - TST-COM-CAT-085
    provenance: test
    source: >-
      services-commerce:modules/pricing/tests/unit/engine/step-2-audience-resolution.spec.js#warns
      of an audience with no binding, and holds nobody for it; a binding the batch did not answer is
      simply not held
    category: edge
    binding_evidence:
      - >-
        services-commerce:modules/pricing/tests/unit/engine/step-2-audience-resolution.spec.js#warns
        of an audience with no binding, and holds nobody for it; a binding the batch did not answer
        is simply not held
    step_evidence:
      - do: Resolve qualification for a buyer
        provenance: test
        source: >-
          services-commerce:modules/pricing/tests/unit/engine/step-2-audience-resolution.spec.js#warns
          of an audience with no binding, and holds nobody for it; a binding the batch did not
          answer is simply not held
    assertions:
      - expect: The audience is absent from qualification and identified in a warning
        provenance: test
        source: >-
          services-commerce:modules/pricing/tests/unit/engine/step-2-audience-resolution.spec.js#warns
          of an audience with no binding, and holds nobody for it; a binding the batch did not
          answer is simply not held
  - id: ATS-COM-CAT-010-06
    title: Audience writes require permission and current version
    level: api
    proves:
      - BR-CAP-COM-CAT-010-10
      - BR-CAP-COM-CAT-010-11
    preconditions: A reader and version-two audience are available
    steps: Write as the reader and replace from version one
    expected: Permission and concurrency refusals prevent both changes
    negative: true
    data_needs: Read-exclusively persona
    bound_to:
      - TST-COM-CAT-062
      - TST-COM-CAT-061
    provenance: test
    source: >-
      services-commerce:modules/pricing/tests/e2e/pricing-configuration-security.e2e.spec.js#is
      refused the creates, replacements and deletes, 403 permission_missing, each leaving the record
      as it was
    category: permission
    binding_evidence:
      - >-
        services-commerce:modules/pricing/tests/e2e/pricing-configuration-security.e2e.spec.js#is
        refused the creates, replacements and deletes, 403 permission_missing, each leaving the
        record as it was
      - >-
        services-commerce:modules/pricing/tests/e2e/pricing-audiences.e2e.spec.js#answers 409 to a
        stale version, 400 to a body whose id is not the path’s, and 400 to a replacement without
        its version
    step_evidence:
      - do: Write as the reader and replace from version one
        provenance: test
        source: >-
          services-commerce:modules/pricing/tests/e2e/pricing-configuration-security.e2e.spec.js#is
          refused the creates, replacements and deletes, 403 permission_missing, each leaving the
          record as it was
    assertions:
      - expect: Permission and concurrency refusals prevent both changes
        provenance: test
        source: >-
          services-commerce:modules/pricing/tests/e2e/pricing-configuration-security.e2e.spec.js#is
          refused the creates, replacements and deletes, 403 permission_missing, each leaving the
          record as it was
  - id: ATS-COM-CAT-010-07
    title: Audience editing returns to the saved view
    level: browser
    proves:
      - AS-JNY-COM-CAT-002-02
    preconditions: The browser uses Commerce mock fixtures
    steps: 'Open an audience, edit it and save'
    expected: The full-width view presents the changed information
    negative: false
    data_needs: Console mock
    bound_to:
      - TST-COM-CAT-006
    provenance: test
    source: >-
      react-console:e2e/mock/commerce-view-edit.mock.spec.ts#open an audience on a full-width view,
      edit it and save back to the view
    category: rule
    binding_evidence:
      - >-
        react-console:e2e/mock/commerce-view-edit.mock.spec.ts#open an audience on a full-width
        view, edit it and save back to the view
    step_evidence:
      - do: 'Open an audience, edit it and save'
        provenance: test
        source: >-
          react-console:e2e/mock/commerce-view-edit.mock.spec.ts#open an audience on a full-width
          view, edit it and save back to the view
    assertions:
      - expect: The full-width view presents the changed information
        provenance: test
        source: >-
          react-console:e2e/mock/commerce-view-edit.mock.spec.ts#open an audience on a full-width
          view, edit it and save back to the view
  - id: ATS-COM-CAT-010-08
    title: Audience protection refuses the protected write
    category: invariant
    level: api
    proves:
      - BR-CAP-COM-CAT-010-12
    preconditions: Separate otherwise editable records use full protection and deletion-only protection.
    steps: >-
      Replace and delete the fully protected record, then replace and delete the deletion-only
      protected record; reread both.
    expected: >-
      The full-protection requests refuse; the deletion-only replacement succeeds and removal
      refuses; refused writes preserve the stored record.
    negative: true
    data_needs: Run-owned workspace and records; fixed clock where dates are exercised.
    bound_to: []
    provenance: proposed
    source:
      - 'services-commerce:modules/pricing/services/persistence/pricing-audiences.ts'
    step_evidence:
      - do: >-
          Replace and delete the fully protected record, then replace and delete the deletion-only
          protected record; reread both.
        provenance: proposed
        source:
          - 'services-commerce:modules/pricing/services/persistence/pricing-audiences.ts'
    assertions:
      - expect: >-
          The full-protection requests refuse; the deletion-only replacement succeeds and removal
          refuses; refused writes preserve the stored record.
        provenance: proposed
        source:
          - 'services-commerce:modules/pricing/services/persistence/pricing-audiences.ts'
  - id: ATS-COM-CAT-010-09
    title: Audience deactivation changes a configured price strategy
    category: interaction
    level: api
    proves:
      - BR-CAP-COM-CAT-010-06
      - BR-CAP-COM-CAT-012-03
    preconditions: Member and Student qualify for one product.
    steps: 'Select rank pricing, deactivate the first audience, quote, reactivate and quote again.'
    expected: >-
      The inactive audience is skipped without losing its stored price and returns to selection
      after reactivation.
    negative: false
    data_needs: Run-owned workspace and records; fixed clock where dates are exercised.
    bound_to: []
    provenance: proposed
    source:
      - >-
        services-commerce:modules/pricing/tests/integration/services/inputs/pricing-inputs.integration.spec.js#loads
        the active audiences in rank order, the inactive left out, and the period each schedule is
        in at the instant
      - >-
        services-commerce:modules/pricing/tests/e2e/product-purchasing-settings.e2e.spec.js#prices
        the same buyer at the member price under rank, Member coming before Student members
    exercises:
      - CAP-COM-CAT-010
      - CAP-COM-CAT-012
    workflows:
      - WF-COM-CAT-009
    step_evidence:
      - do: 'Select rank pricing, deactivate the first audience, quote, reactivate and quote again.'
        provenance: proposed
        source:
          - >-
            services-commerce:modules/pricing/tests/integration/services/inputs/pricing-inputs.integration.spec.js#loads
            the active audiences in rank order, the inactive left out, and the period each schedule
            is in at the instant
          - >-
            services-commerce:modules/pricing/tests/e2e/product-purchasing-settings.e2e.spec.js#prices
            the same buyer at the member price under rank, Member coming before Student members
    assertions:
      - expect: >-
          The inactive audience is skipped without losing its stored price and returns to selection
          after reactivation.
        provenance: proposed
        source:
          - >-
            services-commerce:modules/pricing/tests/integration/services/inputs/pricing-inputs.integration.spec.js#loads
            the active audiences in rank order, the inactive left out, and the period each schedule
            is in at the instant
          - >-
            services-commerce:modules/pricing/tests/e2e/product-purchasing-settings.e2e.spec.js#prices
            the same buyer at the member price under rank, Member coming before Student members
  - id: ATS-COM-CAT-010-10
    title: Removing an audience binding removes qualification
    category: interaction
    level: api
    proves:
      - BR-CAP-COM-CAT-010-07
      - BR-CAP-COM-CAT-013-02
    preconditions: An eligibility audience has a selected binding and a price.
    steps: 'Quote an eligible buyer, remove the binding, then quote again.'
    expected: The second quote omits that audience and explains the missing binding.
    negative: false
    data_needs: Run-owned workspace and records; fixed clock where dates are exercised.
    bound_to: []
    provenance: proposed
    source:
      - >-
        services-commerce:modules/pricing/tests/unit/engine/step-2-audience-resolution.spec.js#warns
        of an audience with no binding, and holds nobody for it; a binding the batch did not answer
        is simply not held
      - >-
        services-commerce:modules/pricing/tests/unit/engine/step-2-audience-resolution.spec.js#does
        not qualify for an ineligible decision, an indeterminate one, a provisional one or one under
        review, and says why
    exercises:
      - CAP-COM-CAT-010
      - CAP-COM-CAT-013
    workflows:
      - WF-COM-CAT-009
    step_evidence:
      - do: 'Quote an eligible buyer, remove the binding, then quote again.'
        provenance: proposed
        source:
          - >-
            services-commerce:modules/pricing/tests/unit/engine/step-2-audience-resolution.spec.js#warns
            of an audience with no binding, and holds nobody for it; a binding the batch did not
            answer is simply not held
          - >-
            services-commerce:modules/pricing/tests/unit/engine/step-2-audience-resolution.spec.js#does
            not qualify for an ineligible decision, an indeterminate one, a provisional one or one
            under review, and says why
    assertions:
      - expect: The second quote omits that audience and explains the missing binding.
        provenance: proposed
        source:
          - >-
            services-commerce:modules/pricing/tests/unit/engine/step-2-audience-resolution.spec.js#warns
            of an audience with no binding, and holds nobody for it; a binding the batch did not
            answer is simply not held
          - >-
            services-commerce:modules/pricing/tests/unit/engine/step-2-audience-resolution.spec.js#does
            not qualify for an ineligible decision, an indeterminate one, a provisional one or one
            under review, and says why
  - id: ATS-COM-CAT-010-11
    title: Provisioning reruns preserve audience and placement edits
    category: interaction
    level: api
    proves:
      - BR-CAP-COM-CAT-010-01
      - BR-CAP-COM-CAT-019-02
    preconditions: A new workspace has built-in audiences and storefront placements.
    steps: >-
      Change a permitted audience field and a placement cap; rerun both seed operations and verify
      setup.
    expected: Required setup exists once and the customer’s saved settings remain.
    negative: false
    data_needs: Run-owned workspace and records; fixed clock where dates are exercised.
    bound_to: []
    provenance: proposed
    source:
      - >-
        services-commerce:modules/pricing/tests/e2e/pricing-audiences.e2e.spec.js#lists standard for
        everyone at rank 0 and member by eligibility at rank 10, built in, member shown to visitors,
        with no binding yet
      - >-
        services-commerce:modules/recommendations/tests/e2e/recommendation-rules.e2e.spec.js#refuses
        a cap above the placement’s, 400 max_offers_exceeds_placement
    exercises:
      - CAP-COM-CAT-010
      - CAP-COM-CAT-019
    workflows:
      - WF-COM-CAT-019
    step_evidence:
      - do: >-
          Change a permitted audience field and a placement cap; rerun both seed operations and
          verify setup.
        provenance: proposed
        source:
          - >-
            services-commerce:modules/pricing/tests/e2e/pricing-audiences.e2e.spec.js#lists standard
            for everyone at rank 0 and member by eligibility at rank 10, built in, member shown to
            visitors, with no binding yet
          - >-
            services-commerce:modules/recommendations/tests/e2e/recommendation-rules.e2e.spec.js#refuses
            a cap above the placement’s, 400 max_offers_exceeds_placement
    assertions:
      - expect: Required setup exists once and the customer’s saved settings remain.
        provenance: proposed
        source:
          - >-
            services-commerce:modules/pricing/tests/e2e/pricing-audiences.e2e.spec.js#lists standard
            for everyone at rank 0 and member by eligibility at rank 10, built in, member shown to
            visitors, with no binding yet
          - >-
            services-commerce:modules/recommendations/tests/e2e/recommendation-rules.e2e.spec.js#refuses
            a cap above the placement’s, 400 max_offers_exceeds_placement
  - id: ATS-COM-CAT-010-12
    title: Special-price handover realization is exercised across every declared move
    category: transition
    level: api
    proves:
      - BR-CAP-COM-CAT-010-01
      - BR-CAP-COM-CAT-010-02
    preconditions: >-
      Independent run-owned records start in each declared origin state; guarded variants omit one
      required condition at a time.
    steps: >-
      For each transition case, establish the origin, apply its trigger with the guard satisfied,
      read the resulting state and side effects, then repeat on a separate record with a required
      guard absent.
    expected: >-
      Every allowed case reaches its stated destination and retains its declared side effects;
      failed guards preserve the originating record except for the separately documented partial
      offer action.
    negative: true
    data_needs: Run-owned workspace and records; fixed clock where dates are exercised.
    bound_to: []
    provenance: proposed
    source:
      - >-
        rhythm-v2-docs:specs/commerce/catalog/design/state-models/STATE-COM-CAT-006-special-price-handover-realization.md#STATE-COM-CAT-006
      - >-
        services-commerce:modules/pricing/tests/integration/services/handovers/audience-handover-realization.integration.spec.js#leaves
        a handover whose rank another audience of the tenant holds, naming the rank
      - >-
        services-commerce:modules/pricing/tests/integration/services/handovers/audience-handover-realization.integration.spec.js#leaves
        a handover whose rank another audience of the tenant holds, naming the rank
      - 'services-commerce:modules/pricing/services/handovers/audience-handover-realization.ts'
      - 'services-commerce:modules/pricing/services/handovers/audience-handover-realization.ts'
      - 'services-commerce:modules/pricing/services/handovers/audience-handover-realization.ts'
    state_model: STATE-COM-CAT-006
    transition_cases:
      - from: handed over
        to: audience prepared
        trigger: Realization processes a pending handover.
        guard: The required rank must be available in the workspace.
        provenance: proposed
        source:
          - >-
            services-commerce:modules/pricing/tests/integration/services/handovers/audience-handover-realization.integration.spec.js#leaves
            a handover whose rank another audience of the tenant holds, naming the rank
          - >-
            rhythm-v2-docs:specs/commerce/catalog/design/state-models/STATE-COM-CAT-006-special-price-handover-realization.md#STATE-COM-CAT-006
      - from: handed over
        to: unresolved
        trigger: Realization encounters an occupied audience rank.
        guard: A different audience must already occupy the desired rank.
        provenance: proposed
        source:
          - >-
            services-commerce:modules/pricing/tests/integration/services/handovers/audience-handover-realization.integration.spec.js#leaves
            a handover whose rank another audience of the tenant holds, naming the rank
          - >-
            rhythm-v2-docs:specs/commerce/catalog/design/state-models/STATE-COM-CAT-006-special-price-handover-realization.md#STATE-COM-CAT-006
      - from: audience prepared
        to: realized
        trigger: The binding port returns the definition and binding.
        guard: The binding port must accept the retained criteria.
        provenance: proposed
        source:
          - 'services-commerce:modules/pricing/services/handovers/audience-handover-realization.ts'
          - >-
            rhythm-v2-docs:specs/commerce/catalog/design/state-models/STATE-COM-CAT-006-special-price-handover-realization.md#STATE-COM-CAT-006
      - from: audience prepared
        to: unresolved
        trigger: Binding creation rejects the retained criteria.
        guard: No additional condition applies.
        provenance: proposed
        source:
          - 'services-commerce:modules/pricing/services/handovers/audience-handover-realization.ts'
          - >-
            rhythm-v2-docs:specs/commerce/catalog/design/state-models/STATE-COM-CAT-006-special-price-handover-realization.md#STATE-COM-CAT-006
      - from: unresolved
        to: audience prepared
        trigger: A later realization run can prepare the audience.
        guard: The requested rank must be available.
        provenance: proposed
        source:
          - 'services-commerce:modules/pricing/services/handovers/audience-handover-realization.ts'
          - >-
            rhythm-v2-docs:specs/commerce/catalog/design/state-models/STATE-COM-CAT-006-special-price-handover-realization.md#STATE-COM-CAT-006
    step_evidence:
      - do: >-
          For each transition case, establish the origin, apply its trigger with the guard
          satisfied, read the resulting state and side effects, then repeat on a separate record
          with a required guard absent.
        provenance: proposed
        source:
          - >-
            rhythm-v2-docs:specs/commerce/catalog/design/state-models/STATE-COM-CAT-006-special-price-handover-realization.md#STATE-COM-CAT-006
          - >-
            services-commerce:modules/pricing/tests/integration/services/handovers/audience-handover-realization.integration.spec.js#leaves
            a handover whose rank another audience of the tenant holds, naming the rank
          - >-
            services-commerce:modules/pricing/tests/integration/services/handovers/audience-handover-realization.integration.spec.js#leaves
            a handover whose rank another audience of the tenant holds, naming the rank
          - 'services-commerce:modules/pricing/services/handovers/audience-handover-realization.ts'
          - 'services-commerce:modules/pricing/services/handovers/audience-handover-realization.ts'
          - 'services-commerce:modules/pricing/services/handovers/audience-handover-realization.ts'
    assertions:
      - expect: >-
          Every allowed case reaches its stated destination and retains its declared side effects;
          failed guards preserve the originating record except for the separately documented partial
          offer action.
        provenance: proposed
        source:
          - >-
            rhythm-v2-docs:specs/commerce/catalog/design/state-models/STATE-COM-CAT-006-special-price-handover-realization.md#STATE-COM-CAT-006
          - >-
            services-commerce:modules/pricing/tests/integration/services/handovers/audience-handover-realization.integration.spec.js#leaves
            a handover whose rank another audience of the tenant holds, naming the rank
          - >-
            services-commerce:modules/pricing/tests/integration/services/handovers/audience-handover-realization.integration.spec.js#leaves
            a handover whose rank another audience of the tenant holds, naming the rank
          - 'services-commerce:modules/pricing/services/handovers/audience-handover-realization.ts'
          - 'services-commerce:modules/pricing/services/handovers/audience-handover-realization.ts'
          - 'services-commerce:modules/pricing/services/handovers/audience-handover-realization.ts'
  - id: ATS-COM-CAT-010-13
    title: Deactivation preserves a referenced audience price
    category: invariant
    level: api
    proves:
      - INV-DOM-COM-CAT-004-03
      - BR-CAP-COM-CAT-010-05
    preconditions: A product price refers to Retiree and the buyer qualifies.
    steps: >-
      Request audience deletion, deactivate and quote, inspect the price row, reactivate and quote
      again.
    expected: >-
      Deletion identifies the retaining product, the price row survives and the audience returns to
      qualification after reactivation.
    negative: true
    data_needs: Run-owned workspace and records; fixed clock where dates are exercised.
    bound_to: []
    provenance: proposed
    source:
      - >-
        services-commerce:modules/pricing/tests/integration/services/persistence/pricing-audiences.integration.spec.js#refuses
        409 audience_in_use, naming the products and their count, and keeps the audience
      - >-
        rhythm-v2-docs:specs/commerce/catalog/design/objects/DOM-COM-CAT-004-price.md#DOM-COM-CAT-004
    verification_note: >-
      This design references the invariant; executable binding awaits an assertion-by-assertion
      comparison with this complete scenario.
    step_evidence:
      - do: >-
          Request audience deletion, deactivate and quote, inspect the price row, reactivate and
          quote again.
        provenance: proposed
        source:
          - >-
            services-commerce:modules/pricing/tests/integration/services/persistence/pricing-audiences.integration.spec.js#refuses
            409 audience_in_use, naming the products and their count, and keeps the audience
          - >-
            rhythm-v2-docs:specs/commerce/catalog/design/objects/DOM-COM-CAT-004-price.md#DOM-COM-CAT-004
    assertions:
      - expect: >-
          Deletion identifies the retaining product, the price row survives and the audience returns
          to qualification after reactivation.
        provenance: proposed
        source:
          - >-
            services-commerce:modules/pricing/tests/integration/services/persistence/pricing-audiences.integration.spec.js#refuses
            409 audience_in_use, naming the products and their count, and keeps the audience
          - >-
            rhythm-v2-docs:specs/commerce/catalog/design/objects/DOM-COM-CAT-004-price.md#DOM-COM-CAT-004
evidence:
  - 'Pinned service inputs: test sources in scenario bindings'
  - 'Pinned console inputs: console sources in scenario bindings'
  - >-
    rhythm-v2-docs:specs/commerce/catalog/planning/capabilities/CAP-COM-CAT-010-define-the-groups-of-buyers-that-get-their-own-price.md#CAP-COM-CAT-010
  - >-
    rhythm-v2-docs:specs/commerce/catalog/design/workflows/WF-COM-CAT-009-quote-a-price.md#WF-COM-CAT-009
  - >-
    rhythm-v2-docs:specs/commerce/catalog/design/workflows/WF-COM-CAT-011-realize-accounting-s-special-price-handovers.md#WF-COM-CAT-011
  - >-
    rhythm-v2-docs:specs/commerce/catalog/design/workflows/WF-COM-CAT-019-prepare-a-new-workspace-s-built-in-audiences.md#WF-COM-CAT-019
  - >-
    rhythm-v2-docs:specs/commerce/catalog/design/workflows/WF-COM-CAT-021-reorder-audience-ranks.md#WF-COM-CAT-021
product_intent: proposed
coverage:
  rule: covered
  transition: covered
  validation: covered
  permission: covered
  edge: covered
  failure: 'gap: FND-COM-CAT-064'
  boundary: 'gap: FND-COM-CAT-064'
  concurrency: 'gap: FND-COM-CAT-064'
  invariant: covered
  interaction: covered
coverage_notes:
  failure: >-
    No complete failure scenario is established by this back-fill; the finding records the missing
    proof.
  boundary: >-
    No complete boundary scenario is established by this back-fill; the finding records the missing
    proof.
  concurrency: Concurrent execution has no complete scenario; sequential retry is insufficient proof.
permission_coverage:
  - key: commerce.pricing-audiences.read
    coverage: 'gap: FND-COM-CAT-064'
    reason: >-
      Existing permission examples cover selected personas, not the independent allow and deny
      matrix for every named key.
    provenance: unknown
    source:
      - 'rhythm-v2-docs:specs/commerce/catalog/FINDINGS.md#FND-COM-CAT-064'
  - key: commerce.pricing-audiences.create
    coverage: 'gap: FND-COM-CAT-064'
    reason: >-
      Existing permission examples cover selected personas, not the independent allow and deny
      matrix for every named key.
    provenance: unknown
    source:
      - 'rhythm-v2-docs:specs/commerce/catalog/FINDINGS.md#FND-COM-CAT-064'
  - key: commerce.pricing-audiences.update
    coverage: 'gap: FND-COM-CAT-064'
    reason: >-
      Existing permission examples cover selected personas, not the independent allow and deny
      matrix for every named key.
    provenance: unknown
    source:
      - 'rhythm-v2-docs:specs/commerce/catalog/FINDINGS.md#FND-COM-CAT-064'
  - key: commerce.pricing-audiences.delete
    coverage: 'gap: FND-COM-CAT-064'
    reason: >-
      Existing permission examples cover selected personas, not the independent allow and deny
      matrix for every named key.
    provenance: unknown
    source:
      - 'rhythm-v2-docs:specs/commerce/catalog/FINDINGS.md#FND-COM-CAT-064'
  - key: commerce.pricing-audiences.bulk
    coverage: 'gap: FND-COM-CAT-064'
    reason: >-
      Existing permission examples cover selected personas, not the independent allow and deny
      matrix for every named key.
    provenance: unknown
    source:
      - 'rhythm-v2-docs:specs/commerce/catalog/FINDINGS.md#FND-COM-CAT-064'
---

# Configure qualifying price audiences: Capability Test Specification

## Coverage

| Rule | Proof Scenario or Gap |
|---|---|
| `BR-CAP-COM-CAT-010-01` | `ATS-COM-CAT-010-01`, `ATS-COM-CAT-010-11`, `ATS-COM-CAT-010-12` |
| `BR-CAP-COM-CAT-010-02` | `ATS-COM-CAT-010-02`, `ATS-COM-CAT-010-12` |
| `BR-CAP-COM-CAT-010-03` | `ATS-COM-CAT-010-02` |
| `BR-CAP-COM-CAT-010-04` | `ATS-COM-CAT-010-03` |
| `BR-CAP-COM-CAT-010-05` | `ATS-COM-CAT-010-04`, `ATS-COM-CAT-010-13` |
| `BR-CAP-COM-CAT-010-06` | `ATS-COM-CAT-010-04`, `ATS-COM-CAT-010-09` |
| `BR-CAP-COM-CAT-010-07` | `ATS-COM-CAT-010-05`, `ATS-COM-CAT-010-10` |
| `BR-CAP-COM-CAT-010-10` | `ATS-COM-CAT-010-06` |
| `BR-CAP-COM-CAT-010-11` | `ATS-COM-CAT-010-06` |
| `BR-CAP-COM-CAT-010-12` | `ATS-COM-CAT-010-08` |

## Interactions With Related Capabilities

Audience deactivation changes a configured price strategy. Removing an audience binding removes qualification. Provisioning reruns preserve audience and placement edits.

Coverage describes specified proof. A binding names the existing assertions that contribute to it; proposed designs remain unexecuted.
