---
id: ATS-COM-CAT-008
scope: CAP-COM-CAT-008
product_area: commerce
module: catalog
revision: 2
status: proposed
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-COM-CAT-008-01
    title: Visibility removes inactive or unavailable products
    level: unit
    proves:
      - BR-CAP-COM-CAT-008-01
    preconditions: 'Products are retired, outside sale dates or hidden from portal display'
    steps: Evaluate storefront visibility
    expected: Each exclusion returns its reason
    negative: false
    data_needs: none
    bound_to:
      - TST-COM-CAT-027
    provenance: test
    source: >-
      services-commerce:modules/catalog/tests/unit/storefront/storefront-visibility.spec.js#removes
      a retired or inactive product
    category: rule
    binding_evidence:
      - >-
        services-commerce:modules/catalog/tests/unit/storefront/storefront-visibility.spec.js#removes
        a retired or inactive product
      - >-
        services-commerce:modules/catalog/tests/unit/storefront/storefront-visibility.spec.js#removes
        a product not yet on sale, and one whose sale has ended (the end exclusive)
      - >-
        services-commerce:modules/catalog/tests/unit/storefront/storefront-visibility.spec.js#removes
        a product hidden from the portal
    step_evidence:
      - do: Evaluate storefront visibility
        provenance: test
        source: >-
          services-commerce:modules/catalog/tests/unit/storefront/storefront-visibility.spec.js#removes
          a retired or inactive product
    assertions:
      - expect: Each exclusion returns its reason
        provenance: test
        source: >-
          services-commerce:modules/catalog/tests/unit/storefront/storefront-visibility.spec.js#removes
          a retired or inactive product
  - id: ATS-COM-CAT-008-02
    title: Eligibility changes visibility after authentication
    level: api
    proves:
      - BR-CAP-COM-CAT-008-02
    preconditions: The dinner requires membership eligibility
    steps: Browse anonymously and as eligible and ineligible contacts
    expected: >-
      Anonymous browsing retains a warning, eligible browsing retains the item and ineligible
      browsing excludes it
    negative: false
    data_needs: Fixture eligibility
    bound_to:
      - TST-COM-CAT-023
    provenance: test
    source: >-
      services-commerce:modules/catalog/tests/integration/services/storefront/storefront-listings.integration.spec.js#is
      not evaluated for eligibility: a bound product is shown, flagged that signing in may change
      its availability
    category: interaction
    binding_evidence:
      - >-
        services-commerce:modules/catalog/tests/integration/services/storefront/storefront-listings.integration.spec.js#is
        not evaluated for eligibility: a bound product is shown, flagged that signing in may change
        its availability
      - >-
        services-commerce:modules/catalog/tests/integration/services/storefront/storefront-listings.integration.spec.js#keeps
        the dinner for a member the binding qualifies
      - >-
        services-commerce:modules/catalog/tests/integration/services/storefront/storefront-listings.integration.spec.js#removes
        the dinner for a stranger the binding refuses (rule 4)
    step_evidence:
      - do: Browse anonymously and as eligible and ineligible contacts
        provenance: test
        source: >-
          services-commerce:modules/catalog/tests/integration/services/storefront/storefront-listings.integration.spec.js#is
          not evaluated for eligibility: a bound product is shown, flagged that signing in may
          change its availability
    assertions:
      - expect: >-
          Anonymous browsing retains a warning, eligible browsing retains the item and ineligible
          browsing excludes it
        provenance: test
        source: >-
          services-commerce:modules/catalog/tests/integration/services/storefront/storefront-listings.integration.spec.js#is
          not evaluated for eligibility: a bound product is shown, flagged that signing in may
          change its availability
  - id: ATS-COM-CAT-008-03
    title: Public and member browsing use different price presentations
    level: api
    proves:
      - BR-CAP-COM-CAT-008-03
      - BR-CAP-COM-CAT-008-04
      - AS-JNY-COM-CAT-003-01
    preconditions: Member pricing is marked for public display
    steps: Read as visitor and member
    expected: >-
      The visitor sees Standard 25 dollars and Member 20 dollars with a notice; the member receives
      20-dollar pricing
    negative: false
    data_needs: Priced products
    bound_to:
      - TST-COM-CAT-016
    provenance: test
    source: >-
      services-commerce:modules/catalog/tests/e2e/storefront.e2e.spec.js#shows the audiences marked
      for public display beside the Standard price (D10): the Members price 2000, with its audience
    category: interaction
    binding_evidence:
      - >-
        services-commerce:modules/catalog/tests/e2e/storefront.e2e.spec.js#shows the audiences
        marked for public display beside the Standard price (D10): the Members price 2000, with its
        audience
      - >-
        services-commerce:modules/catalog/tests/e2e/storefront.e2e.spec.js#prices a portal member as
        themselves (the recorded member: the member price, nothing signing in could change)
    step_evidence:
      - do: Read as visitor and member
        provenance: test
        source: >-
          services-commerce:modules/catalog/tests/e2e/storefront.e2e.spec.js#shows the audiences
          marked for public display beside the Standard price (D10): the Members price 2000, with
          its audience
    assertions:
      - expect: >-
          The visitor sees Standard 25 dollars and Member 20 dollars with a notice; the member
          receives 20-dollar pricing
        provenance: test
        source: >-
          services-commerce:modules/catalog/tests/e2e/storefront.e2e.spec.js#shows the audiences
          marked for public display beside the Standard price (D10): the Members price 2000, with
          its audience
  - id: ATS-COM-CAT-008-04
    title: Remaining display restores the shelf quantity
    level: unit
    proves:
      - BR-CAP-COM-CAT-008-07
    preconditions: The listing enables counts and has three units on hand
    steps: Request availability presentation
    expected: The response reports three remaining alongside the availability word
    negative: false
    data_needs: none
    bound_to:
      - TST-COM-CAT-026
    provenance: test
    source: >-
      services-commerce:modules/catalog/tests/unit/storefront/storefront-availability.spec.js#shows
      the units on hand when the listing shows its remaining count
    category: rule
    binding_evidence:
      - >-
        services-commerce:modules/catalog/tests/unit/storefront/storefront-availability.spec.js#shows
        the units on hand when the listing shows its remaining count
      - >-
        services-commerce:modules/catalog/tests/unit/storefront/storefront-availability.spec.js#shows
        no count when the listing does not show its remaining count
    step_evidence:
      - do: Request availability presentation
        provenance: test
        source: >-
          services-commerce:modules/catalog/tests/unit/storefront/storefront-availability.spec.js#shows
          the units on hand when the listing shows its remaining count
    assertions:
      - expect: The response reports three remaining alongside the availability word
        provenance: test
        source: >-
          services-commerce:modules/catalog/tests/unit/storefront/storefront-availability.spec.js#shows
          the units on hand when the listing shows its remaining count
  - id: ATS-COM-CAT-008-05
    title: Closed stores and excluded pages return appropriate absence
    level: api
    proves:
      - BR-CAP-COM-CAT-008-08
      - AS-JNY-COM-CAT-003-02
    preconditions: A closed store and draft listing exist
    steps: 'Read the closed store, an unknown store and the draft page'
    expected: The list is empty and both unknown or excluded pages are not found
    negative: true
    data_needs: none
    bound_to:
      - TST-COM-CAT-016
      - TST-COM-CAT-023
    provenance: test
    source: >-
      services-commerce:modules/catalog/tests/e2e/storefront.e2e.spec.js#answers an empty page of
      the closed store, 404 for an unknown store, and refuses a bad query 400
    category: edge
    binding_evidence:
      - >-
        services-commerce:modules/catalog/tests/e2e/storefront.e2e.spec.js#answers an empty page of
        the closed store, 404 for an unknown store, and refuses a bad query 400
      - >-
        services-commerce:modules/catalog/tests/integration/services/storefront/storefront-listings.integration.spec.js#opens
        an unlisted product by its page, and is answered 404 for a draft and for a product another
        store does not sell
    step_evidence:
      - do: 'Read the closed store, an unknown store and the draft page'
        provenance: test
        source: >-
          services-commerce:modules/catalog/tests/e2e/storefront.e2e.spec.js#answers an empty page
          of the closed store, 404 for an unknown store, and refuses a bad query 400
    assertions:
      - expect: The list is empty and both unknown or excluded pages are not found
        provenance: test
        source: >-
          services-commerce:modules/catalog/tests/e2e/storefront.e2e.spec.js#answers an empty page
          of the closed store, 404 for an unknown store, and refuses a bad query 400
  - id: ATS-COM-CAT-008-06
    title: Public browsing isolates the addressed workspace
    level: api
    proves:
      - BR-CAP-COM-CAT-008-10
    preconditions: Fixtures provide two workspaces and an unavailable workspace
    steps: 'Read without context, with signed context and at an unavailable workspace'
    expected: >-
      Public reading succeeds independently of signed context, and unavailable workspace access
      fails
    negative: true
    data_needs: none
    bound_to:
      - TST-COM-CAT-011
    provenance: test
    source: >-
      services-commerce:modules/catalog/tests/e2e/catalog-security.e2e.spec.js#is served with no
      security context, acting in the path’s tenant alone
    category: boundary
    binding_evidence:
      - >-
        services-commerce:modules/catalog/tests/e2e/catalog-security.e2e.spec.js#is served with no
        security context, acting in the path’s tenant alone
      - >-
        services-commerce:modules/catalog/tests/e2e/catalog-security.e2e.spec.js#is refused by the
        tenant access gate in a tenant Platform has no row for (403 TenantUnavailable)
      - >-
        services-commerce:modules/catalog/tests/e2e/catalog-security.e2e.spec.js#ignores a signed
        context it is handed: no diagnosis, the public prices
    step_evidence:
      - do: 'Read without context, with signed context and at an unavailable workspace'
        provenance: test
        source: >-
          services-commerce:modules/catalog/tests/e2e/catalog-security.e2e.spec.js#is served with no
          security context, acting in the path’s tenant alone
    assertions:
      - expect: >-
          Public reading succeeds independently of signed context, and unavailable workspace access
          fails
        provenance: test
        source: >-
          services-commerce:modules/catalog/tests/e2e/catalog-security.e2e.spec.js#is served with no
          security context, acting in the path’s tenant alone
  - id: ATS-COM-CAT-008-07
    title: Shelf membership changes the browsable assortment
    category: interaction
    level: api
    proves:
      - BR-CAP-COM-CAT-005-04
      - BR-CAP-COM-CAT-008-01
    preconditions: A store admits only Books and a published product belongs to Apparel.
    steps: Browse; assign the product to Books; browse; remove its Books membership and browse again.
    expected: The product appears after assignment and disappears after removal.
    negative: false
    data_needs: Run-owned workspace and records; fixed clock where dates are exercised.
    bound_to: []
    provenance: proposed
    source:
      - >-
        services-commerce:modules/catalog/tests/integration/services/persistence/product-categories.integration.spec.js#refuses
        a list naming one product twice (400) and an unknown category (404)
      - >-
        services-commerce:modules/catalog/tests/unit/storefront/storefront-visibility.spec.js#removes
        a product not yet on sale, and one whose sale has ended (the end exclusive)
    exercises:
      - CAP-COM-CAT-005
      - CAP-COM-CAT-008
    workflows: []
    step_evidence:
      - do: Browse; assign the product to Books; browse; remove its Books membership and browse again.
        provenance: proposed
        source:
          - >-
            services-commerce:modules/catalog/tests/integration/services/persistence/product-categories.integration.spec.js#refuses
            a list naming one product twice (400) and an unknown category (404)
          - >-
            services-commerce:modules/catalog/tests/unit/storefront/storefront-visibility.spec.js#removes
            a product not yet on sale, and one whose sale has ended (the end exclusive)
    assertions:
      - expect: The product appears after assignment and disappears after removal.
        provenance: proposed
        source:
          - >-
            services-commerce:modules/catalog/tests/integration/services/persistence/product-categories.integration.spec.js#refuses
            a list naming one product twice (400) and an unknown category (404)
          - >-
            services-commerce:modules/catalog/tests/unit/storefront/storefront-visibility.spec.js#removes
            a product not yet on sale, and one whose sale has ended (the end exclusive)
  - id: ATS-COM-CAT-008-08
    title: Browsing and quoting use the same buyer context
    category: interaction
    level: api
    proves:
      - BR-CAP-COM-CAT-013-08
      - BR-CAP-COM-CAT-008-03
      - BR-CAP-COM-CAT-008-04
    preconditions: Standard and a publicly displayed Member price exist.
    steps: 'Browse and quote anonymously, then repeat as the member without staff assumptions.'
    expected: Public results show public alternatives; signed results use the member’s identity.
    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/price-quotes.e2e.spec.js#refuses a body that
        names a subject, an acting contact, a recipient or a cart: nothing about a person is read
        anonymously
      - >-
        services-commerce:modules/catalog/tests/e2e/storefront.e2e.spec.js#shows the audiences
        marked for public display beside the Standard price (D10): the Members price 2000, with its
        audience
      - >-
        services-commerce:modules/catalog/tests/e2e/storefront.e2e.spec.js#prices a portal member as
        themselves (the recorded member: the member price, nothing signing in could change)
    exercises:
      - CAP-COM-CAT-013
      - CAP-COM-CAT-008
    workflows:
      - WF-COM-CAT-007
    step_evidence:
      - do: 'Browse and quote anonymously, then repeat as the member without staff assumptions.'
        provenance: proposed
        source:
          - >-
            services-commerce:modules/pricing/tests/e2e/price-quotes.e2e.spec.js#refuses a body that
            names a subject, an acting contact, a recipient or a cart: nothing about a person is
            read anonymously
          - >-
            services-commerce:modules/catalog/tests/e2e/storefront.e2e.spec.js#shows the audiences
            marked for public display beside the Standard price (D10): the Members price 2000, with
            its audience
          - >-
            services-commerce:modules/catalog/tests/e2e/storefront.e2e.spec.js#prices a portal
            member as themselves (the recorded member: the member price, nothing signing in could
            change)
    assertions:
      - expect: Public results show public alternatives; signed results use the member’s identity.
        provenance: proposed
        source:
          - >-
            services-commerce:modules/pricing/tests/e2e/price-quotes.e2e.spec.js#refuses a body that
            names a subject, an acting contact, a recipient or a cart: nothing about a person is
            read anonymously
          - >-
            services-commerce:modules/catalog/tests/e2e/storefront.e2e.spec.js#shows the audiences
            marked for public display beside the Standard price (D10): the Members price 2000, with
            its audience
          - >-
            services-commerce:modules/catalog/tests/e2e/storefront.e2e.spec.js#prices a portal
            member as themselves (the recorded member: the member price, nothing signing in could
            change)
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-008-show-shoppers-what-a-store-sells.md#CAP-COM-CAT-008
  - >-
    rhythm-v2-docs:specs/commerce/catalog/design/workflows/WF-COM-CAT-007-build-a-storefront-page-or-product-page.md#WF-COM-CAT-007
