Appearance
Sanctions and PEP escalation
Two escalation paths from one screening step: a sanctions hit opens a critical case before any rule runs, while softer signals (a politically exposed person, adverse media) are scored and may open an ordinary review. Pack: examples/policies/sanctions-and-pep-escalation/.
A pattern for expressing an escalation policy, not compliance guidance: what counts as a hit, which lists are screened and what a reviewer must do with a match are the tenant's and the vendor's business. The pack screens with the deterministic mock-sanctions app, whose install on the development stack blocklists the name 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 subject can proceed without a person looking, must be looked at within hours, or within a day. The point of the pack is the ordering: the expensive, time-critical path is a branch straight after the screening step, not a rule in a set.
Data expected
- A subject with
data.nameanddata.country(what the screen is run on), plus the optional flagsdata.pepanddata.adverseMediathat the integrating system sets from its own sources or from an earlier screening. - No collection flow: screening happens on data the platform already holds.
Steps and rules
| Step | Type | Why |
|---|---|---|
screen | call_app | mock-sanctions screen on subject.name and subject.country; output under sanctions (hit, matches). |
hit | branch | sanctions.hit == true goes to escalate; everything else to rules. |
escalate | create_case | sanctions_escalation, priority critical, 4-hour SLA. No rules run: the case context carries the matches, and the reviewer decides. |
rules | evaluate_rules | The screening_pep rule set, for subjects that cleared the screen. |
route | branch | rules.outcome == manual_review opens the softer case. |
pep_review | create_case | pep_review, priority high, 24-hour SLA. |
decide | emit_decision | The reviewer's decision when there was a case (either one), otherwise from the rules. A run that took the escalation branch has no rule results; the decision is the reviewer's alone. |
The rule set screening_pep sums weights into two bands, 0-40 approve and 40-100 manual_review: there is no automatic reject on these signals, by design.
| Rule | Type | Severity, weight | Fails when |
|---|---|---|---|
screening_pep_declared | comparison | warn, 60 | subject.pep == true (passWhen: false turns the match into a failure) |
screening_adverse_media | comparison | warn, 40 | subject.adverseMedia == true |
What a reviewer sees
A sanctions_escalation case at the top of the queue (critical, four hours) with the vendor's matches and scores in its context; or a pep_review case with the two rule results. A case queue in the admin console can pin either type (see Admin console: queues and filters).
How to adapt it
Screen with the opensanctions app of the App catalogue instead of the mock, once its apiKey secret is stored: the same screen action, plus input: { "type": "Company" } or Person. Use an app rule against the same app instead of screening_pep_declared, with input: { "type": "Person", "topics": ["role.pep"] } and resultPath: hit, as the seeded pep_hit rule does, so the PEP signal comes from the vendor instead of the subject record. Add a score_threshold on the best match score to route weak matches to the softer review instead of the critical case.
Run it
bash
pnpm policy:import examples/policies/sanctions-and-pep-escalation --publishThe fixture (expect.json) screens Evil Corp: the mock reports a hit, the run skips the rules and opens a sanctions_escalation case, the check rejects it and the run completes with a manual reject; sanctions.hit is true in the run context.