jasonrkeen/sanctions-ownership-network-investigator
GitHub: jasonrkeen/sanctions-ownership-network-investigator
一个基于OFAC与GLEIF数据源的制裁筛查与企业所有权网络调查工具,通过多层级股权传播分析帮助合规分析师识别直接或间接的制裁关联。
Stars: 0 | Forks: 0
# 制裁所有权网络调查器
一个由数据源支持的最小可行性产品(MVP),用于制裁筛查、实体解析、所有权分析和关系探索。
该项目旨在回答一个实际问题:
它将一个可立即运行的标准库 Python pipeline 与可选的 Streamlit、PostgreSQL、Neo4j、Docker 和 PDF 报告层结合在一起。
**项目状态:** 公开作品集发布,版本 1.0.0。本应用程序是用于分析师决策支持的演示,而非生产级合规软件、法律建议或最终的法律裁定。
## 评估者快速开始
使用 Python 3.11 或更高版本运行确定性虚构案例:
```
python main.py --mode sample --query "Harbor Meridian Trading LLC"
```
预期结果:`ownership_derived_candidate`。该命令会创建一个由数据源支持的案例目录,无需安装包或连接网络。请参阅[演示指南](docs/DEMO_WALKTHROUGH.md)以获取仪表盘、工作流、分析师审查、比较和导出的完整介绍。
## 与众不同之处
传统的名单筛查只是将名称与制裁名单进行比对。本项目将其拆分为四个分析问题:
1. **身份:** 记录是否指向同一实体?
2. **指定:** 解析后的实体是否被直接指定(制裁)?
3. **所有权:** 加载的直接或间接所有权是否达到配置的聚合阈值?
4. **控制与背景:** 是否存在足以触发加强审查但无法直接判定为受限状态的关系?
每个匹配项和关系都会保留其来源、置信度、证据和审查状态。输出结果旨在为分析师提供支持——而非最终的法律裁定。
## 当前 MVP 功能
- 内置的虚构演示网络
- 下载并解析 OFAC 的四个关系型 SDN CSV 文件
- 按名称或精确 LEI 进行针对性的 GLEIF 法人实体搜索
- 结合间距感知名称比对的 GLEIF 候选排序选择
- GLEIF Level 1 身份、地址、注册和法律形式富集
- GLEIF 直接和最终会计合并母公司图谱链接
- 主名称和别名筛查
- 法律后缀标准化与 token 感知的模糊比对
- 无需安装数据库的 SQLite 调查存储
- 使用可配置 50% 阈值的迭代所有权传播
- 区分直接指定、所有权派生候选人和控制关系
- 同址调查指标
- 两跳或三跳的图谱提取
- 兼容 Neo4j 的节点和关系导出
- Markdown 及可选的 PDF 调查简报
- Streamlit 实体、网络、匹配审查和证据视图
- 支持重新打开历史运行记录的多案件调查注册表
- 具备状态和优先级过滤功能的可搜索案件队列
- 仅追加的工作流状态、优先级、分配、标签和更新说明
- CSV 和 JSON 格式的案件队列合并导出
- 包含候选人和图谱差异的归档案件并排比较
- 兼容旧版的 `outputs/latest` 快照,方便系统集成
- 仅追加的分析师处置意见、备注、审查者身份和时间戳
- PostgreSQL schema 和 Docker Compose 环境
- 标准库自动化测试及 GitHub Actions
## 文档说明
| 文档 | 用途 |
|---|---|
| [架构](docs/ARCHITECTURE.md) | 组件、数据流、存储和生产差距 |
| [方法论](docs/METHODOLOGY.md) | 匹配、所有权和分析规则 |
| [模型卡片](docs/MODEL_CARD.md) | 预期用途、局限性和人工监督 |
| [数据字典](docs/DATA_DICTIONARY.md) | 记录、字段和关系 |
| [分析师工作流](docs/ANALYST_WORKFLOW.md) | 审查、队列和审计跟踪流程 |
| [GLEIF 富集](docs/GLEIF_ENRICHMENT.md) | 身份与会计母公司边界 |
| [演示指南](docs/DEMO_WALKTHROUGH.md) | 可复现的审查者演示与截图计划 |
| [作品集简报](docs/PORTFOLIO_BRIEF.md) | 简历要点、项目总结和面试话题 |
| [1.0.0 版本发布说明](docs/RELEASE_NOTES_v1.0.0.md) | 安装、亮点和已知限制 |
| [发布检查清单](docs/RELEASE_CHECKLIST.md) | 验证与归档要求 |
## 演示发现
内置的示例完全是虚构的:
```
Alex Riverstone (direct demonstration designation)
└── owns 60% of Meridian Holdings PLC
└── owns 55% of Harbor Meridian Trading LLC
```
引擎首先将 Meridian Holdings 标记为所有权派生候选人,然后将该发现传播给 Harbor Meridian Trading。这在保持直接名称筛查独立的同时,测试了多层所有权逻辑。
## 快速开始
推荐使用 Python 3.11 或更高版本。
### 1. 运行零依赖演示
```
python main.py --mode sample --query "Harbor Meridian Trading LLC"
```
命令行演示无需执行 `pip install`。
每次运行的结果都会保存在 `outputs/cases//` 下:
- `investigation_result.json`
- `investigation_brief.md`
- `investigation_brief.pdf` (安装了 ReportLab 时生成)
- `investigation_graph.json`
- `investigator.sqlite`
- `neo4j/nodes.csv`
- `neo4j/relationships.csv`
CLI 还会将 `outputs/latest/` 刷新为兼容性快照,以供 Docker、Neo4j 导入和早期集成使用。在发布新的最新快照之前,应用程序会自动归档未注册的旧版最新案例,从而保留其输出产物和分析师审查数据库。
### 2. 运行分析师仪表盘
```
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
pip install -e ".[dashboard,pdf]"
streamlit run app.py
```
仪表盘默认打开案件调查注册表。其工作区支持:
- 选择并重新打开之前的调查运行
- 按案件文本、工作流状态和优先级过滤队列
- 本地分配、打标签以及仅追加的工作流事件历史记录
- 合并导出为 CSV 和 JSON 队列
- 对过往调查产出物进行基准对比审查
- 审查生成的核心发现及解析出的实体
- 支持可选地址节点的实时图谱探索
- 独立的身份解析与制裁筛查证据
- GLEIF 富集和来源注册表审查
- 下载 JSON、图谱、Markdown 和 PDF 案件产出物
- 仅追加的分析师处置意见和审查历史
再次运行 `main.py` 可添加另一个归档案例并刷新兼容性快照。分析师审查存储在每个案例的 `investigator.sqlite` 中,并依附于该运行,同时与系统自动生成的分类保持独立。
### 3. 下载并筛查当前的 OFAC SDN 文件
```
python main.py --mode live --query "ENTITY NAME"
```
下载器会发送 OFAC 制裁名单服务所要求的 User-Agent 标头。它会检索:
- `SDN.CSV`
- `ALT.CSV`
- `ADD.CSV`
- `SDN_COMMENTS.CSV`
OFAC 解释说,需要全部四个文件才能重建主记录、别名、地址和详细备注之间的一对多关系。
要针对已下载的文件重新运行:
```
python main.py --mode live --skip-download --query "ENTITY NAME"
```
### 4. 添加 GLEIF 身份和会计母公司富集
```
python main.py --mode live --gleif-enrich --query "JPMorgan Chase & Co."
```
使用两位字母的国家代码缩小名称搜索范围:
```
python main.py --mode live --gleif-enrich --country US --query "ENTITY NAME"
```
如果已知正确的记录,请使用精确的 LEI:
```
python main.py --mode live --gleif-enrich --gleif-lei "LEI_HERE" --query "ENTITY NAME"
```
选定的 GLEIF 记录及其已发布的母公司链接将被合并到 OFAC 调查所使用的同一个 SQLite 存储、图谱 JSON、Neo4j CSV、Markdown 简报和 PDF 简报中。仪表盘还包含一个独立的 GLEIF 查找工作区,用于候选排序选择和母公司网络审查。候选人评分有助于消除歧义,但并不代表身份概率;分析师应结合司法管辖区、标识符、注册状态和地址来确认 LEI。
GLEIF Level 2 数据标识了直接和最终的**会计合并母公司**。它不提供所有权百分比数值。因此,应用程序将这些链接存储为上下文图谱证据,并特意将其排除在 OFAC 50% 规则的传播计算之外。
## Docker 环境
将 `.env.example` 复制为 `.env`,替换演示密码,然后运行:
```
docker compose up --build
```
服务:
| 服务 | 地址 | 用途 |
|---|---|---|
| Streamlit | `http://localhost:8501` | 分析师界面 |
| PostgreSQL | `localhost:5432` | 关系型暂存和案件数据 |
| Neo4j Browser | `http://localhost:7474` | 图谱探索 |
| Neo4j Bolt | `bolt://localhost:7687` | 应用程序连接 |
命令行 MVP 默认写入 SQLite。内置的 PostgreSQL schema 和 Neo4j 导出是下一阶段的迁移基础。
## 分析工作流
```
flowchart LR
A[Source ingestion] --> B[Normalize records]
B --> C[Resolve identities]
C --> D[Build relationship graph]
D --> E[Evaluate ownership]
E --> F[Analyst review and report]
```
## 分析师审查与审计跟踪
最新调查工作流记录了五种人工处置意见之一:
- 需要更多信息
- 身份已确认
- 身份被拒绝
- 已升级进行合规审查
- 已关闭 - 无实质性指标
每条记录都保存了运行 ID、目标身份、原始系统分类、审查者、所需备注和时间戳。记录仅为追加模式:记录审查会创建一个新的审计事件,绝不会覆盖模型输出或之前的分析师决策。
## 案件工作流
每个案件都从派生的默认状态 **Open / Normal / Unassigned** 开始。分析师可以记录受控的状态和优先级值、本地受理人、逗号分隔的标签、执行更新的人员以及所需的理由。
工作流更改是仅追加的事件。最新的事件提供了当前队列状态,而不会删除之前的分配或状态历史记录。工作流状态仅用于管理工作路由;它不会改变制裁分类或分析师的处置意见。
## 案件比较与队列导出
**案件比较**工作区会比较两个归档的运行记录,并报告:
- 分类与目标更改
- 身份得分与候选人数量差值
- 新增或移除的身份及制裁筛查候选人
- 新增或移除的图谱关系
- 来源与调查指标差异
- 工作流状态和分析师审查活动
比较结果 JSON 可供下载以供复现。结果描述了已存储产出物之间的差异;它不建立因果关系,也不代表恶化、改善或法律状态的变化。
案件调查侧边栏中的**队列导出**控件可将所有案件摘要下载为 CSV 或 JSON,包括状态、优先级、受理人、标签、工作流时间戳、事件计数和分析师审查计数。
## 匹配方法论
名称匹配器使用:
- Unicode 标准化
- 标点和空格标准化
- 可选的法律后缀移除
- 直接字符序列比对
- token 排序比对
- token 重叠度
- 可选的国家和精确标识符上下文
精确的标识符优先于模糊的名称比对。仅凭名称得分绝不会自动合并两条记录。
评分是排序辅助工具,而非经过校准的概率。应在类似于组织自身客户、语言和司法管辖区的已标注实体对上评估生产环境的阈值。
## 所有权方法论
引擎从直接指定的实体开始。对于每个未分类实体,它会汇总已被标记为直接指定或所有权派生的实体所持有的已加载百分比。超过配置阈值的实体将被添加到下一轮传播中。
此图谱操作可以识别出如下链条:
```
blocked owner -> majority-owned holding company -> majority-owned subsidiary
```
这种分类被特意称为 `ownership_derived_candidate`。分析师必须验证:
- 所有权百分比
- 直接与间接所有权
- 总计持股
- 生效日期
- 资产剥离
- 特定项目的限制
- 许可证和授权书
- 当前的官方指南
控制关系被单独存储和报告,因为根据 OFAC 的 50% 规则,单纯的控制并不等同于所有权。
## 数据来源
- [OFAC SDN 名单](https://ofac.treasury.gov/specially-designated-nationals-and-blocked-persons-list-sdn-human-readable-lists)
- [OFAC 关系平面文件教程](https://ofac.treasury.gov/sdn-list-data-formats-data-schemas/tutorial-on-the-use-of-list-related-legacy-flat-files)
- [OFAC 50% 规则常见问题解答](https://ofac.treasury.gov/faqs/topic/1521)
- [GLEIF API](https://www.gleif.org/en/lei-data/gleif-api) — 已实现针对性的身份和会计母公司富集
- [GLEIF Level 2 数据](https://www.gleif.org/en/lei-data/access-and-use-lei-data/level-2-data-who-owns-whom)
- [SEC EDGAR APIs](https://www.sec.gov/search-filings/edgar-application-programming-interfaces) — 计划实现的文件报告富集
- [ICIJ Offshore Leaks 下载](https://offshoreleaks.icij.org/pages/database) — 计划实现的调查富集
当前版本实现了 OFAC 数据摄取和针对性的 GLEIF 富集。其他数据源已记录在案,留待后续受控阶段使用。
## 仓库结构
```
sanctions-ownership-network-investigator/
├── .github/
├── app.py
├── main.py
├── CHANGELOG.md
├── CONTRIBUTING.md
├── SECURITY.md
├── CITATION.cff
├── data/
│ ├── raw/ofac/
│ └── sample/
├── docs/
├── scripts/
├── sql/
├── src/sowni/
├── tests/
├── Dockerfile
├── docker-compose.yml
└── pyproject.toml
```
## 验证
运行:
```
python -m unittest discover -s tests -v
python scripts\check_publication.py
```
该测试套件会检查标准化、别名筛查、所有权传播、OFAC 关系文件解析、GLEIF 身份/母公司解析、仪表盘产出物加载与图谱渲染、旧案件迁移、多案件索引、仅追加的分析师审查与工作流事件、受控的工作流值、队列导出、确定性的案件比对差异、将 GLEIF 会计母公司链接排除在所有权百分比计算之外的情况,以及完整的演示 pipeline。发布审计会检查所需的公开文件、版本同步、文档链接、发布说明和披露边界。
## 构建干净的发布版本
请使用标准库的发布构建器,而不要手动压缩工作文件夹:
```
python scripts\build_release.py
```
构建器会在父目录中创建 `sanctions-ownership-network-investigator-mvp.zip`。它会验证归档并排除:
- `.venv`、`.venv-1`、`venv` 和其他带编号的虚拟环境
- Python 缓存以及测试/代码缓存
- `*.egg-info`、构建和分发元数据
- `.env`、SQLite 数据库和现有的 ZIP 文件
- 下载的 OFAC 文件
- 生成的报告、图谱、PDF 和案件输出
- 临时的 PDF 渲染文件
归档文件会保留 `.gitkeep` 占位符,以便在解压后重新创建所需的原始数据和输出目录。在发布之前,请运行 `python scripts\check_publication.py` 并查看 [`docs/RELEASE_CHECKLIST.md`](docs/RELEASE_CHECKLIST.md)。
## 路线图
- GLEIF 报告例外详情
- PostgreSQL repository adapter
- Neo4j 驱动程序集成
- 具备标识符感知能力的实体解析
- 具备时间感知能力的所有权和资产剥离分析
- 跨多个所有者的汇总受限所有权
- SEC 子公司和所有权文件提取
- ICIJ 核对与受控富集
- 身份验证、基于角色的访问控制和主管审批
- 基于已标注匹配与非匹配对的回溯测试
## 负责任的使用
本项目用于合法的合规研究、尽职调查、教育和分析师决策支持。它不能用于证明某人或组织存在不当行为。名单匹配、同址、离岸数据集出现或网络连接必须在具体语境中进行审查。
在根据结果采取行动之前,请务必咨询当前的官方来源以及合格的合规或法律人员。
## 许可证
MIT。请参阅 [LICENSE](LICENSE)。
标签:Kubernetes, Neo4j, Python, Streamlit, 代码示例, 实体解析, 数据分析, 无后门, 测试用例, 访问控制, 请求拦截, 逆向工具, 金融合规