robocop

Checks KYC attributes against sanction lists
Log | Files | Refs | Submodules | README | LICENSE

README.md (3471B)


      1 <!--
      2 SPDX-FileCopyrightText: 2025 Christian Grothoff
      3 
      4 SPDX-License-Identifier: GPL-3.0-or-later
      5 -->
      6 
      7 # Robocop
      8 
      9 Robocop is a Counter Terrorist Financing (CTF) sanction processing tool written in Rust. It can be used for compliance processes in software such as [GNU Taler](https://taler.net).
     10 
     11 ## Prepare for installation
     12 
     13 Download the repository containing all the [source files](https://git.taler.net/robocop.git/)
     14 
     15 Then make sure you have Rust and Cargo installed.
     16 
     17 ## Install and run
     18 
     19 Once Cargo is installed, we can install `robocop` with the command:
     20 
     21 ```
     22 $ cargo install --path .
     23 ```
     24 
     25 You can then run it by providing the sanction list in JSON format:
     26 
     27 ```
     28 $ ~/.cargo/bin/robocop swiss.json
     29 ```
     30 
     31 
     32 ## Converting official sanction lists to robocop's internal format
     33 
     34 `robocop` consumes its sanction list as a JSON **array of target records**. Each
     35 record has a string `ssid` (its identifier) plus any number of registry fields
     36 whose values are **arrays of strings** (e.g. `FULL_NAME`, `PERSON_FIRST_NAMES`,
     37 `PERSON_LAST_NAME`, `DATE_OF_BIRTH`, `NATIONALITY`, `PERSON_NATIONAL_ID`,
     38 `COMPANY_NAME`, `ADDRESS_*` / `REGISTERED_OFFICE_ADDRESS_*`). At match time
     39 `robocop` compares each field of an incoming query against the same-named field
     40 of every record (fuzzy, Levenshtein-based), so all converters emit the **same**
     41 registry field names regardless of source list.
     42 
     43 One converter is provided per source-list format. Each reads the official XML on
     44 stdin and writes the JSON array on stdout; pipe it through
     45 `robocop-json-postprocess` (which drops empty/`null` fields) to get the final
     46 list:
     47 
     48 | Converter | Source list | Official XML schema |
     49 |-----------|-------------|---------------------|
     50 | `robocop-ch-to-json`   | Switzerland — SECO | `swiss-sanctions-list` |
     51 | `robocop-eu-to-json`   | EU — Consolidated Financial Sanctions List | `export` / `sanctionEntity` |
     52 | `robocop-un-to-json`   | UN — Security Council Consolidated List | `CONSOLIDATED_LIST` |
     53 | `robocop-ofac-to-json` | US — OFAC SDN **and** Consolidated lists | legacy `sdnList` / `sdnEntry` |
     54 | `robocop-uk-to-json`   | UK — OFSI Consolidated List | `ArrayOfFinancialSanctionsTarget` |
     55 
     56 Each record's `ssid` is namespaced by authority (`EU-`, `UN-`, `OFAC-`, `GB-`,
     57 and the bare numeric Swiss id) so records stay unique if several lists are
     58 concatenated into one file.
     59 
     60 ```
     61 $ ./robocop-ch-to-json   < swiss.xml   | robocop-json-postprocess > swiss.json
     62 $ ./robocop-eu-to-json   < eu.xml      | robocop-json-postprocess > eu.json
     63 $ ./robocop-un-to-json   < un.xml      | robocop-json-postprocess > un.json
     64 $ ./robocop-ofac-to-json < SDN.XML | robocop-json-postprocess > ofac-sdn.json
     65 $ ./robocop-ofac-to-json --prefix OFAC-CONS- < CONSOLIDATED.XML \
     66       | robocop-json-postprocess > ofac-cons.json
     67 $ ./robocop-uk-to-json   < ConList.xml | robocop-json-postprocess > uk.json
     68 ```
     69 
     70 Note on the OFAC consolidated (non-SDN) list: OFAC serves it in the legacy
     71 `sdnList` format at `.../exports/CONSOLIDATED.XML`, and in the newer "advanced"
     72 format at `CONS_ADVANCED.XML`. `robocop-ofac-to-json` reads the **legacy** format,
     73 so a single converter handles both the SDN list and the consolidated list; use
     74 `CONSOLIDATED.XML` (not `CONS_ADVANCED.XML`, which robocop does not parse). Because
     75 OFAC reuses a few `uid`s across the two lists, pass `--prefix OFAC-CONS-` when
     76 converting the consolidated list if you intend to merge it with the SDN list into
     77 one file, so the records keep distinct `ssid`s.