尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗The investigator workspace is live at fintrac-aml.vercel.app. No sign-in, no environment variables. The book is synthetic.
Explainable AML monitoring and regulatory reporting for virtual-currency transactions.
Detect → Investigate → Explain → Report
All data in this project is synthetic. Reports are submitted to a local mock receiver. This system is not connected to FINTRAC and must not be used to file anything. See PRIVACY.md.
8KSS/FINTRAC-LVCTR is a single HTML
page that builds a JSON-LD Large Virtual Currency Transaction Report. It is a
genuinely useful artefact — it is where the field names, nesting and code lists
in this project were reconciled from — but it starts at the end of the
compliance process:
Human already knows the transaction is reportable → fill in the form
The hard problems are all upstream of that:
Thousands of transactions
↓ which ones matter?
↓ which ones aggregate, and on what relationship?
↓ who controls the related wallets?
↓ what indicators are present, and how strong?
↓ does a compliance officer need to investigate?
↓ what did the human decide, and why?
↓ which report(s), and does the payload actually validate?
Sentinel implements that pipeline and keeps the report builder at the end of it, where it belongs. docs/LEGACY_REPO_ANALYSIS.md documents exactly what was carried over and what was deliberately left behind.
No database server, no Node toolchain, no network access required.
pip install -r requirements.txt
python run.py
That seeds a synthetic ledger on first run, then serves the console at
http://127.0.0.1:8099/ with API docs at /docs.
Sign in as l.chen / sentinel1234 (compliance officer). Other demo accounts
exercise different halves of the RBAC matrix:
| Account | Role | Can |
|---|---|---|
j.okafor | Analyst | triage alerts, add notes, escalate |
s.rahman | Senior analyst | + record filing decisions, override scores |
l.chen | Compliance officer | + run the pipeline, build reports |
d.vasquez | Approver | + approve a case and submit reports |
a.petrov | Auditor | read-only, including the audit trail |
Password for all of them: sentinel1234. It is set by DEMO_PASSWORD — change
it for any deployment with a public URL, since this file documents the default.
To regenerate the dataset:
python -m scripts.seed --customers 40 --days 45
Run the tests:
pip install -r requirements-dev.txt
python -m pytest
The Next.js app in web/ is a view of one detection run: alerts, customer
risk, the ledger, a network graph, STR drafts, triage, case notes, a rule
simulator and draft filings. Case assignment and notes stay in the browser.
It does not need Postgres.
python -m scripts.export_snapshot
cd web
npm install
npm run dev
The dev server is at http://127.0.0.1:3000/. npm run build is the production
build (next build).
The graph page embeds a self-contained HTML file built with PyVis and NetworkX
from the bundled snapshot. Node colour and size follow residual risk, nodes are
grouped by entity type, and each node has an HTML tooltip. Physics defaults to
vis.js forceAtlas2Based. Pass --solver barnesHut for the Barnes–Hut model.
python -m scripts.build_pyvis_graph
That writes web/public/graph/entity-graph.html and inlines vis-network, so the
page does not call a CDN. The file is committed. Regenerate it after
python -m scripts.export_snapshot when the book changes. The same page can
switch to the in-app graph, which clusters by type, focuses a search hit,
dims non-neighbours, filters by risk and type, and highlights a path to a
sanctions-screening entity.
The geography page uses a Natural Earth world atlas committed at
web/public/geo/countries-50m.json (world-atlas 2). It does not need an API key.
The workspace now also has:
/api/v2/* in the Next.js app is typed with zod and reads the bundled snapshot, so npm run build in web/ needs no environment variables. If OPENAI_API_KEY or AI_GATEWAY_API_KEY is absent, the copilot still routes the same tools and cites the notes.
The FastAPI service mirrors that surface at /api/studio/* (OpenAPI at /docs): alerts, cases, entities, graph, stats, simulation, and chat. The Python chat uses LangChain when langchain-core is installed (see requirements-dev.txt) and the same deterministic router when no model key is set. Statistics and the book simulator live in app/services/statistics.py and app/services/book_simulator.py.
Two Vercel projects, documented in docs/DEPLOY_VERCEL.md.
| Setting | Value |
|---|---|
| Root directory | web |
| Framework | Next.js |
| Build command | next build |
| Environment variables | none |
Import the repository, set the root directory to web, and deploy. Pages and
/api/* read web/src/data/snapshot.json.
The FastAPI app runs as a single Python serverless function serving both the
API and the vanilla console. Root directory is the repository root, not web.
Three things are worth knowing before you start, because each one produces a demo that looks like it works and quietly does not:
DATABASE_URL). The app
refuses to start on a serverless host with non-durable storage rather than
pretending, unless you opt in with ALLOW_EPHEMERAL_STORAGE=1.scikit-learn from requirements.txt; the anomaly layer abstains cleanly,
labels itself 1.0-unavailable, and every rule-based control keeps working.GET /api/health reports which mode is live:
{ "storage": { "durable": true }, "capabilities": { "anomaly_detection": true } }
Provision a database without demo data:
DATABASE_URL="postgresql+psycopg://..." python -m scripts.provision
For anything operational rather than demonstrative, prefer a container with a scheduler (Cloud Run, Fly.io, Render) over serverless: the detection pipeline is a batch job, and it belongs on a cron rather than an HTTP request. No code changes are needed — only where you run it.
Sign in and open the case for Maple Digital Imports Ltd.
The company declared CAD 20,000 of monthly crypto activity at onboarding. Over one day it receives CAD 21,600 from six distinct wallets, moves CAD 10,100 straight back out to a wallet tagged as a high-risk exchange, and shares a beneficiary with an unrelated customer.
Every layer has something to say about it:
| Layer | Finding |
|---|---|
| 24-hour rule | receipts aggregate to CAD 24,999.99 on a shared beneficiary → LVCTR obligation, due in 5 working days |
| Rules | fan-in, near-threshold accumulation, baseline deviation, rapid pass-through, high-risk counterparty, shared beneficiary, chain hopping |
| ML | behavioural anomaly in the top percentile of the population, with feature attributions |
| Graph | the network, the high-risk counterparty and the shared beneficiary, plotted |
| Copilot | a cited STR narrative that passes the unsupported-claim verifier |
| Report | an LVCTR payload that validates clean at all four local levels |
| Controls | the case cannot be closed unfiled, the owner cannot self-approve, and the submitted report cannot be rebuilt |
Full script: docs/DEMO_SCENARIOS.md.
ingestion ──► CAD valuation ──► 24-hour aggregation ──► rules engine
(snapshotted) (deduplicated) (versioned)
│
audit ◄── mock receiver ◄── validation ◄── LVCTR builder │
▲ ▲ ▼
└──────── case management ◄── human review ◄──── risk score
(+ graph, + anomaly)
DATABASE_URL)web/, reading a bundled snapshot. Zod studio routes, a LangChain.js copilot with a no-key fallback, and WebGL force graphs/api/studio over the same snapshot, with a Python LangChain copilot that degrades to deterministic tool routingMore detail: docs/ARCHITECTURE.md.
These are deliberate, and each one is enforced or documented rather than assumed:
submission_endpoint is hard-guarded to mock; anything else raises.fintrac-sentinel/
├── app/
│ ├── config.py regulatory parameters and deployment settings
│ ├── models.py ORM: customers, wallets, transactions, cases, reports, audit
│ ├── security.py password hashing, tokens, the RBAC matrix
│ ├── audit.py append-only hash-chained trail
│ ├── rules/ aml_rules.yaml — the rule catalogue
│ ├── schemas_json/ lvctr.schema.json
│ ├── services/ one module per pipeline stage (see services/__init__.py)
│ ├── routers/ the HTTP API
│ └── static/ the investigator console (no build step)
├── scripts/
│ ├── generate_synthetic.py scenario-driven dataset generator
│ ├── seed.py seed + full detection run
│ └── export_snapshot.py detection run → web/src/data/snapshot.json
├── web/ Next.js investigator workspace (Vercel root: web)
├── tests/ compliance regressions first, including cash and wires
└── docs/
| Document | Contents |
|---|---|
| ARCHITECTURE.md | pipeline stages, boundaries, scaling notes |
| DATA_MODEL.md | tables, invariants, decimal and time conventions |
| AML_RULES.md | every rule, its parameters, and its tuning history |
| FINTRAC_MAPPING.md | canonical model → LVCTR JSON-LD, field by field |
| LEGACY_REPO_ANALYSIS.md | what was reused from the reference repo, and what was not |
| MODEL_CARD.md | the anomaly model: intended use, limitations, governance |
| SECURITY.md | RBAC matrix, controls, what a real deployment must add |
| PRIVACY.md | synthetic-data policy and PII handling |
| DEMO_SCENARIOS.md | every planted scenario and what should fire |
| DEPLOY_VERCEL.md |
Always verify current requirements before implementing regulatory logic. The logic here was written against:
The payload format follows the 2021 JSON-LD structure encoded in the reference repository. A reporting entity must reconcile every field against FINTRAC's current technical documentation before filing anything.
This project is released under the MIT License — see LICENSE.
8KSS/FINTRAC-LVCTRThe reference repository 8KSS/FINTRAC-LVCTR
is licensed GPL v2, so it is worth being precise about what was and was not
taken from it.
Not taken: any source code. That project is a single self-contained HTML page with inline JavaScript; this one is a Python/FastAPI application with a separate front end. No file, function or block was copied or translated.
Taken: the shape of FINTRAC's report format — field names, object
nesting, $id/$ref conventions, code-list values and the field length and
type constraints. These originate in FINTRAC's own technical specification for
the LVCTR upload format; the reference repository is where they were
conveniently transcribed, and it is credited for that throughout
docs/LEGACY_REPO_ANALYSIS.md and
docs/FINTRAC_MAPPING.md. Everything derived from it
is confined to app/services/fintrac_mapper.py and
app/schemas_json/lvctr.schema.json.
A data-interchange format is an interface specification, not an expressive work, and reimplementing one independently is not generally held to create a derivative work. That is the basis for licensing this project under MIT rather than GPL v2. It is a considered position, not legal advice — anyone redistributing this, or building on it commercially, should form their own view.
The reference repository deserves the credit either way: it is the artefact that made the 2021 LVCTR format legible to people outside the reporting entities that already had it working.
| Next.js workspace and the FastAPI console |