---
id: CAP-COM-CAT-020
title: Present offers and process buyer responses
feature: FEAT-COM-CAT-05
product_area: commerce
module: catalog
revision: 1
status: draft
product_intent: proposed
implementation_evidence: observed
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
purpose: >-
  Commerce produces contextual suggestions and records permitted acceptances or
  dismissals.
outcomes:
  - Suppression respects existing purchases and recent dismissals.
  - 'A suggestion taken is added once, at the price displayed.'
concepts:
  - CON-COM-CAT-006
actors:
  - ACT-COM-005
  - ACT-COM-006
  - ACT-COM-004
surfaces:
  - portal
  - api
permissions:
  - key: commerce.offers.read
    where_checked: api
    scope: tenant
  - key: commerce.offers.respond
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-COM-CAT-020-01
    proved_by: [ATS-COM-CAT-019-08, ATS-COM-CAT-020-01, TST-COM-CAT-135]
    statement: >-
      Evaluation ranks active rules for a placement and subject, quotes each
      candidate for that subject and applies request, rule and placement limits.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    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
    origin: none
  - id: BR-CAP-COM-CAT-020-02
    proved_by: [ATS-COM-CAT-020-02, ATS-COM-CAT-020-08, TST-COM-CAT-135]
    statement: >-
      Configured suppression removes candidates already in checkout, previously
      accepted or recently dismissed, using thirty days as the default dismissal
      interval.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/recommendations/tests/e2e/offers.e2e.spec.js#offers
      nothing inside the dismissal window
    origin: none
  - id: BR-CAP-COM-CAT-020-03
    proved_by: [ATS-COM-CAT-020-03, ATS-COM-CAT-020-08, TST-COM-CAT-135]
    statement: >-
      First acceptance checks the fifteen-minute expiry, while recorded
      acceptances remain repeatable after expiry and added items do not retain a
      frozen offer price.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: observed
    source: >-
      services-commerce:modules/recommendations/services/acceptance/accept-offer.ts:acceptOffer
    origin: none
  - id: BR-CAP-COM-CAT-020-04
    proved_by: [ATS-COM-CAT-020-01, ATS-COM-CAT-020-08, TST-COM-CAT-135]
    statement: >-
      Accepting an add or upgrade offer changes the buyer’s checkout once and
      records the offer reference, with repeats returning the saved result.
    kind: policy
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/recommendations/tests/e2e/offers.e2e.spec.js#answers
      the first acceptance to a second, repeated, adding nothing
    origin: none
  - id: BR-CAP-COM-CAT-020-05
    proved_by: [ATS-COM-CAT-020-02, ATS-COM-CAT-020-08, TST-COM-CAT-135]
    statement: >-
      Portal response authority follows the presented contact, acting contact or
      accessible checkout; console staff may respond within the workspace, and
      repeated dismissal records no additional interaction.
    kind: permission
    enforced_at:
      - service
    must_prove: true
    provenance: observed
    source: >-
      services-commerce:modules/recommendations/services/acceptance/accept-offer.ts:ownedOffer
    origin: none
  - id: BR-CAP-COM-CAT-020-06
    proved_by: [ATS-COM-CAT-020-04, TST-COM-CAT-135]
    statement: >-
      Anonymous subjects receive public-price estimates only in public
      placements, and those estimate presentations cannot be accepted.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/recommendations/tests/e2e/offers.e2e.spec.js#cannot
      have the estimate accepted, even by a signed-in member: 409
      sign_in_required
    origin: none
  - id: BR-CAP-COM-CAT-020-07
    proved_by: []
    statement: >-
      Holdout assignment is recorded without presenting that rule’s offer to the
      withheld subject.
    kind: policy
    enforced_at:
      - service
    must_prove: false
    provenance: test
    source: >-
      services-commerce:modules/recommendations/tests/unit/holdout.spec.js#holds
      a subject out exactly when its bucket is below ten times the percentage
    origin: none
  - id: BR-CAP-COM-CAT-020-08
    proved_by: [ATS-COM-CAT-020-05, TST-COM-CAT-135]
    statement: >-
      Staff-only offer preview reports suppression reasons and persists no
      presentation.
    kind: permission
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/recommendations/tests/e2e/offers.e2e.spec.js#is
      refused to a portal member, 403 preview_not_allowed, and answers the
      console the suppressed rules without writing
    origin: none
  - id: BR-CAP-COM-CAT-020-09
    proved_by: []
    statement: >-
      An accepted offer reference passes from the checkout item to its order
      line for conversion measurement.
    kind: invariant
    enforced_at:
      - service
    must_prove: false
    provenance: test
    source: >-
      services-commerce:modules/recommendations/tests/e2e/offers.e2e.spec.js#places
      the order with the offer frozen on the mug’s line
    origin: none
  - id: BR-CAP-COM-CAT-020-10
    proved_by: [ATS-COM-CAT-020-06, TST-COM-CAT-137]
    statement: >-
      Offer evaluation requires read permission, response requires respond
      permission, and anonymous evaluation requires neither but rejects person
      or cart references.
    kind: permission
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/recommendations/tests/e2e/recommendations-security.e2e.spec.js#may
      evaluate but not accept: 403 permission_missing on the acceptance
    origin: none
  - id: BR-CAP-COM-CAT-020-11
    proved_by: [ATS-COM-CAT-020-07, ATS-COM-CAT-020-08, ATS-COM-CAT-020-09, ATS-COM-CAT-020-10]
    statement: >-
      Live offer evaluation persists shown and held-out presentations and locks
      their producing rules in the same transaction, while preview evaluation
      omits those writes.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: observed
    source: >-
      services-commerce:modules/recommendations/services/persistence/offer-presentations.ts:insertOfferPresentations
    origin: none
