Skip to content

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:

  1. Request Execution: Frontend routes (e.g. /api/verify/[desk]) make HTTP requests.
  2. Resilience Wrapper: A shared fetchWithRetry helper targets the API Gateway with a 1.5s timeout and up to 2 retries.
  3. Graceful Fallback: On ECONNREFUSED or HTTP 503, the interceptor returns high-fidelity mock data.
  4. 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 microservices
  • POST /api/ssi* → proxied to Identity Service
  • POST /api/verify* → proxied to Verify Service
  • POST /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