---
id: DOM-COM-CAT-002
title: Store
realises: CON-COM-CAT-002
product_area: commerce
module: catalog
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
owned_by: SVC-COM-CAT-configuration
readable_by:
  - SVC-COM-CAT-catalog
  - SVC-COM-CAT-pricing
  - SVC-COM-CAT-recommendations
lifecycle: STATE-COM-CAT-002
custom_fields: none
identity: >-
  A store uses a stable readable key chosen by staff or derived from its initial name. Creation rejects a key
  already occupied in the workspace.
attributes:
  - name: name and description
    kind: text
    required: true
    computed: false
    notes: Staff give the store a nonblank name and may add a description.
  - name: active
    kind: enum
    required: true
    computed: false
    notes: Deactivation closes shopper browsing and public quoting for this store.
  - name: checkout policy
    kind: reference
    required: true
    computed: false
    notes: The referenced policy supplies the unit and currency for checkouts opened here.
  - name: assortment rule and categories
    kind: enum
    required: true
    computed: false
    notes: 'The store admits every category, a selected set, or every category except selected exclusions.'
  - name: home category
    kind: reference
    required: false
    computed: false
    notes: The initial shelf must fall within the configured assortment.
  - name: default sort
    kind: enum
    required: false
    computed: false
    notes: The store supplies a fallback order when the request and category do not override it.
  - name: default image
    kind: reference
    required: false
    computed: false
    notes: A picture prepared by the shared asset pipeline can stand in for a listing without an image.
  - name: organization purchasing roles
    kind: collection
    required: false
    computed: false
    notes: >-
      Role restrictions apply to contacts buying for organizations; an empty selection allows affiliated
      contacts.
  - name: pricing extension references
    kind: reference
    required: false
    computed: false
    notes: Handler references are retained without verifying their registration at save time.
  - name: protection and version
    kind: computed
    required: true
    computed: true
    notes: >-
      System metadata carries the replacement version, protection level and creation and latest-change
      attribution.
relationships:
  - to: DOM-COM-CAT-001
    cardinality: many stores to one policy
    ownership: The store retains its policy link; that link blocks policy removal.
    cross_service: false
  - to: DOM-COM-CAT-003
    cardinality: one store to many categories through its assortment
    ownership: 'Assortment links belong to the store, and referenced categories cannot be removed.'
    cross_service: false
  - to: DOM-COM-CAT-006
    cardinality: one store to many offer rules
    ownership: Recommendation rules may restrict their scope to stores without being listed on the store record.
    cross_service: false
invariants:
  - id: INV-DOM-COM-CAT-002-01
    statement: A store must reference a checkout policy belonging to its workspace.
    enforced_at:
      - api
      - service
      - database
    provenance: test
    source: >-
      services-commerce:modules/configuration/tests/e2e/stores.e2e.spec.js#answers 400 to an ordering profile
      the tenant does not have, naming the property
  - id: INV-DOM-COM-CAT-002-02
    statement: Store requests cannot supply a separate unit or currency.
    enforced_at:
      - api
    provenance: test
    source: >-
      services-commerce:modules/configuration/tests/e2e/stores.e2e.spec.js#answers 400 to a currency or a
      business unit on the body: the store carries neither since D23
  - id: INV-DOM-COM-CAT-002-03
    statement: Assortment categories must exist in the store’s workspace.
    enforced_at:
      - service
    provenance: test
    source: >-
      services-commerce:modules/configuration/tests/integration/services/persistence/stores.integration.spec.js#refuses
      a category id the tenant does not have, 400 naming category_ids and the id, creating nothing
  - id: INV-DOM-COM-CAT-002-04
    statement: The selected opening category must be admitted by the assortment.
    enforced_at:
      - service
    provenance: test
    source: >-
      services-commerce:modules/configuration/tests/integration/services/persistence/stores.integration.spec.js#refuses
      a home category an "all_but" rule leaves out, 400 naming home_category_id
  - id: INV-DOM-COM-CAT-002-05
    statement: Checkout and order references prevent a store from being removed.
    enforced_at:
      - service
      - database
    provenance: test
    source: >-
      services-commerce:modules/configuration/tests/integration/services/persistence/stores.integration.spec.js#refuses
      deleting a store a checkout was opened in, naming the store
  - id: INV-DOM-COM-CAT-002-06
    statement: The asset pipeline prepares the default picture; deletion detaches it for later cleanup.
    enforced_at:
      - service
    provenance: test
    source: >-
      services-commerce:modules/catalog/tests/integration/services/assets/catalog-assets.integration.spec.js#detaches
      the store’s picture when the store is deleted
  - id: INV-DOM-COM-CAT-002-07
    statement: A changed store version causes a replacement using the old version to fail.
    enforced_at:
      - api
      - service
    provenance: test
    source: >-
      services-commerce:modules/configuration/tests/e2e/stores.e2e.spec.js#replaces a store at the version
      read, the purchasing roles with it, and answers 409 to the stale version after
physical:
  - stores
evidence:
  - >-
    services-commerce at c8b66a98: modules/configuration/db/stores.table.ts; services/persistence/stores.ts
    (storeColumns); modules/catalog/services/assets/catalog-assets.ts.
  - >-
    services-commerce at c8b66a98: modules/configuration/tests/e2e/stores.e2e.spec.js;
    tests/integration/services/persistence/stores.integration.spec.js.
  - 'react-console at baf6dae3: components/commerce/stores/**, lib/commerce/stores/live.ts.'
---

# Store

## What It Models

A store combines an offered assortment with the policy used to process purchases. It also chooses the starting shelf, default browsing order and fallback picture. Organization-role restrictions and pricing-handler references provide purchasing context.

## Identity and Attributes

Stores use permanent readable keys. Their unit and currency come from the selected checkout policy. Handler references are stored as supplied; pricing discovers whether a handler can answer.

## Relationships

A policy may serve several stores. Category references select the assortment and prevent referenced categories from being deleted. Recommendation rules may name stores independently.

## Invariants

The service checks policy and category membership in the workspace and requires the home category to satisfy the assortment. References from checkouts or orders block removal. Replacements reject stale versions.

## How It Is Stored and Shared

Configuration owns stores. Catalog reads their assortments and manages default pictures through its asset binding. Pricing reads handler references and recommendations reads store restrictions. No custom fields or change events are declared.

## Open Design Questions

The handler references are not exposed by the current store form. If an unresolved reference reaches a required pricing step, checkout can fail even though the store save succeeded.
