Wive is a full-stack web application that audits payroll data, flags anomalies, and verifies workforce authenticity to eliminate ghost-worker fraud in public and private sector organisations.
Ghost workers — fictitious or deceased employees kept on a payroll to divert salaries — cost governments and organisations billions annually. Manual audits are slow, error-prone, and easily circumvented. Wive automates the detection process end-to-end, combining a deterministic rules engine with unsupervised machine learning to surface suspicious employees for human review, and then facilitates direct payment to verified workers.
| Feature | Description |
|---|---|
| CSV Upload | Upload payroll and biometric attendance files for a named payroll cycle |
| ML Analysis | Hybrid pipeline (rules engine + Isolation Forest) scores every employee 0–100 |
| Risk Classification | HIGH / MEDIUM / CLEARED labels with per-employee flag explanations |
| AI Explanations | OpenRouter LLM produces a plain-English summary for each flagged employee |
| Payment Disbursement | Finance Controller pays cleared employees directly via the Squad Co API |
| Audit Trail | Every action (upload, analysis, hold, release, pay) is logged with actor and timestamp |
| Role-Based Access | Three distinct dashboards for Finance Controller, HR Personnel, and ICPC |
| External API | Programmatic access for third-party integrations via API-key authentication |
| Cross-Cycle Comparison | Detects salary changes, account swaps, and BVN re-use across payroll cycles |
- Python 3.11 · FastAPI · Uvicorn
- SQLAlchemy 2 · Alembic (migrations) · SQLite (dev) / PostgreSQL (prod)
- scikit-learn — Isolation Forest (payroll + biometric anomaly detection)
- pandas / numpy — data transformation and feature engineering
- PyJWT / bcrypt — authentication
- Squad Co API — bank transfers
- Next.js 16 (App Router) · React 19
- TypeScript · Tailwind CSS v4
- TanStack Query v5 — server-state management
- Axios · Lucide React
Wive/
├── backend/
│ ├── app/
│ │ ├── api/
│ │ │ └── routes/
│ │ │ ├── auth.py # Register/login (HR, Finance, ICPC)
│ │ │ ├── cycles.py # Upload, analyse, pay-cleared
│ │ │ ├── employees.py # Per-employee review and hold/release
│ │ │ ├── dashboard.py # Aggregated KPIs
│ │ │ ├── audit.py # Audit log queries
│ │ │ ├── payments.py # Payment records
│ │ │ └── external.py # Public API (API-key auth)
│ │ └── core/
│ │ ├── security.py # JWT + API-key middleware
│ │ └── dependencies.py # Shared deps (semaphore, audit logger)
│ ├── ml/
│ │ ├── pipeline.py # Orchestrates all ML stages
│ │ ├── rules_engine.py # 15+ deterministic fraud rules
│ │ ├── isolation_forest.py # Payroll anomaly scoring
│ │ └── biometric_isolation_forest.py # Attendance anomaly scoring
│ ├── db/
│ │ ├── models.py # SQLAlchemy ORM models
│ │ └── config.py # DB session factory
│ ├── services/
│ │ ├── ai.py # OpenRouter LLM explanations
│ │ ├── squad.py # Squad Co payment integration
│ │ └── payments.py # Payment upsert helper
│ ├── alembic/ # Database migrations
│ ├── main.py # Entry point
│ └── requirements.txt
└── frontend/
├── app/
│ ├── (auth)/login|register/ # Login pages per role
│ └── (dashboard)/
│ ├── finance-controller/ # Finance Controller dashboard
│ ├── hr/ # HR Personnel dashboard
│ ├── icpc/ # ICPC dashboard
│ ├── cycles/ # Payroll cycle management
│ ├── audit/ # Audit log viewer
│ ├── upload/ # File upload flow
│ └── review/[id]/ # Individual employee review
├── components/dashboard/ # Shared UI components
└── lib/ # API client, session, route helpers
Each employee receives a composite risk score (0–100) from three layers:
| Layer | Weight | Method |
|---|---|---|
| Rules Engine | 35% | 15+ deterministic rules (duplicate BVN/NIN/account, salary vs. grade mismatch, retired/deceased on payroll, cross-cycle account swap, etc.) |
| Payroll Isolation Forest | 20% | Unsupervised outlier detection on financial features |
| Biometric Isolation Forest | 45% | Unsupervised outlier detection on attendance patterns (hours, check-in variance, zero-hour days) |
Risk thresholds: HIGH ≥ 70 · MEDIUM ≥ 40 · CLEARED < 40
After scoring, an LLM (via OpenRouter) writes a one-sentence plain-English explanation for every HIGH/MEDIUM employee.
| Role | Capabilities |
|---|---|
| Finance Controller | Upload payroll cycles, trigger analysis, approve/reject flagged employees, disburse salaries to cleared employees |
| HR Personnel | Review employees within their ministry, flag or clear individuals |
| ICPC Personnel | Read-only access to all cycles and audit logs for independent oversight |
- Python 3.11+
- Node.js 18+ / npm
cd backend
# 1. Create and activate a virtual environment
python -m venv venv
venv\Scripts\activate # Windows
# source venv/bin/activate # macOS / Linux
# 2. Install dependencies
pip install -r requirements.txt
# 3. Configure environment variables
cp .env.example .env
# Edit .env — see Environment Variables below
# 4. Start the server
python main.py
# API available at http://localhost:8000
# Interactive docs at http://localhost:8000/docscd frontend
# 1. Install dependencies
npm install
# 2. Configure environment variables
# Create frontend/.env.local and set NEXT_PUBLIC_API_URL=http://localhost:8000
# 3. Start the dev server
npm run dev
# App available at http://localhost:3000| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
No | SQLAlchemy connection string (defaults to SQLite ghostsight.db) |
SECRET_KEY |
Yes | JWT signing secret |
OPENROUTER_API_KEY |
No | Enables AI explanations for flagged employees |
SQUAD_SECRET_KEY |
No | Squad Co API key for payment disbursement |
SQUAD_BASE_URL |
No | Squad Co base URL (sandbox or production) |
SQUAD_VIRTUAL_ACCOUNT |
No | Source account number for transfers |
| Variable | Required | Description |
|---|---|---|
NEXT_PUBLIC_API_URL |
Yes | Backend base URL |
The full interactive API reference is available at http://localhost:8000/docs when the backend is running.
POST /api/auth/finance/login # Finance Controller login
POST /api/auth/hr/login # HR Personnel login
POST /api/auth/icpc/login # ICPC login
All protected endpoints require a Bearer token in the Authorization header.
POST /api/cycles/upload # Upload payroll + biometric CSVs
POST /api/cycles/{id}/analyze # Trigger ML analysis (background job)
GET /api/cycles/{id}/status # Poll analysis progress
GET /api/cycles/{id}/results # Fetch scored employee results
POST /api/cycles/{id}/pay-cleared # Disburse salaries to cleared employees
POST /api/external/analyze # Submit CSVs and receive results via webhook callback
Pass your API key in the X-API-Key header.
Payroll CSV — required columns:
staff_id, first_name, last_name, ministry, grade_level, monthly_salary, bank_name, account_number, bvn, nin, address, next_of_kin_phone, retirement_date, death_date
Biometric CSV — required columns:
staff_id, attendance_date, check_in, check_out, total_hours