Platform Architecture & Microservices¶
The BPEVeriFlow system follows a decoupled, resilient architecture designed to maintain applicant portal throughput even during downstream database or container outages.
System Architecture Diagram¶
graph TD
Browser([":busts_in_silhouette: Browser / Applicant"]) --> Next["Next.js 16 App<br/>localhost:3000"]
subgraph "Client State (React Context)"
RBAC["RBACContext<br/>(Auth · Roles · Permissions)"]
VC["VerificationContext<br/>(Desk State · Scores · SLA)"]
Wallet["WalletContext<br/>(SSI Credentials · DID)"]
I18n["I18nContext<br/>(EN · HA · YO · IG)"]
Toast["ToastContext<br/>(Notifications)"]
end
Next --> RBAC
Next --> VC
Next --> Wallet
subgraph "Next.js Resilience Boundary"
Next --> |"API Calls"| Routes["API Routes<br/>/api/verify/:desk<br/>/api/ssi<br/>/api/exception"]
Routes --> |"fetchWithRetry"| GW["Express API Gateway<br/>Port 4000"]
Routes -. "ECONNREFUSED / timeout" .-> Mock["Mock Responders<br/>(Local JS fallback)"]
end
subgraph "Backend Container Mesh"
GW --> |"Port 4001"| Identity["Identity Service<br/>(NIMC · CAC · SSI)"]
GW --> |"Port 4002"| Verify["Verify AI Engine<br/>(OCR · AML · ZKP Biometrics)"]
GW --> |"Port 4003"| Exception["Exception Service<br/>(Human Review · Escalations)"]
Identity --> DB[("NeonDB PostgreSQL<br/>(HA Cluster)")]
Verify --> DB
Exception --> DB
end
1. Next.js Resilience Boundary¶
Offline-First Design
The resilience boundary ensures the UI remains fully functional even when backend services are unavailable. Fallback actions are flagged with isMockFallback: true in audit metadata so they can be re-synced when connectivity is restored.
The communication pattern works in four steps:
- Request Execution: Frontend routes (e.g.
/api/verify/[desk]) make HTTP requests. - Resilience Wrapper: A shared
fetchWithRetryhelper targets the API Gateway with a 1.5s timeout and up to 2 retries. - Graceful Fallback: On
ECONNREFUSEDor HTTP 503, the interceptor returns high-fidelity mock data. - UI Continuity: React continues to render timelines, process uploads, run biometric checks, and advance desks — no red screen errors.
2. Express Microservices¶
Each service in the microservices/ folder is TypeScript, compiled to Node.js, and packaged in a lightweight Docker container.
A. API Gateway (Port 4000)¶
| Property | Value |
|---|---|
| Role | Central routing proxy and rate limiter |
| Rate Limit | 500 requests / 15 minutes per IP |
| Security | Helmet.js headers, CORS domain allowlist |
| Config Validation | Zod schema on boot for all downstream URLs |
Endpoints:
GET /health— Aggregated ping check of all downstream microservicesPOST /api/ssi*→ proxied to Identity ServicePOST /api/verify*→ proxied to Verify ServicePOST /api/exception*→ proxied to Exception Service
B. Identity Service (Port 4001)¶
- Role: Identity records and decentralised wallet integration.
- Components: NIMC national registry lookup, CAC company registration checks, SSI Verifiable Credential verification, and DIDComm handshake handling.
C. Verify Service (Port 4002)¶
- Role: AI evaluation scores and compliance rule engine.
- Components: Fraud pattern detection, AML/NFIU threshold checks, bank statement analysis, liveness calculation simulators, and ZKP biometric vector comparison.
D. Exception Service (Port 4003)¶
- Role: Escalation queue manager.
- Components: Human review request routing, audit log state overwrites, support ticket lifecycle management.
3. Frontend State Management (VerificationContext)¶
The client tracks runtime state via a unified context provider: VerificationContext.tsx.
State Shape Reference¶
| Field | Type | Description |
|---|---|---|
applicationId |
string \| null |
Unique BPE application ID (e.g. BPE-X7K2M) |
applicantName |
string \| null |
Full name from SSI wallet or form |
appStatus |
AppStatus |
idle · active · exception · completed |
currentDesk |
number |
Active desk number (1–5) |
desks |
DeskResult[] |
Array of per-desk scores, flags, and officer assignments |
slaDeadline |
string \| null |
ISO 8601 SLA expiry timestamp (5 days from intake) |
overallAiScore |
number \| null |
Rolling average AI confidence score across completed desks |
exceptionRequested |
boolean |
Whether a human review has been requested |
exceptionReason |
string \| null |
Reason text for the escalation |
biometricFallbackUsed |
boolean |
True if camera hardware failed at Desk 5 |
isLoading |
boolean |
True during async desk API calls |
error |
string \| null |
Last API error message |
paymentStatus |
"pending" \| "processing" \| "disbursed" |
CBN RTGS payment lifecycle state |
auditTrail |
AuditEntry[] |
All logged events, SHA-256 chained |
Action Reducers¶
| Action | Trigger | Effect |
|---|---|---|
INIT_APPLICATION |
Desk 1 form submit | Allocates unique ID, sets SLA deadline (5 days), activates Desk 1 |
UPDATE_DESK |
Desk API response | Updates a specific desk's score, flags, and AI summary |
ADVANCE_DESK |
Officer approve | Marks desk complete, increments currentDesk, recalculates average AI score |
ASSIGN_AGENT |
Executive dropdown change | Updates officerId and officerName for a specific desk in real-time |
REQUEST_EXCEPTION |
Applicant or AI trigger | Sets exceptionRequested: true and stores reason text |
RESOLVE_EXCEPTION |
Officer marks resolved | Clears exception flag, resumes desk workflow |
SET_PAYMENT_STATUS |
Payment flow | Transitions pending → processing → disbursed |
ADD_AUDIT_LOG |
Any state change | Appends a new chained audit entry with SHA-256 mock hash |
RESET |
Workflow restart | Returns all state to initial values |