product_intent: proposed
coverage:
  rule: covered
  transition: 'gap: FND-COM-CAT-062'
  validation: 'gap: FND-COM-CAT-062'
  permission: 'gap: FND-COM-CAT-062'
  edge: covered
  failure: 'gap: FND-COM-CAT-062'
  boundary: covered
  concurrency: 'gap: FND-COM-CAT-062'
  invariant: 'gap: FND-COM-CAT-062'
  interaction: covered
coverage_notes:
  transition: >-
    No complete transition scenario is established by this back-fill; the finding records the
    missing proof.
  validation: >-
    No complete validation scenario is established by this back-fill; the finding records the
    missing proof.
  permission: >-
    No complete permission scenario is established by this back-fill; the finding records the
    missing proof.
  failure: >-
    No complete failure 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.
  invariant: >-
    No complete invariant scenario is established by this back-fill; the finding records the missing
    proof.
permission_coverage:
  - key: commerce.storefront.read
    coverage: 'gap: FND-COM-CAT-062'
    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-062'
---

# Present the store’s available products: Capability Test Specification

## Coverage

| Rule | Proof Scenario or Gap |
|---|---|
| `BR-CAP-COM-CAT-008-01` | `ATS-COM-CAT-008-01`, `ATS-COM-CAT-008-07` |
| `BR-CAP-COM-CAT-008-02` | `ATS-COM-CAT-008-02` |
| `BR-CAP-COM-CAT-008-03` | `ATS-COM-CAT-008-03`, `ATS-COM-CAT-008-08` |
| `BR-CAP-COM-CAT-008-04` | `ATS-COM-CAT-008-03`, `ATS-COM-CAT-008-08` |
| `BR-CAP-COM-CAT-008-07` | `ATS-COM-CAT-008-04` |
| `BR-CAP-COM-CAT-008-08` | `ATS-COM-CAT-008-05` |
| `BR-CAP-COM-CAT-008-10` | `ATS-COM-CAT-008-06` |

## Interactions With Related Capabilities

Eligibility changes visibility after authentication. Public and member browsing use different price presentations. Shelf membership changes the browsable assortment. Browsing and quoting use the same buyer context.

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