Safety and records
How Neo protects people and private data
How Neo checks identity, ownership, private information, and access to protected pages.
Phone-bound authentication
flowchart TB WhatsApp[Verified phone identity] --> Challenge[One-time challenge] Challenge --> Buyer[Order-scoped buyer session] Challenge --> Seller[Merchant-bound seller session] Challenge --> Creator[Creator-bound session] Challenge --> Admin[Role-revalidated admin session] Buyer --> Ownership[Resource ownership checks] Seller --> Ownership Creator --> Ownership Admin --> Role[Role and step-up checks] Ownership --> CSRF[CSRF on state-changing forms] Role --> CSRF
If the diagram does not render, its Mermaid source remains readable above.
Challenges are hashed, expiring, and one-time. Session cookies are signed and HTTP-only; production cookies are secure. Verification revalidates the expected phone, user, role, merchant, creator, or order binding.
Defence in depth
- Shared request-body and stricter upload limits.
- Database-backed rate limits for authentication and callbacks.
- Hosted payment pages; no raw card storage.
- Private object storage and protected readback.
- Encryption or masking for sensitive provider recipient references.
- Redaction for identity-number text, beta invite secrets, logs, audits, and evidence.
- PostgreSQL constraints, advisory locks, and immutable financial triggers.
- Production environment validation rejects mocks and unsafe delivery combinations.
Privacy boundary
Ordinary WhatsApp chat must not request or store BVN/NIN. Neo does not collect BVN. Seller NIN enters only through the signed, expiring seller-identity Flow; it is encrypted while the Dojah request is queued, matched on legal name and the NIN-registered phone, then purged with the submitted legal name after every terminal attempt. Live identity verification remains unavailable until the exact Dojah account and deployment target are certified.
Privacy intake creates one open audited request per canonical phone and supports controlled review transitions. A default-on terminal-state guard records redacted category outcomes and returns fulfilment_blocked instead of completed while any postcondition is missing. Automated field-level deletion/anonymization, legal holds, and provider fulfilment are not complete. Public documentation therefore describes request intake and guarded review, not completed erasure.
src/nin-verification.tssrc/whatsapp-flow-contracts.tsassets/whatsapp-flows/seller-verification.jsonsrc/privacy.tsdb/migrations/069_privacy_fulfilment_guard.sqltest/nin-verification.test.tstest/phase2-postgres-runtime.test.ts
Evidence and tests
src/buyer-auth.tssrc/seller-auth.tssrc/creator-auth.tssrc/admin-auth.tssrc/rate-limit.tssrc/uploads.tssrc/privacy.tssrc/env.tstest/security.test.ts