scenarios:
  - id: SC-CAP-COM-CAT-020-01
    given: A member’s t-shirt cart produces a related mug offer
    when: Accept the mug and complete the order
    then: >-
      The offer reference follows the item and performance records a
      twelve-dollar converted line
    provenance: test
    source: >-
      services-commerce:modules/recommendations/tests/e2e/offers.e2e.spec.js#shows
      one shown, one accepted and one converted line worth $12.00 on the rule’s
      performance once the order is accepted
depends_on:
  - CAP-COM-CAT-019
  - CAP-COM-CAT-013
journeys:
  - JNY-COM-CAT-006
open_questions:
  - OQ-COM-CAT-005
evidence:
  - >-
    Pinned service inputs: modules/recommendations/aws/api/offers.routes.ts;
    services/evaluation/**, services/acceptance/**;
    db/offer-presentations.table.ts, offer-interactions.table.ts; tests (offers
    e2e, presentations, interactions, holdout)
controls: [TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-005, TC-AZ-006, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-TEN-004, TC-CRY-001, TC-CRY-004, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-LOG-004, TC-LOG-005, TC-AVL-004, TC-AVL-005, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002]
exercised_by: [FAS-COM-CAT-05-01, FAS-COM-CAT-05-02, FAS-COM-CAT-05-03, FAS-COM-CAT-05-04, FAS-COM-CAT-05-05]
suites: [TST-COM-CAT-135, TST-COM-CAT-137]
---

# Present offers and process buyer responses

## Purpose

Commerce produces contextual suggestions and records permitted acceptances or dismissals.

## How It Works

Evaluation uses the placement, subject and selling context to build candidate offers. Pricing supplies candidate amounts and suppression keeps unnecessary repetitions out of the response. Live evaluation retains presentations, while staff preview returns diagnostics without that write. A buyer can respond to a permitted presentation through its action. Checkout item actions and acceptance records are joined for add and replacement paths. Expiry prevents a new late acceptance, but does not freeze the displayed amount or invalidate an earlier recorded result. The product should prove those distinctions and resolve the separate promotion-action transaction gap.

## Relationships

The configure recommendation rules and placements capability supplies related configuration or assessment used in this work.

The calculate and explain a buyer’s item price capability supplies related configuration or assessment used in this work.
