---
id: WF-COM-CAT-017
title: Evaluate offers for a placement
trigger: >-
  Deterministic rule evaluation selects, prices and records suggestions at an application placement. No model
  generates the offers or their messages.
product_area: commerce
module: catalog
revision: 1
status: draft
design_intent: open
implementation_evidence: observed
inference: []
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
implements:
  - CAP-COM-CAT-020
moves:
  - STATE-COM-CAT-012
  - STATE-COM-CAT-011
crosses:
  - SVC-COM-CAT-recommendations
  - SVC-COM-CAT-pricing
idempotency: >-
  Every live evaluation can create new presentations. Suppression limits repeats, while preview creates
  neither presentations nor protected-fields locks.
concurrency: >-
  Presentation and rule-lock writes commit together. Concurrent evaluations can each create presentations;
  stable holdout does not deduplicate evaluations.
hops:
  - 'n': 1
    actor_or_service: Recommendations service
    action: >-
      Require an available placement, public eligibility for anonymous callers and console authority for
      preview mode.
    anchor: 'services-commerce:modules/recommendations/services/evaluation/evaluate-offers.ts:evaluateOffers'
    seam: sync
    on_failure: Reject missing or retired placements and unsupported caller modes.
    left_inconsistent: No presentation is saved.
    observer: The requesting person or service receives the result and any returned refusal.
    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
  - 'n': 2
    actor_or_service: Recommendations service
    action: 'Resolve the priced subject and required checkout, order or product-and-store context.'
    anchor: 'services-commerce:modules/recommendations/services/evaluation/evaluate-offers.ts:evaluateOffers'
    seam: sync
    on_failure: Reject inaccessible or invalid subject and context inputs.
    left_inconsistent: No presentation is saved.
    observer: The requesting person or service receives the result and any returned refusal.
    provenance: documented
    source: 'services-commerce:modules/recommendations/services/evaluation/evaluate-offers.ts'
  - 'n': 3
    actor_or_service: Recommendations service
    action: >-
      Load active placement rules and recent subject history, apply suppression and exclusions, and gather
      supported candidates while skipping membership-savings evaluation.
    anchor: 'services-commerce:modules/recommendations/services/persistence/offer-presentations.ts'
    seam: sync
    on_failure: Fail evaluation if rule or history loading fails.
    left_inconsistent: No new rule lock or presentation is saved.
    observer: The requesting person or service receives the result and any returned refusal.
    provenance: test
    source: >-
      services-commerce:modules/recommendations/tests/e2e/offers.e2e.spec.js#offers nothing inside the
      dismissal window
  - 'n': 4
    actor_or_service: Recommendations service to pricing quote
    action: >-
      Quote candidates and the current product for upgrades in a single batch with checkout context where
      available.
    anchor: 'services-commerce:modules/pricing/services/quotes/price-quotes.ts:priceQuote'
    seam: sync
    on_failure: 'Return no offers when quoting fails, and omit individually refused candidates with diagnostic reasons.'
    left_inconsistent: The placement can return no priced suggestion.
    observer: The requesting person or service receives the result and any returned refusal.
    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
  - 'n': 5
    actor_or_service: Recommendations service
    action: >-
      Apply stable holdout and priority order, enforce offer ceilings, and commit shown or withheld
      presentations with first-presentation rule locks.
    anchor: >-
      services-commerce:modules/recommendations/services/persistence/offer-presentations.ts:insertOfferPresentations
    seam: sync
    on_failure: Roll back the presentation write and return a request error.
    left_inconsistent: No partial presentation set or lock change commits.
    observer: The requesting person or service receives the result and any returned refusal.
    provenance: observed
    source: >-
      services-commerce:modules/recommendations/services/persistence/offer-presentations.ts:insertOfferPresentations
branches:
  - Console preview includes suppression explanations while leaving presentation and lock records untouched.
waits:
  - The displayed offer’s quote-based lifetime is fifteen minutes.
evidence:
  - >-
    services-commerce at c8b66a98: modules/recommendations/services/evaluation/evaluate-offers.ts, holdout.ts,
    messages.ts; services/persistence/offer-presentations.ts, recommendation-rules.ts
    (lockRecommendationRules); aws/api/offers.routes.ts.
controls: [TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, 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-DAT-004, TC-LOG-004, TC-LOG-005, TC-AVL-005, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-005, TC-PRV-001, TC-PRV-002]
---

# Evaluate offers for a placement

## What It Does

Deterministic rule evaluation selects, prices and records suggestions at an application placement. No model generates the offers or their messages.

## The Flow

```mermaid
sequenceDiagram
  participant U as Selling surface
  participant R as Recommendations service
  participant P as Pricing quote
  participant D as Database
  U->>R: evaluate (placement, subject, context)
  R->>D: placement, active rules, subject history
  R->>R: suppression, candidates per kind
  R->>P: one batched quote
  P-->>R: prices or refusals
  R->>R: holdout, rank, caps
  R->>D: presentations and rule locks (one transaction)
  R-->>U: shown offers with expiry
```

## When Something Fails

Reject missing or retired placements and unsupported caller modes. No presentation is saved. Reject inaccessible or invalid subject and context inputs. No presentation is saved. Fail evaluation if rule or history loading fails. No new rule lock or presentation is saved. Return no offers when quoting fails, and omit individually refused candidates with diagnostic reasons. The placement can return no priced suggestion. Roll back the presentation write and return a request error. No partial presentation set or lock change commits.

## Open Design Questions

The implemented recovery and concurrency behaviour above defines the current boundary. Any change to transaction scope or product authority requires a recorded decision.
