Skip to content
security posture · controls in the live product

The money path, documented

Written like a docs page, not a marketing one. If a control isn’t live, it isn’t here.

Authentication

Firebase Auth with email + password. SMS OTP login is on the roadmap. Lender admin sessions expire on inactivity. Every Netlify Function call validates the Firebase ID token server-side before touching Firestore.

Authoritative server math

Money math runs on Netlify Functions, not the browser. A borrower cannot underpay by mutating client-side totalPayable. Repayment amounts are recomputed against the Firestore-locked loan document at credit time.

Hosted in West Africa

Application code on Netlify edge. Database on Firestore. Money-rail calls hit Flutterwave on infrastructure inside West Africa, keeping settlement latency low and aligned with NDPR data-locality expectations.

Data handling

Where PII actually lives

  • BVN, NIN, face video, ID upload land in Firebase Cloud Storage under admin-only Storage Rules.
  • Lenders only read KYC documents of borrowers with active disbursed loans on their workspace. The Storage Rule revokes access once the loan settles — no permanent retention.
  • Loan, wallet, ledger, OTP, and audit-log documents live in Firestore. Firestore Security Rules scope every read and write to the authenticated uid and the lender they belong to.
  • NDPR-aligned: data minimisation on collection, lawful-basis on each PII field, deletion on request via support@ytfinancehq.com.
Money-path safety

Why a network blip never debits your wallet twice

  • Idempotent ledger. Every wallet operation is anchored on a deterministic doc ID computed from inputs. A retry writes to the same doc, so the second attempt is a no-op.
  • OTP single-purpose. One code authorises one action — disburse OR undo OR mark-paid. The OTP is burned on use, even if Flutterwave returns an error. Want to retry? You request a fresh OTP.
  • Flutterwave status cross-verify. Before re-debiting on a retry, we query Flutterwave for the transfer’s actual status. If it’s already SUCCESSFUL, we don’t debit again — we just reconcile.
  • Auto-refund on failure. transfer.failed and transfer.reversed webhooks trigger a refund to the lender wallet under the same deterministic ID anchor.
  • Heartbeat sentinel. A scheduled Netlify Function runs every 5 minutes, scans for failedOperations, auto-replays them, and surfaces any silent failure on the admin Incidents page.
  • Three-loan cap, transactionally enforced. The borrower can’t hold more than three concurrent disbursed loans — checked inside a Firestore runTransaction lock so two parallel applications can’t both win.
  • Race-condition-free repayment crediting. The read-after-write race that lets a fast-double-tap double-count a payment is fixed by reading the loan document inside the same transaction that writes the credit.
Webhooks & endpoints

Server boundary

  • Flutterwave webhooks validated with the verif-hash signature header against our server-side secret. Unsigned or mismatched payloads are dropped before any ledger touch.
  • CSP enforced on every page (default-src self, scoped script-src, frame-src locked to Flutterwave checkout and Firebase auth).
  • CORS strict origin allowlist per Netlify endpoint. No wildcard origins on money-path endpoints.
  • Every money endpoint rate-limited per uid and per IP at the Netlify Function entry.
  • Lender KYC required before disbursement is unlocked. Aligned with CBN onboarding expectations for lenders moving money on a hosted rail.
Compliance posture

What we align to

NDPR (Nigeria Data Protection Regulation)

PII collection mapped to lawful basis. Borrower BVN handled via Dojah’s NDPR-licensed pipeline. Storage rules revoke lender access on loan settlement.

CBN-aligned lender KYC

Lender KYC required before disbursement unlocks. OTP-gated settlement to the lender’s named NGN bank account — not arbitrary third parties.

PCI DSS scope reduction

YT Finance never stores card data. Card collection happens inside Flutterwave hosted checkout, which is PCI DSS Level 1.

Audit log

Every disbursement, refund, OTP issuance, KYC approval, and admin override is recorded in an append-only audit log scoped per lender, exportable on request.

Responsible disclosure

Found a vulnerability? Tell me

Email security@ytfinancehq.com with a description, reproduction steps, and any supporting material. If the issue touches the money path (disbursement, refund, ledger, OTP, webhook signature), flag it in the subject line and I will read it the same day.

I commit to acknowledging within 2 business days, providing a status update within 7 days, and crediting the researcher (with permission) once the fix is shipped. Please don’t access more data than necessary to demonstrate the issue, and please don’t share details publicly until I’ve had a reasonable chance to remediate.

See security.txt

Questions about a specific control?

Happy to share the Firestore Rules, Storage Rules, and Netlify Function source for any money endpoint under NDA. Email Stephen directly.