Resources
Identity verification
How Pierflow verifies member identity at enrollment time, what we store, and how the disposition rules drive policy issuance.
Identity verification runs inline inside POST /v1/enrollments. You don't call it directly — you submit the member's NIN or BVN as part of the enrollment body and Pierflow returns the verification disposition alongside the enrollment record. This page documents how that step works, what we store, and how the disposition rules drive what happens next.
What we store#
We hold the absolute minimum needed to verify and reconcile, and we treat the rest as sensitive PII subject to NDPC.
| Field | How it's stored |
|---|---|
| nin / bvn (plaintext) | Never persisted. Used in-memory during the verification call, then discarded. |
| nin_hash / bvn_hash | SHA-256(IDENTITY_HASH_SECRET || identifier). Stable across calls for dedup; not trivially reversible. |
| nin_last4 / bvn_last4 | Last 4 digits for display in the portal. |
| encrypted_payload | AES-256-GCM ciphertext of the original identifiers + supplied profile. Keyed by IDENTITY_ENCRYPTION_KEY (env). Decrypted only by the identity service when re-verifying. |
| full_name, date_of_birth, sex | Plain columns — needed to display the member in the portal and to compare against future re-verifications. |
Verification providers#
The implementation is provider-pluggable. The active provider is selected by the IDENTITY_PROVIDER env var.
| Provider | When to use | Behaviour |
|---|---|---|
| stub (default) | Sandbox, dev, early production while NIMC credentials are being procured. | Returns AUTO_APPROVED at confidence 95 for any name. Magic names TEST_FAIL and TEST_SOFT force REJECTED / SOFT_REVIEW respectively — useful for exercising downstream branches. |
| partner_declared | When the fintech has already KYC'd the user upstream and you want a trust-but-audit record. | Returns AUTO_APPROVED at confidence 90. We record the verification row so a future dispute can be audited, but we don't re-call NIMC. |
| nimc | Production. Calls the real NIMC API. | Not yet wired in this version. Production deployments must implement runNimc() in lib/insurance/identity.ts before going live; the stub throws if selected without an implementation. |
Disposition rules#
Every verification returns a confidence score 0–100. Three dispositions follow from it:
| Confidence | Disposition | Enrollment outcome |
|---|---|---|
| > 85 | AUTO_APPROVED | Enrollment proceeds normally. Policy issues on payment. |
| 60 – 85 | SOFT_REVIEW | Enrollment proceeds. The IdentityVerification row is flagged for ops review. Useful for ops investigation but doesn't block the user. |
| < 60 | REJECTED | Enrollment is refused. No enrollment row created. The hmo_enrollment.identity_rejected webhook fires so you can prompt the user to fix their data. |
In the enrollment response#
The identity outcome is surfaced on every enrollment response:
{
"enrollment": { /* ... */ },
"identity": {
"status": "AUTO_APPROVED", // AUTO_APPROVED | SOFT_REVIEW | REJECTED
"confidence": 95, // 0..100
"provider": "STUB" // STUB | PARTNER_DECLARED | NIMC
},
"idempotent_replay": false
}SOFT_REVIEW enrollments succeed but you should surface a note in your admin tooling — Pierflow staff will reach out if the verification ends up needing manual correction.
Dedup & cross-tenant rules#
The SHA-256 hash is stable for a given identifier across all your verifications, which means you can answer "have I verified this person before?" without ever storing the plaintext. The same hash across two different fintech partners is the same person, but Pierflow does not cross-link partners — each fintech sees only its own verification history.
Dedup lookup
Not currently exposed as a public endpoint. Use your audit logs or contact Pierflow support to confirm whether a NIN already has a verification on file for your partner.
Encryption at rest#
AES-256-GCM with a 32-byte key. Wire format: [12B nonce][16B authTag][ciphertext]. The key lives in IDENTITY_ENCRYPTION_KEY as 64 hex chars (32 raw bytes). Generate with openssl rand -hex 32; never commit to source control.
Auditability#
Every verification — including rejections — writes an IdentityVerification row with the disposition, provider, confidence, field-level checks, and the raw provider response. Combined with the immutable HmoEnrollmentEvent log, this gives Pierflow and the fintech a complete trail for any dispute.