Skip to main content

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-Active destination 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.