README.md (3997B)
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 The program version comes from `git describe --tags --always --abbrev=8` at 20 build time. Git takes precedence over a `.version` file in the checkout. 21 Before exporting a source archive, record the version with: 22 23 ```sh 24 git describe --tags --always --abbrev=8 > .version 25 ``` 26 27 Include that file at the archive root. Builds without Git metadata read 28 `.version` and fail if it is missing or does not contain a nonempty single-line 29 version. The Cargo manifest version is dependency metadata, not the version 30 reported by the program. 31 32 Once Cargo is installed, we can install `robocop` with the command: 33 34 ``` 35 $ cargo install --path . 36 ``` 37 38 You can then run it by providing the sanction list in JSON format: 39 40 ``` 41 $ ~/.cargo/bin/robocop swiss.json 42 ``` 43 44 45 ## Converting official sanction lists to robocop's internal format 46 47 `robocop` consumes its sanction list as a JSON **array of target records**. Each 48 record has a string `ssid` (its identifier) plus any number of registry fields 49 whose values are **arrays of strings** (e.g. `FULL_NAME`, `PERSON_FIRST_NAMES`, 50 `PERSON_LAST_NAME`, `DATE_OF_BIRTH`, `NATIONALITY`, `PERSON_NATIONAL_ID`, 51 `COMPANY_NAME`, `ADDRESS_*` / `REGISTERED_OFFICE_ADDRESS_*`). At match time 52 `robocop` compares each field of an incoming query against the same-named field 53 of every record (fuzzy, Levenshtein-based), so all converters emit the **same** 54 registry field names regardless of source list. 55 56 One converter is provided per source-list format. Each reads the official XML on 57 stdin and writes the JSON array on stdout; pipe it through 58 `robocop-json-postprocess` (which drops empty/`null` fields) to get the final 59 list: 60 61 | Converter | Source list | Official XML schema | 62 |-----------|-------------|---------------------| 63 | `robocop-ch-to-json` | Switzerland — SECO | `swiss-sanctions-list` | 64 | `robocop-eu-to-json` | EU — Consolidated Financial Sanctions List | `export` / `sanctionEntity` | 65 | `robocop-un-to-json` | UN — Security Council Consolidated List | `CONSOLIDATED_LIST` | 66 | `robocop-ofac-to-json` | US — OFAC SDN **and** Consolidated lists | legacy `sdnList` / `sdnEntry` | 67 | `robocop-uk-to-json` | UK — OFSI Consolidated List | `ArrayOfFinancialSanctionsTarget` | 68 69 Each record's `ssid` is namespaced by authority (`EU-`, `UN-`, `OFAC-`, `GB-`, 70 and the bare numeric Swiss id) so records stay unique if several lists are 71 concatenated into one file. 72 73 ``` 74 $ ./robocop-ch-to-json < swiss.xml | robocop-json-postprocess > swiss.json 75 $ ./robocop-eu-to-json < eu.xml | robocop-json-postprocess > eu.json 76 $ ./robocop-un-to-json < un.xml | robocop-json-postprocess > un.json 77 $ ./robocop-ofac-to-json < SDN.XML | robocop-json-postprocess > ofac-sdn.json 78 $ ./robocop-ofac-to-json --prefix OFAC-CONS- < CONSOLIDATED.XML \ 79 | robocop-json-postprocess > ofac-cons.json 80 $ ./robocop-uk-to-json < ConList.xml | robocop-json-postprocess > uk.json 81 ``` 82 83 Note on the OFAC consolidated (non-SDN) list: OFAC serves it in the legacy 84 `sdnList` format at `.../exports/CONSOLIDATED.XML`, and in the newer "advanced" 85 format at `CONS_ADVANCED.XML`. `robocop-ofac-to-json` reads the **legacy** format, 86 so a single converter handles both the SDN list and the consolidated list; use 87 `CONSOLIDATED.XML` (not `CONS_ADVANCED.XML`, which robocop does not parse). Because 88 OFAC reuses a few `uid`s across the two lists, pass `--prefix OFAC-CONS-` when 89 converting the consolidated list if you intend to merge it with the SDN list into 90 one file, so the records keep distinct `ssid`s.