Skip to content

cLLeB/verification-system

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

67 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

title Biometric Verify
emoji 🟣
colorFrom indigo
colorTo purple
sdk docker
app_port 7860
pinned false
short_description Contactless face verification + identification API

Inclusive, contactless identity — on any phone

Confirm who someone is using just a phone or tablet camera — by their face or the palm of their hand. No fingerprint scanner, no cards, no internet required.

Think of it as a universal "prove it's really you" button that any app or organisation can plug in: point a camera at a person, and it either confirms they're who they claim to be, or tells you who they are — in a second or two, on the cheap phones people already have, and it keeps working when the internet is down.

The problem it solves

Most identity systems today rely on fingerprint scanners, which have two big problems:

  1. They exclude people. Farmers, cleaners, builders, traders and the elderly often have worn or damaged fingerprints that scanners can't read — so they get turned away from their own benefits, SIM cards, wages or exams. This is a real, documented failure of large fingerprint-based ID programmes.
  2. They cost money and break. Every scanner is hardware to buy, install, clean and maintain.

This fixes both:

  • Nobody gets excluded — if your palm doesn't read, your face does (and vice-versa). A match is a match.
  • No special hardware — it's the camera already in every phone.
  • Contactless & hygienic — nothing to touch.
  • Works fully offline — for rural clinics, remote sites and field work with no signal (there's an air-gapped Android build too).
  • Private by design — it never stores photos, only a scrambled mathematical signature that can't be turned back into a face, and it can be wiped on request.

Who needs it, and why

Anyone who must answer "is this the right person?" at scale, cheaply, without leaving people out:

Who Why
Employers (factories, farms, schools) Stop "buddy-punching" on attendance where fingerprint clocks fail on manual workers
Governments & NGOs (cash transfers, welfare) Eliminate ghost/duplicate beneficiaries and pay people out without excluding worn-fingerprint citizens
Exam boards & universities Stop candidates sitting exams for one another
Clinics & hospitals Find a patient's record instantly when the card is lost; avoid duplicate records
Banks, microfinance, mobile-money agents Verify members and stop multi-branch fraud, even in villages with no connectivity
Software teams Add trustworthy identity to their product with a couple of API calls — no biometric work of their own

See examples/ for four small, working products built on it (attendance, exams, welfare, clinics) — proof it weaves into anything.

"Isn't this already solved?"

Parts exist — but no one combines them for these people and places, and the most common existing tool (fingerprints) is the problem we solve:

Existing approach Gap it leaves
Fingerprint / national-ID scanners Exclude worn fingerprints; need hardware everywhere
Cloud face APIs (AWS, Azure, Face++, NEC) Need constant internet; costly; no palm fallback; data in someone's cloud
Palm-payment (Amazon One) Needs special infra-red scanners — not a phone
Digital KYC / onboarding (Smile ID, Onfido, Jumio) One-time, online account-opening — not repeated, offline, field verification

We're the only option that is camera-only, face-or-palm, offline, and private — built for the settings the others don't reach. The face-matching tech itself is mature and proven; the edge is the packaging and fit — inclusive, hardware-free, offline, embeddable, and tuned/tested on the target population.


For developers & operators

A contactless face + palm verification + identification service: a phone web client, an operator admin console, and a multi-tenant REST API other apps integrate with. ArcFace face embeddings + active (head-turn) liveness, plus contactless palm-print (MediaPipe-Hands ROI → CCNet ONNX) — both behind one auto-routing API, so a user is recognised whether they show their face or their palm (a match is a match). Encrypted at rest, with adaptive enrolment that keeps recognising a person as they change over months/years.

The earlier contactless-fingerprint system is archived under fingerprint/; phone-camera capture proved unworkable, so the project pivoted to face.

Three surfaces

Surface Path Who Auth
Phone web client / end users (kiosk) verify open; enrol needs admin login
Admin console /admin your operators admin password
Integration API /v1/* other companies' systems X-API-Key + role

📚 Documentation

Full docs in docs/: Architecture · Security & Privacy · Integration · API errors/codes · Operations · Deploy · Development · Android · Roadmap · Changelog. Package maps: face/ (recognition core), face_service/ (web API).

Quickstart (local)

python -m venv venv && venv/Scripts/pip install -r requirements.txt
# PowerShell:  $env:FACE_ADMIN_PASSWORD="choose-one"
python app.py                             # dev server, HTTPS (self-signed) on :5000

Open https://<this-machine-ip>:5000 on a phone (same network), accept the self-signed cert, allow the camera. For public 24/7 access see docs/DEPLOY.md.

Integration API (/v1)

Auth: header X-API-Key: <key>. Mint keys: python manage_keys.py create "App" --role verify.

Endpoint Scope Purpose
POST /v1/enroll enroll enrol one user from image(s)
POST /v1/enroll/bulk enroll enrol many users in one call
POST /v1/verify verify 1:1 (with user_id) or 1:N
POST /v1/identify verify 1:N — who is this?
POST /v1/embed verify stateless: image → 512-d embedding
POST /v1/compare verify stateless: probe vs references
GET /v1/users · POST /v1/users/delete manage · delete list / delete (single or user_ids[])
POST /v1/users/export manage data-subject access (metadata)
POST /v1/users/purge delete erase all users in a tenant (confirm:true)
GET /v1/usage any this tenant's usage this month
GET /v1/challenge · GET /v1/health verify · none liveness token · readiness

Roles: admin = full control; verify = recognition only (cannot enrol/delete/list). Each tenant is isolated; verify/compare results are HMAC-signed with the key's secret. See docs/INTEGRATION.md, openapi.yaml, and the SDKs in sdk/.

from faceverify import FaceVerifyClient
fv = FaceVerifyClient("https://HOST:5000", "fk_yourkey")
fv.enroll("alice", ["a1.jpg", "a2.jpg", "a3.jpg"])
if fv.verify("alice", "probe.jpg")["success"]:
    grant_access()

Bulk import a dataset

python bulk_enroll.py dataset/ --tenant acme     # dataset/<person>/<images...>

Operations

  • Probes: GET /healthz (liveness), GET /readyz (readiness), GET /metrics (Prometheus).
  • Audit trail per tenant in audit_logs/; usage counters in usage.json.
  • Rate limited per caller (FACE_RATE_LIMIT/FACE_RATE_WINDOW); security headers on every response.

Configuration (environment)

Var Default Purpose
FACE_ADMIN_PASSWORD random (printed) admin console / enrolment password
FACE_SECRET_KEY random per run signs admin session cookies (set in prod)
FACE_DB_KEY random key file passphrase for encryption-at-rest
FACE_SIGNING_SECRET HMAC-sign first-party verify results
FACE_CORS_ORIGINS same-origin comma-separated browser origins allowed on /v1
FACE_RATE_LIMIT / FACE_RATE_WINDOW 120 / 60 requests per window per caller
FACE_ACTIVE_LIVENESS 1 require a live head-turn on verify
FACE_LIVENESS 0 also run the passive single-shot anti-spoof model (opt-in; pairs with active liveness; self-host only — models ship there)
FACE_LIVENESS_THRESHOLD 0.55 passive-liveness strictness (only used when FACE_LIVENESS=1)
FACE_ATTRIBUTES 0 estimate age/gender (returned on /v1/embed) — loads the small genderage model
FACE_USE_ANN 0 use the HNSW ANN index instead of exact (needs hnswlib; for very large tenants)
FACE_DB_PATH face_db base data directory (store + per-tenant + index)
FACE_KEYS_FILE · FACE_ADMINS_FILE · FACE_AUDIT_DIR · FACE_USAGE_FILE apikeys.json · admins.json · audit_logs · usage.json state locations

Operators: python manage_admins.py create alice. While no operators exist, the FACE_ADMIN_PASSWORD bootstrap login (admin / that password) is active; adding the first operator disables it.

Privacy & compliance

Biometric templates and the search index are encrypted at rest; raw images are never stored (only embeddings, encrypted). The audit log records actions, not faces. Right-to-erasure: POST /v1/users/delete / …/purge. Data-subject access: POST /v1/users/export. Obtain consent before enrolling people.

Layout

face/            ArcFace engine: detection, matching, liveness, adaptive, encrypted store + index
face_service/    /v1 API, API keys + roles, admin auth, audit, usage, metrics, security
app.py           Flask app: phone client + admin console + mounts /v1
bulk_enroll.py   offline dataset importer        serve.py  production launcher (waitress)
templates/, static/   phone client + admin console UIs
sdk/, openapi.yaml, docs/, Dockerfile
tests/           pytest suite + scale/drift benchmarks
fingerprint/     archived fingerprint system

Offline / air-gapped

The service runs fully offline — no internet needed at runtime. There are no CDN assets, no telemetry, and no outbound calls; the ArcFace models are loaded from a local cache (pre-baked into the Docker image). For a self-contained kiosk, run the server and open https://localhost:5000 in a browser on the same device — it works with zero network. The phone client is a PWA whose shell caches for instant loads and shows an offline page if the server is unreachable (verification itself always needs the server, since the model runs server-side).

Scale

Tuned for ~100k identities per tenant (exact match, 100% accurate, ~40 ms search, encrypted). For 1M+ swap the index to FAISS — see face/index.py (_USE_ANN).

Tests

python -m pytest tests/ -q
python _scale_test.py 100000      # scale/accuracy benchmark

Tech

InsightFace (buffalo_l ArcFace, ONNX Runtime, CPU) · active-liveness head-turn · Flask · Fernet/AES encryption · waitress/gunicorn. No GPU required.