---
id: STATE-COM-ORD-003
title: Hold and claim ledger
object: DOM-COM-ORD-002
product_area: commerce
module: orders
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
states:
  - name: held
    meaning: 'A cart hold exists, or a placed lease still awaits confirmation.'
  - name: committed
    meaning: The application has committed resources to the purchased line.
  - name: consumed
    meaning: Delivery has used the committed resources.
  - name: released
    meaning: The cart or sale workflow returned the reserved resources.
  - name: expired
    meaning: An unplaced hold passed its recorded expiry.
  - name: mismatch
    meaning: The application's resource position disagrees with the recorded promise.
transitions:
  - from: held
    to: committed
    trigger: Placement converts a hold or a later pass confirms a placed lease.
    guard: The claim function succeeds or lease confirmation reports confirmed.
    side_effects:
      - attach the purchased-line reference to the reservation
      - append leased-resource confirmation history
    who: System within placement or the hold sweep
    provenance: test
    source: >-
      services-commerce:modules/checkout/tests/e2e/holds-and-claims.e2e.spec.js#places the checkout: the hold
      re-affirmed and converted in TX-P, the ledger committed on the line, the claim frozen on the purchase
  - from: held
    to: expired
    trigger: The reservation pass discovers a lapsed unplaced hold.
    guard: The reservation remains held.
    side_effects:
      - set selection assessment to stale
    who: System (hold sweep)
    provenance: observed
    source: 'services-commerce:modules/orders/services/reservations/reservation-sweeper.ts:sweepReservations'
  - from: held
    to: released
    trigger: Item removal or cart abandonment returns held resources.
    guard: Any declared release function runs before the ledger change.
    side_effects:
      - append the cart resource-release event
    who: 'Staff, portal buyer or the expiry sweep'
    provenance: observed
    source: 'services-commerce:modules/checkout/services/checkout/hold-release.ts:releaseHeldReservations'
  - from: committed
    to: released
    trigger: Void or after-sale execution returns committed resources.
    guard: The seller release function participates in the same transaction.
    side_effects:
      - append purchased-resource release history
    who: 'Staff, the tender-window sweep or the after-sale workflows'
    provenance: test
    source: >-
      services-commerce:modules/checkout/tests/e2e/holds-and-claims.e2e.spec.js#releases a placed order’s
      committed claims on void, cancels its pending obligations and leaves claims_released on its history
  - from: committed
    to: consumed
    trigger: Delivery completes using the committed claim.
    guard: The corresponding obligation has completed.
    side_effects: []
    who: Delivery register (fulfilment module)
    provenance: observed
    source: 'services-commerce:modules/orders/services/persistence/reservations.ts:RESERVATION_TRANSITIONS'
  - from: held
    to: mismatch
    trigger: Lease confirmation reports expired capacity or conflict.
    guard: The lease is attached to a purchased line.
    side_effects:
      - record unconfirmed resources for operational review
    who: System after placement or the hold sweep
    provenance: observed
    source: 'services-commerce:modules/orders/services/placement/lease-confirmation.ts:confirmLease'
invalid:
  - from: released
    to: held
    why: Terminal reservations have no outgoing transition; new capacity needs another record.
  - from: expired
    to: committed
    why: Fresh preparation creates a claim instead of reviving the expired reservation.
concurrency: >-
  Canonical claim ordering reduces conflicting lock orders between placements. An unanswered placed lease
  remains held for another confirmation pass; an explicit expiry or conflict becomes mismatch.
invariants:
  - INV-DOM-COM-ORD-002-13
  - INV-DOM-COM-ORD-003-06
evidence:
  - >-
    services-commerce at c8b66a98: modules/orders/db/reservations.table.ts;
    services/persistence/reservations.ts, claims.ts; services/placement/claims-at-placement.ts,
    lease-confirmation.ts; services/reservations/reservation-sweeper.ts;
    modules/checkout/services/checkout/hold-release.ts.
---

# Hold and claim ledger

## The Lifecycle

```mermaid
stateDiagram-v2
  [*] --> held: early hold or lease
  [*] --> committed: claim made at placement
  held --> committed: converted at placement or lease confirmed
  held --> expired: hold lapsed before placement
  held --> released: item removed or cart abandoned
  held --> mismatch: lease not confirmed
  committed --> released: void, cancellation or amendment
  committed --> consumed: delivered
  committed --> mismatch: reconciler finding
```

## Transitions Explained

The ledger records promises made by sellers, including early holds, transactional claims and leases confirmed after placement. Releasing a promise uses the owning application's function and then changes Commerce's record in the same transaction.

## What Cannot Happen

Terminal reservation rows cannot be revived. Expired holds need fresh preparation rather than a transition back to committed.

## Concurrency and Timing

Canonical claim ordering reduces conflicting lock orders between placements. An unanswered placed lease remains held for another confirmation pass; an explicit expiry or conflict becomes mismatch.
