Automated KYB & Vendor Due Diligence β Desktop Application
VendorLens fans out to 12+ intelligence APIs in parallel, extracts adverse findings with Google Gemini AI, and surfaces risk across sanctions, litigation, media, and identity verification β all in a local Electron desktop app backed by FastAPI and MySQL.
| Layer | Technology |
|---|---|
| Desktop app | Electron 42 Β· React 19 Β· TypeScript Β· Vite Β· Tailwind CSS 4 |
| Backend | Python 3.11 Β· FastAPI Β· asyncio Β· BackgroundTasks |
| Database | MySQL 9.x Β· SQLAlchemy ORM Β· pymysql |
| AI | Google Gemini 2.0 Flash (google-genai) |
| India KYC | AuthBridge (GSTIN Β· PAN Β· MSME Β· Court Β· Sanctions) |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β VendorLens Desktop App β
β Electron 42 Β· React 19 Β· TypeScript β
β β
β IntakeForm βββΆ ScanSelector βββΆ Dashboard β
β (manual / xlsx) (quick / deep) (5-tab report) β
βββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββ
β HTTP Β· localhost:8000
βββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββ
β FastAPI Backend β
β Python 3.11 Β· asyncio Β· BackgroundTasks β
β β
β POST /intake POST /scan GET /scan/{id}/status β
β POST /intake/excel GET /scan/{id}/report β
βββββ¬βββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββ
β β
βββββΌβββββββββββ ββββββββββββββββΌβββββββββββββββββββββββββ
β MySQL 9.x β β External API Layer (asyncio.gather) β
β 4 tables β β 12+ providers Β· ~30 concurrent tasks β
ββββββββββββββββ ββββββββββββββββββββββ¬βββββββββββββββββββ
β
βββββββββββββΌββββββββββββ
β Gemini 2.0 Flash β
β findings + risk scoresβ
βββββββββββββββββββββββββ
Vendor Input (manual form OR .xlsx batch upload)
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Phase 1 Β· Parallel API Fan-out (~30 concurrent tasks) β
β β
β Corporate Sanctions News & Adverse Media β
β OpenCorp OpenSanctions GDELT Β· NewsAPI Β· Serperβ
β β
β Domain Intel Address India / AuthBridge β
β WHOIS Β· SSL GooglePlaces GSTIN Β· PAN Β· MSME β
β Microlink Wikipedia Court Β· Defaulting Dir β
β Global Sanctions Β· Emailβ
ββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ
β
βΌ (India vendors only)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Phase 2 Β· Alternate-name Enrichment β
β GSTIN β registered trade names β full search re-run β
ββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Gemini 2.0 Flash β Findings Extraction β
β findings[] Β· section_analysis{} Β· article_scores[]β
ββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ
β
βΌ
Risk Report β MySQL β Dashboard
| Tool | Version | Notes |
|---|---|---|
| Python | 3.11+ | 3.12 supported |
| Node.js | 20 LTS+ | For frontend & Electron |
| MySQL | 8.0+ or 9.x | Tables auto-created on first run |
| Git | any |
Windows (user-local ZIP install, no admin required)
# Extract MySQL ZIP to C:\Users\<you>\Apps\mysql-9.x-winx64
# Initialize data directory (first time only):
C:\Users\<you>\Apps\mysql-9.x-winx64\bin\mysqld.exe --initialize-insecure --defaults-file="C:\Users\<you>\Apps\mysql-9.x-winx64\my.ini"
# Start MySQL (from project root):
.\start-mysql.ps1
# Set password + create database (first time only):
mysql -u root --connect-expired-password -e "ALTER USER 'root'@'localhost' IDENTIFIED BY 'vendorlens_dev'; FLUSH PRIVILEGES; CREATE DATABASE IF NOT EXISTS vendorlens CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"macOS
brew install mysql
brew services start mysql
mysql -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY 'vendorlens_dev'; FLUSH PRIVILEGES; CREATE DATABASE IF NOT EXISTS vendorlens CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"Windows
cd backend
python -m venv venv
.\venv\Scripts\activate
pip install -r requirements.txt
copy .env.example .env
# Open .env and fill in your API keys
uvicorn app.main:app --host 127.0.0.1 --port 8000 --reloadmacOS / Linux
cd backend
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
# Open .env and fill in your API keys
uvicorn app.main:app --host 127.0.0.1 --port 8000 --reloadOpen a second terminal. Backend must be running on port 8000 first.
Windows
cd frontend
npm install
npm run dev # Vite dev server β http://localhost:5173
# To run as Electron desktop app (third terminal):
npx electron .macOS / Linux
cd frontend
npm install
npm run dev # Vite dev server β http://localhost:5173
# To run as Electron desktop app (third terminal):
npx electron .Mock mode β Set
MOCK_API_CALLS=trueinbackend/.envto run scans without consuming API credits. Returns realistic randomized findings for UI development.
Copy from backend/.env.example and fill in your keys.
# ββ Database
MYSQL_HOST=127.0.0.1
MYSQL_PORT=3306
MYSQL_USER=root
MYSQL_PASSWORD=vendorlens_dev
MYSQL_DB=vendorlens
# ββ Required APIs
GEMINI_API_KEY=your_key
OPENSANCTIONS_API_KEY=your_key
SERPER_API_KEY=your_key
NEWS_API_KEY=your_key
# ββ Optional APIs
OPENCORPORATES_API_KEY=
GOOGLE_MAPS_API_KEY=
MICROLINK_API_KEY=
# ββ India only (AuthBridge)
AUTHBRIDGE_API_KEY=your_key
AUTHBRIDGE_API_SECRET=your_secret
# ββ Dev
MOCK_API_CALLS=false
GEMINI_MODEL=gemini-2.0-flash| Env Var | Provider | Status | Purpose |
|---|---|---|---|
GEMINI_API_KEY |
Google AI Studio (AIzaβ¦) or Vertex AI express mode (AQ.Abβ¦) |
Required | LLM findings extraction & risk synthesis. The transport is auto-detected from the key prefix; set GEMINI_API_BACKEND=studio|vertex to force it. |
OPENSANCTIONS_API_KEY |
OpenSanctions | Required | Sanctions & PEP screening |
SERPER_API_KEY |
Serper.dev | Required | Adverse web, reviews, profile, news |
NEWS_API_KEY |
NewsAPI.org | Required | Adverse media + regulatory news |
OPENCORPORATES_API_KEY |
OpenCorporates | Optional | Company registry (140+ jurisdictions) |
GOOGLE_MAPS_API_KEY |
Google Cloud | Optional | Address & operational status |
MICROLINK_API_KEY |
Microlink | Optional | Domain metadata (free tier available) |
| Wikipedia API | Wikimedia | Free | Always active β no key needed |
AUTHBRIDGE_API_KEY |
AuthBridge | India only | GSTIN Β· PAN Β· MSME verification |
AUTHBRIDGE_API_SECRET |
AuthBridge | India only | Court Β· Defaulting Director Β· Global Sanctions Β· Email |
Note β All AuthBridge endpoint paths in
backend/app/api/endpoints.pyare marked# CONFIRM with AuthBridge docs. Verify each path against your plan's API documentation before going live.
Project_1/
β
βββ start-mysql.ps1 β Windows user-local MySQL launcher
βββ docker-compose.yml β Docker config (future use)
β
βββ backend/
β βββ .env β your credentials (gitignored)
β βββ .env.example β template for above
β βββ requirements.txt
β βββ Dockerfile β future Docker deployment
β βββ app/
β βββ main.py β FastAPI app, routes, scan workflow
β βββ api/
β β βββ endpoints.py β all API client classes
β βββ core/
β β βββ database.py β SQLAlchemy engine (MySQL + pymysql)
β β βββ models.py β ORM models (4 tables)
β βββ services/
β βββ data_aggregator.py β Phase 1+2 parallel API fan-out
β βββ llm_service.py β Gemini 2.0 Flash integration
β βββ token_manager.py
β
βββ frontend/
β βββ package.json
β βββ vite.config.ts
β βββ electron/
β β βββ main.ts β Electron entry point
β βββ src/
β βββ App.tsx β Router: / β /scan/:id β /dashboard/:id
β βββ components/
β βββ IntakeForm.tsx β vendor input form + Excel upload
β βββ ScanSelector.tsx β quick / deep scan choice
β βββ Dashboard.tsx β top-level report view + polling
β βββ dashboard/
β βββ OverviewTab.tsx β risk summary + source heatmap
β βββ FindingsTab.tsx β adverse findings list
β βββ NewsTab.tsx β AI-scored articles
β βββ WebTab.tsx β domain, reviews, places
β βββ IndiaTab.tsx β AuthBridge checks (India)
β
βββ inputs/
β βββ VendorLens_Intake_Template.xlsx β Excel template for batch
β
βββ docs/
βββ VendorLens_PRD_Techincal.md
βββ KEYS.md
| Column | Type | Notes |
|---|---|---|
input_id |
UUID PK | auto-generated |
legal_name |
VARCHAR(255) | indexed |
website_domain |
VARCHAR(255) | |
jurisdiction_country |
VARCHAR(10) | e.g. IN, US |
tax_identifier |
VARCHAR(100) | GSTIN for India |
pan_number |
VARCHAR(50) | India |
msmed_certificate_number |
VARCHAR(100) | India |
director_names |
JSON | array of strings |
corporate_email_domain |
VARCHAR(255) | used for email verification |
source_method |
VARCHAR(10) | manual or excel |
| Column | Type | Notes |
|---|---|---|
scan_id |
UUID PK | |
input_id |
FK | β vendor_inputs |
scan_type |
VARCHAR | quick or deep |
status |
VARCHAR | PENDING Β· COMPLETED Β· ERROR |
overall_risk_level |
VARCHAR | LOW Β· MEDIUM Β· HIGH Β· CRITICAL |
risk_score |
INTEGER | 0β100 |
raw_data_summary |
JSON | full aggregated report |
| Column | Type | Notes |
|---|---|---|
finding_id |
UUID PK | |
scan_id |
FK | β kyb_scans |
category |
VARCHAR | sanctions_match Β· news_adverse Β· regulatory_issue β¦ |
severity |
VARCHAR | critical Β· high Β· medium Β· low |
confidence_score |
INTEGER | 0β100 |
source_tool |
VARCHAR | originating API |
recommended_action |
VARCHAR |
| Column | Type | Notes |
|---|---|---|
subject_id |
UUID PK | |
scan_id |
FK | β kyb_scans |
subject_type |
VARCHAR | entity Β· director Β· founder |
is_pep |
BOOLEAN | Politically Exposed Person flag |
| Tab | Visible | Contents |
|---|---|---|
| Overview | Always | Overall risk level, finding count, per-source relevance/criticality heatmap |
| Findings | Always | Structured adverse findings sorted by severity with source citations |
| News & Media | Always | All articles from GDELT Β· NewsAPI Β· Serper with Gemini relevance scores |
| Web & Reviews | Always | Domain intel (WHOIS, SSL, Microlink), Google Places, review excerpts, Wikipedia |
| AuthBridge Checks | India only | Email verification Β· Global Sanctions Β· Court records Β· Defaulting Director Β· GSTIN/PAN/MSME |
| Method | Path | Description |
|---|---|---|
POST |
/intake |
Submit a single vendor (JSON body) |
POST |
/intake/excel |
Upload a batch .xlsx file |
POST |
/scan |
Trigger scan for an existing input_id |
GET |
/scan/{id}/status |
Poll scan status |
GET |
/scan/{id}/report |
Retrieve full risk report |
| Mode | Sources | Phase 2 Enrichment | Duration |
|---|---|---|---|
| Quick | Sanctions Β· GDELT Β· Serper adverse | No | ~15 s |
| Deep | All 12+ sources + India checks | Yes (if GSTIN present) | 30β60 s |
Run tests
# Windows
cd backend && .\venv\Scripts\activate && pytest tests/
# macOS
cd backend && source venv/bin/activate && pytest tests/Smoke-test backend imports
python -c "from app.main import app; print('OK')"Type-check frontend
cd frontend && npx tsc --noEmitProduction frontend build
cd frontend && npm run buildbackend/Dockerfile and docker-compose.yml are included but require WSL2 and admin access β not available on standard office laptops. Use the native setup above for local development. The Docker configuration is ready for IT-managed server or cloud deployment.
# Future: deploy with Docker Compose
cp backend/.env.example backend/.env # fill in keys
docker compose up --build
# Backend: http://localhost:8000
# MySQL: port 3306 (internal)Use inputs/VendorLens_Intake_Template.xlsx for batch uploads. Column mapping is flexible β headers are matched by keyword, not exact name.
| Column | Recognized Aliases |
|---|---|
legal_name |
name, supplier, vendor name |
website_domain |
domain, website |
jurisdiction_country |
country |
tax_identifier |
tax no, gstin |
pan_number |
pan, pan no |
director_names |
directors, board |
founder_ceo_name |
ceo, founder |
corporate_email_domain |
email domain |