---
id: STATE-COM-ORD-012
title: Return authorization
object: DOM-COM-ORD-005
product_area: commerce
module: orders
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
states:
  - name: open
    meaning: The customer may send the authorized goods before the recorded deadline.
  - name: partially_received
    meaning: Receiving recorded only part of the authorized goods.
  - name: closed
    meaning: Receipt completed or the return otherwise reached a non-expiry terminal outcome.
  - name: expired
    meaning: The return's expired outcome is reflected on the authorization.
  - name: cancelled
    meaning: 'Cancellation is declared, while the withdrawal workflow uses closed instead.'
transitions:
  - from: open
    to: partially_received
    trigger: Receiving reports a portion of the authorized quantity.
    guard: Receipt processing supplies the target state without an independent authorization guard.
    side_effects: []
    who: System (receiving report)
    provenance: observed
    source: 'services-commerce:modules/orders/services/returns/return-workflow.ts'
  - from: open
    to: closed
    trigger: Full receipt or a non-expiry return end closes authorization.
    guard: The persistence update has no independent transition check.
    side_effects: []
    who: System
    provenance: observed
    source: 'services-commerce:modules/orders/services/persistence/returns.ts:transitionReturn'
  - from: partially_received
    to: closed
    trigger: The remaining goods arrive or the return otherwise ends.
    guard: The persistence update has no independent transition check.
    side_effects: []
    who: System
    provenance: observed
    source: 'services-commerce:modules/orders/services/persistence/returns.ts:transitionReturn'
  - from: open
    to: expired
    trigger: An expired return propagates its outcome.
    guard: No current caller automatically expires the return.
    side_effects: []
    who: Nobody today
    provenance: observed
    source: 'services-commerce:modules/orders/services/persistence/returns.ts:transitionReturn'
invalid:
  - from: closed
    to: open
    why: >-
      The ordinary return path closes authorization, but its low-level update accepts any declared state
      without lifecycle validation.
concurrency: >-
  Authorization updates have no independent transition map or return lock. Recorded deadlines have no
  automatic expiry worker.
invariants:
  - INV-DOM-COM-ORD-005-07
evidence:
  - >-
    services-commerce at c8b66a98: modules/orders/db/return-authorizations.table.ts;
    services/persistence/returns.ts (transitionReturn, transitionReturnAuthorization);
    services/returns/return-workflow.ts.
---

# Return authorization

## The Lifecycle

```mermaid
stateDiagram-v2
  [*] --> open: issued
  open --> partially_received
  open --> closed
  partially_received --> closed
  open --> expired: declared, unreached
  partially_received --> expired: declared, unreached
```

## Transitions Explained

The authorization tells the customer what may return and by when. Receipt updates its partial or complete progress; ending the return normally closes outstanding authorizations. Expiry is only reflected if the return itself becomes expired.

## What Cannot Happen

The normal workflow does not reopen a closed authorization, but the persistence update does not enforce this restriction. The unique index excludes multiple open or partially received authorizations for one return.

## Concurrency and Timing

Authorization updates have no independent transition map or return lock. Recorded deadlines have no automatic expiry worker.
