Metadata-Version: 2.5
Name: warninglists
Version: 0.1.0
Summary: Regulator warning lists (IOSCO I-SCAN, CONSOB website blocking orders, FCA) in one schema, with domain and name matching. Library, CLI and MCP server.
Project-URL: Documentation, https://github.com/mariotrerotola/warninglists#readme
Project-URL: Source, https://github.com/mariotrerotola/warninglists
Project-URL: Issues, https://github.com/mariotrerotola/warninglists/issues
Author: Mario Trerotola
License-Expression: MIT
License-File: LICENSE
Keywords: consob,fca,financial-crime,investment-fraud,iosco,mcp,regtech,suptech,typosquatting,warning-list
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: Legal Industry
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Security
Requires-Python: >=3.10
Requires-Dist: idna>=3.6
Requires-Dist: publicsuffixlist>=1.0
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Provides-Extra: mcp
Requires-Dist: mcp>=1.2; extra == 'mcp'
Description-Content-Type: text/markdown

# warninglists

Warning lists published by financial regulators, in one schema, with domain and name matching.
A Python library, a command line tool and an MCP server.

| Source | What it is | How it is read |
|---|---|---|
| `iosco` | **IOSCO I-SCAN**: alerts submitted by IOSCO members (FCA, CNMV, AMF, FINMA, SEC, CONSOB, …) | public CSV export |
| `consob` | **CONSOB website blocking orders** (Italy, since July 2019) | full text of the press releases |
| `fca` | **FCA Warning List**, latest items | official warnings RSS feed |

Why three sources when I-SCAN already aggregates regulators: I-SCAN is voluntary and lags.
On 14 October 2026, of the 1,944 registrable domains named in CONSOB blocking orders,
598 were also in I-SCAN; of the 20 domains in that week's FCA feed, 1 was.
`warninglists stats` recomputes both figures on your own cache.

## Install

```bash
pip install warninglists            # library and CLI
pip install "warninglists[mcp]"     # plus the MCP server
```

Python 3.10+. Two dependencies: `publicsuffixlist` and `idna`.

## Command line

```bash
warninglists fetch                          # download all three lists into ~/.cache/warninglists
warninglists check https://clientzone.dmaeu.com/login
warninglists check etoro.com --json
warninglists search "Goldgcapital"
warninglists stats                          # freshness and completeness of each source
warninglists export --format csv -o alerts.csv
```

```text
$ warninglists check https://clientzone.dmaeu.com/login
https://clientzone.dmaeu.com/login: 1 listed, 0 similar

LISTED
  [consob] CONSOB (Italy) · blocked · 2026-09-24
    host: clientzone.dmaeu.com · DMAsseteuBV
    https://www.consob.it/documents/d/area-pubblica/comunicato-stampa-del-24-settembre-2026
```

`check --exit-code` exits with 1 when anything is listed, for use in scripts.

## Python

```python
from warninglists import store
from warninglists.sources import consob, fca, iosco

for source in (iosco, consob, fca):
    store.save(source.fetch())

index = store.load_index()
for match in index.check("tradoxiumpro.com"):
    print(match.relation, match.alert.authority, match.alert.published, match.alert.source_url)
```

## MCP server

The server reads the local cache and never downloads; run `warninglists fetch` first.
It exposes `check_domain`, `search_entity` and `list_sources`.

```json
{
  "mcpServers": {
    "warninglists": { "command": "warninglists", "args": ["mcp"] }
  }
}
```

## Reading a result

Every match has a **relation**:

- **`listed`**: the queried host, registrable domain or entity name appears in an alert.
- **`similar`**: an alert contains a look-alike domain (edit distance, confusable characters,
  the query as a token inside a longer label) or a name equal to the domain's label.
  Similarity has no direction. If you query a legitimate brand, similar entries are more likely
  clones *of* that brand than evidence against it.

Three more things to keep in mind:

- An alert is issued by one authority for its own jurisdiction. A firm licensed in one country
  can be listed by a regulator of another country where it is not authorised; the
  `authority` and `jurisdiction` fields say which.
- No match means these lists do not contain the query. They are not complete, and they are not
  a register of authorised firms.
- Clone warnings concern firms impersonating an authorised one. For FCA clones the genuine
  firm is kept apart in `details["impersonated_firm"]` and never attributed to the clone.

## How complete each source is

Each fetch records what the source makes measurable, in `warninglists stats`:

- **CONSOB.** Every press release states how many sites it blocks and the running total. On the
  full archive (285 releases, 19 September 2019 to 9 October 2026) the parsed site count matches
  the declared count in 261 of 271 releases, and the parsed sites add up to 1,803 against a
  declared total of 1,838. The remaining mismatches are listed one by one; some come from the
  releases themselves (truncated URLs such as `https://kapidexnx.`, and a counting unit that
  differs between releases). The thresholds and every correction made to the parser are in
  [docs/verification.md](docs/verification.md).
- **I-SCAN.** Date of the latest validated alert, and how many alerts carry no domain
  (27,542 of 47,367 on 14 October 2026: those are matchable by name only).
- **FCA.** The feed holds about 20 items, roughly one week. Older FCA warnings are in I-SCAN,
  where the FCA is the largest contributor.

## Data and terms of use

The package contains no data. Lists are downloaded on your machine, when you run `fetch`, and
stay there. Every record keeps the issuing authority and a `source_url`. Before reusing the data,
read each source's terms:

- **IOSCO I-SCAN**: public information; reuse requires attribution and no distortion. The I-SCAN
  API needs a signed agreement; this package uses the public CSV export instead.
- **CONSOB**: reuse for study, research, information and documentation, citing the source and
  without altering meaning or completeness ([informazioni legali](https://www.consob.it/web/consob/informazioni-legali)).
- **FCA**: saved copies are for personal use or use within your organisation, not for
  redistribution ([fca.org.uk/legal](https://www.fca.org.uk/legal)).

The FCA fixture in `tests/` is synthetic for that reason; the I-SCAN and CONSOB fixtures are short
excerpts with attribution ([tests/fixtures/NOTICE.md](tests/fixtures/NOTICE.md)).

From datacenter networks (CI runners, cloud VMs) the I-SCAN export has been seen to answer 403.
Download the CSV from https://www.iosco.org/i-scan/ ("Export to CSV") and run
`warninglists fetch iosco --iosco-file <file.csv>`. Requests identify themselves as
`warninglists/<version>`; CONSOB pages are fetched two seconds apart.

## Schema

```python
Alert(
    source="consob",                 # iosco | consob | fca
    source_id="2026-10-09:goldgcapital.net",
    authority="CONSOB",              # for iosco: the member that submitted the alert
    jurisdiction="Italy",
    kind="blocked",                  # unauthorised | clone | blocked | other
    names=["Goldgcapital"],
    urls=["goldgcapital.net", "my.aipltfrm.com"],
    hosts=[...], domains=[...],      # derived; only values valid under the Public Suffix List
    emails=[...],
    published="2026-10-09",
    source_url="https://www.consob.it/documents/d/area-pubblica/comunicato-stampa-del-9-ottobre-2026",
    details={...},                   # source-specific: sites vs pages, categories, impersonated firm
)
```

Domains are handled with the Public Suffix List only: unknown TLDs are rejected, so tokens such as
`decreto.crescita` in free text never become domains. Two traps remain that the PSL cannot see,
because `.analytics` and `.target` are real TLDs: script code is stripped from pages before parsing.

## License

MIT for the code. The data belongs to the issuing authorities and follows their terms.
