Skip to content

Seller and payout screening ​

A marketplace screens more than the seller it onboards: payouts can go to an account someone else holds. This pack screens both names through an app, the seller's in a call_app step and the payout account holder's in an app rule, and treats the two hits differently: the seller's rejects, the holder's opens a review. Pack: examples/policies/seller-payout-screening/.

A pattern for screening several parties, not compliance guidance: who must be screened, against which lists, and whether a hit on a third party blocks the seller are the tenant's and the vendor's business. The pack screens with the deterministic mock-sanctions app, which the development tenant has installed with the blocklist Evil Corp; a tenant without that install can import the pack, but its runs fail on unknown_app until the app is installed and enabled.

The decision it automates ​

Whether a seller can start receiving payouts without a person looking. A seller on the list is rejected outright; a clean seller whose payouts go to a listed account holder is held for a reviewer, who decides whether the account changes or the seller goes.

Data expected ​

  • A subject of kind seller with data.name and data.country, and data.payoutAccountHolder: the name on the account payouts go to, which the integrating system sets to the seller's own name when the seller holds the account.
  • No collection flow: the marketplace already holds both names.

Steps and rules ​

StepTypeWhy
screen_sellercall_appmock-sanctions screen on subject.name and subject.country; output under sellerScreening (hit, matches), recorded with the run.
rulesevaluate_rulesThe two rules below, under the default policy: a failed block rule rejects, a failed warn rule sends the run to review.
routebranchrules.outcome == manual_review opens the review case; an approval or a rejection goes straight to the decision.
payout_reviewcreate_casepayout_review, priority high, 24-hour SLA.
decideemit_decisionThe reviewer's decision when there was a case, otherwise from the rules: a seller hit rejects whatever the holder's screen said.
RuleTypeSeverity, weightFails when
payout_seller_sanctions_hitcomparisonblock, 100sellerScreening.hit == true: reads the step's output, so the vendor is called once however many rules read it
payout_holder_sanctions_hitappwarn, 50mock-sanctions screen on subject.payoutAccountHolder returns hit: true

The two rules show the trade-off between the two ways of calling a vendor. A step records its output in the run context, where every later rule reads it and where a backtest finds it again in the recorded evaluation. An app rule calls the vendor while the rules are evaluated: it needs no step and no output key, but a dry run or a backtest cannot call the vendor, so the rule comes back skipped there. Screen with a step whatever the rules must be able to replay.

What a reviewer sees ​

A payout_review case with the two rule results: the seller's screen passed, the holder's failed, with the matched names the app returned in the failed rule's details. A case queue in the admin console can pin the type (see Admin console: queues and filters).

How to adapt it ​

Install the opensanctions app from the catalogue (it needs its apiKey secret) and name it in the step and in the rule instead of mock-sanctions: the screen action takes the same name and country, plus type (Company by default; set input: { "type": "Person" } on the rule when the account holders are people). Screen the seller's directors or beneficial owners the same way, one app rule per party, or collect them in a flow and call screenBatch from one step.

Run it ​

bash
pnpm policy:import examples/policies/seller-payout-screening --publish

The fixture (expect.json) onboards Northwind Traders with payouts to Evil Corp: the seller's screen is clean, the holder's rule fails, the run opens a payout_review case, the check rejects it and the run completes with a manual reject; sellerScreening.hit is false in the run context.

Released under the Apache-2.0 License.