Goods receipt
Synchronous
The receipt workflow transaction writes stock and the outbox rows together. QC edges are the GRN map, including PENDING_QC → PUTAWAY_PENDING. See Procurement.
Asynchronous
stock.received releases waiting fulfillment demand on the worker. stock.sync.requested becomes a channel publish. Neither runs inside the HTTP request that completed the receipt.
Failure
A throw inside the workflow transaction rolls stock and outbox back. A throw in the allocation listener retries the outbox event and can run the listener again.
Stock transfer follows the same outbox pattern after its transaction. It does not use the GRN state machine.