---
id: STATE-COM-CAT-012
title: Offer presentation and response
object: DOM-COM-CAT-006
product_area: commerce
module: catalog
revision: 1
status: draft
design_intent: open
implementation_evidence: observed
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
states:
  - name: held out
    meaning: The assignment deliberately withholds the recorded offer from this subject.
  - name: shown
    meaning: The response returns the offer with its quote-based fifteen-minute expiry.
  - name: shown as estimate
    meaning: A public-price offer is returned for an anonymous session and cannot be accepted.
  - name: accepted
    meaning: >-
      Acceptance has recorded the action result, such as item addition, replacement, code application or page
      target.
  - name: refused
    meaning: An attempted item action recorded checkout or participant problems.
  - name: dismissed
    meaning: The recorded dismissal starts suppression under the rule’s configured interval.
  - name: expired
    meaning: The offer’s quote has expired and a new first acceptance is rejected.
transitions:
  - from: shown
    to: accepted
    trigger: The subject requests the offered action.
    guard: >-
      Response authority and offer access are required; first acceptance must be unexpired and provide an
      accessible checkout for item or code actions. Application-flow execution is unavailable.
    side_effects:
      - Checkout processing adds or replaces the candidate and retains its offer reference.
      - >-
        Item actions commit with acceptance history; code application commits before its separate history
        write.
    who: Portal buyer or console staff
    provenance: test
    source: >-
      services-commerce:modules/recommendations/tests/e2e/offers.e2e.spec.js#answers one offer: the mug, from
      the listing, priced $12.00 by the quote, live, to add to the checkout, expiring with the quote
  - from: accepted
    to: accepted
    trigger: The subject repeats a completed acceptance.
    guard: A saved acceptance can repeat without a fresh expiry check.
    side_effects:
      - The response returns the earlier outcome without a new item action.
    who: Portal buyer or console staff
    provenance: test
    source: >-
      services-commerce:modules/recommendations/tests/e2e/offers.e2e.spec.js#answers the first acceptance to a
      second, repeated, adding nothing
  - from: shown
    to: refused
    trigger: Item processing reports an envelope or participant refusal.
    guard: No additional condition applies.
    side_effects:
      - An interaction retains the problems and the request returns the refusal.
    who: Checkout workflow
    provenance: documented
    source: 'services-commerce:modules/recommendations/services/acceptance/accept-offer.ts'
  - from: shown
    to: dismissed
    trigger: The subject requests dismissal.
    guard: The caller must have response authority and access to this shown offer.
    side_effects:
      - A unique dismissal entry is recorded and reused on repeats.
    who: Portal buyer or console staff
    provenance: test
    source: >-
      services-commerce:modules/recommendations/tests/e2e/offers.e2e.spec.js#offers nothing inside the
      dismissal window
  - from: shown
    to: expired
    trigger: The quote-based fifteen-minute lifetime ends.
    guard: No additional condition applies.
    side_effects:
      - New acceptance receives an expiry refusal.
    who: Time
    provenance: observed
    source: 'services-commerce:modules/recommendations/services/acceptance/accept-offer.ts:acceptOffer'
invalid:
  - from: held out
    to: accepted
    why: Ownership checks reject presentations that were withheld rather than shown.
  - from: shown as estimate
    to: accepted
    why: Session estimates are rejected even when a signed-in caller tries to accept them.
  - from: expired
    to: accepted
    why: After expiry only a previously completed acceptance may repeat.
concurrency: >-
  The history index permits one acceptance and one dismissal entry. Checkout effects occur before acceptance
  insertion, so concurrent first-action safety is unresolved. Item changes and history share a transaction;
  promotion application does not.
invariants:
  - INV-DOM-COM-CAT-006-06
  - INV-DOM-COM-CAT-006-07
  - INV-DOM-COM-CAT-006-08
evidence:
  - >-
    services-commerce at c8b66a98: modules/recommendations/db/offer-presentations.table.ts,
    offer-interactions.table.ts; services/acceptance/accept-offer.ts (acceptOffer, dismissOffer);
    services/persistence/offer-interactions.ts; services/evaluation/evaluate-offers.ts.
---

# Offer presentation and response

## The Lifecycle

```mermaid
stateDiagram-v2
  [*] --> held_out: subject in holdout
  [*] --> shown: live evaluation
  [*] --> shown_as_estimate: anonymous session
  shown --> accepted
  accepted --> accepted: repeat answers the first
  shown --> refused: checkout refuses the item
  shown --> dismissed
  shown --> expired: fifteen minutes
```

## Transitions Explained

Held out: The assignment deliberately withholds the recorded offer from this subject. Shown: The response returns the offer with its quote-based fifteen-minute expiry. Shown as estimate: A public-price offer is returned for an anonymous session and cannot be accepted. Accepted: Acceptance has recorded the action result, such as item addition, replacement, code application or page target. Refused: An attempted item action recorded checkout or participant problems. Dismissed: The recorded dismissal starts suppression under the rule’s configured interval. Expired: The offer’s quote has expired and a new first acceptance is rejected.

## What Cannot Happen

Ownership checks reject presentations that were withheld rather than shown. Session estimates are rejected even when a signed-in caller tries to accept them. After expiry only a previously completed acceptance may repeat.

## Concurrency and Timing

The history index permits one acceptance and one dismissal entry. Checkout effects occur before acceptance insertion, so concurrent first-action safety is unresolved. Item changes and history share a transaction; promotion application does not.
