pending and is resolved exactly once: confirmed, declined, or canceled. Whether a seller’s edit waits for an operator at all depends on the product_request feature flag and on the auto_confirm input.
The status lifecycle
Thestatus field takes one of the four ProductChangeStatus values, exported from @mercurjs/types. Each resolution has its own workflow, which checks that the change is still pending, stamps the actor field, and emits an event.
Confirming, declining, or canceling a change that isn’t
pending fails with a NOT_ALLOWED error. Each resolution step saves the previous values, so if a later step fails, the workflow restores the change to pending.
The model also has
requires_action_by, requires_action_at, and requires_action_reason columns, but ProductChangeStatus has no requires_action value and no workflow writes those columns.Revision requests
A revision request sends a proposed product back to its seller without approving or rejecting it.requestProductChangeWorkflow checks that the product status is proposed, records an audit change with a CHANGE_REQUESTED action, and emits product.change-requested. The product stays proposed for the seller to revise.
A revision request isn’t a fifth status, and it doesn’t resolve any pending change. It’s an already-confirmed entry in the product’s history. The operator’s message is stored twice: in the action’s details.message and in the change’s external_note.
Auto-confirm
Staging always runsautoConfirmProductChangeWorkflow right after the change is created. It runs confirmProductChangeWorkflow in the same workflow run when either condition holds:
- The flag is off: the
product_requestfeature flag is disabled - Forced: the caller passed
auto_confirm: true, which reaches the workflow asforce
pending. The flag is on by default. Turn it off with an environment variable:
.env
draft or proposed.
When Mercur forces auto-confirm
There’s no risk scoring: Mercur doesn’t classify edits as low or high risk. It forces auto-confirm in two places:- Draft deletes:
productEditDeleteProductWorkflowdefaultsauto_confirmtotruewhen the product is adraft - Operator deletes: the admin product delete route always passes
auto_confirm: true
confirmProductChangeWorkflow as a manual approval. It emits product-change.confirmed and fires the same hooks, with confirmed_by set to the change’s author.