Failure scenarios
A real marketplace hits more than the happy path. Every scenario below is real code, live-executed
— npm run test:scenarios in examples/marketplace-mercatto/ runs all 11 against a real instance
and reports pass/fail for each, not just an HTTP status code.
Onboarding
A seller without an authorized Account is rejected, not silently accepted.
Creating an order that names an unauthorized/nonexistent seller Account fails with
422 PARTICIPANT_NOT_AUTHORIZED — checked before the Transaction is ever created.
examples/marketplace-mercatto/scenarios/onboarding-seller-without-account.ts
The alternative to a self-service seller: an anonymous, Organization-owned Account.
For a one-off payer who never needs their own login — accounts.create, no invitation, no
password. Contrast with Seller onboarding.
examples/marketplace-mercatto/scenarios/onboarding-anonymous-account.ts
Payment
An unpaid order's Payment Intent expires on its own.
A real background worker flips it to EXPIRED; the Transaction is never funded, never reserved.
examples/marketplace-mercatto/scenarios/payment-intent-expires.ts
A Late Deposit — money that arrives after the Payment Intent already expired.
Ishtaran never pretends this refinances the original order: the buyer's Available balance is
credited as a real, separate event (PaymentIntentLateDepositReceived) — the expired Transaction
is never reopened or auto-reserved.
examples/marketplace-mercatto/scenarios/payment-late-deposit.ts
A deposit for less than the order total.
The PaymentIntent moves to PARTIALLY_PAID and the Transaction never auto-reserves — a partial
payment is never treated as if the order had been paid in full.
examples/marketplace-mercatto/scenarios/payment-partial-deposit.ts
Workflow
A delivery event ingested from the wrong state is rejected.
Sending "delivered" twice — the second time from an already-terminal state — is denied, not
silently accepted or double-processed.
examples/marketplace-mercatto/scenarios/workflow-event-rejected.ts
Settlement succeeds with no delivery event ever ingested.
Proves Confirming delivery's central point directly: this is real,
current platform behavior, not a bug — confirming delivery before settling is the integrator's
responsibility, not an Ishtaran-enforced gate.
examples/marketplace-mercatto/scenarios/settlement-without-delivery-event.ts
Settlement
A single beneficiary gets 100% with no explicit Split declared.
The simpler sibling of Creating an order's explicit 90/10 — with exactly
one non-payer Participant, BR-SPL-004 gives them the whole Distributable Amount implicitly.
examples/marketplace-mercatto/scenarios/settlement-implicit-split.ts
Both real invalid-Split shapes, rejected at creation.
90% + 20% (doesn't sum to 100%), and two beneficiaries with no split declared at all — neither ever
reaches Settlement.
examples/marketplace-mercatto/scenarios/settlement-invalid-split.ts
A frozen seller Account at Settlement time.
Money for a beneficiary whose Account can't currently receive is never lost, never silently
redistributed to someone else: their allocation is marked RETAINED, the rest of the Settlement
still completes normally, and release is re-checked fresh — rejected while still frozen, succeeds
once the Account is active again.
examples/marketplace-mercatto/scenarios/settlement-frozen-seller-account.ts
Partial Settlement, end to end. Three real partial Settlements over one order, each with its
own Fee, correct remaining/status transitions, and rejection once nothing is left to settle —
the full worked example is Partial Settlement.
examples/marketplace-mercatto/scenarios/settlement-partial.ts
Not built — a real platform limitation, not an oversight
Two scenarios from the original alternative-path catalog aren't executable against any environment today without either a real 24h+ wait or an insecure bypass — both explicitly ruled out:
- Withdrawal destination-change cooldown (168h). Requires an already-
Activedestination to exist first, which itself requires the real 24h activation cooldown to have elapsed. - Withdrawal broadcast-failure retry. Requires a withdrawal to actually reach
Broadcasting, same real blocker.
The 24h activation cooldown itself is covered live — see Withdrawal.