The first question every compliance officer asks: “What biometric data do you store?” The answer is designed to make their job easy: we never store photos. We never store images. We never store raw biometric data.
Here’s exactly what happens to your user’s face data from the moment it enters our API to the moment it leaves.
We never store photos. We never store images. We never store raw biometric data. The image buffer is zeroed within 300 milliseconds of capture.
The data flow
The critical step is the fourth one: the image buffer is zeroed. Not deleted — zeroed. The memory is overwritten with null bytes before being released. The raw face image exists in server memory for approximately 200-300 milliseconds — the time needed to extract the embedding — and then it’s gone.
What is an embedding?
An embedding is a high-dimensional numerical vector — a list of floating-point numbers that represent the mathematical “fingerprint” of a face. Think of it as coordinates in a high-dimensional space. Two embeddings from the same person will be close together in this space. Two embeddings from different people will be far apart.
The critical property: an embedding cannot be reverse-engineered to reconstruct a face image. The transformation from image to embedding is a one-way function. You can go from face → embedding, but you cannot go from embedding → face. There is no algorithm that takes the stored vector and produces the original photograph. This is mathematically guaranteed by the architecture of the neural network that produces the embeddings.
This means even if an attacker compromised the database, they would have a list of opaque float vectors — useless for reconstructing faces, useless for identity theft, useless for impersonation.
How embeddings are encrypted
The high-dimensional embedding vector is encrypted before storage using authenticated encryption (AES-based, with rotation support). This means:
- The cipher encrypts the embedding so it’s unreadable without the key
- An authentication tag signs the ciphertext so any tampering is detected on read
- Each encryption operation includes a timestamp, enabling automatic expiration
- The encryption key is stored as an environment variable on Railway, never in code
When a verification request comes in, the stored embedding is decrypted in memory, compared to the new embedding using cosine similarity, and both embeddings are zeroed from memory after the comparison. The decrypted embedding exists in memory for approximately 5 milliseconds.
What we log
Every verification produces a log entry. Here’s exactly what’s recorded — and what isn’t:
Logged (for audit purposes)
verification_id— unique identifier for this verificationuser_id— the user identifier provided by your platformaction_verified— what action was authorized (“withdraw_50000_usdc”)match— true or falseconfidence— match confidence score (0.0 to 1.0)liveness_score— liveness confidence (0.0 to 1.0)liveness_method— which mode was usedcapture_hash— SHA-256 hash prefix of the image (for replay detection, not reconstruction)verified_at— ISO timestamplatency_ms— pipeline execution timerejection_reason— if verification failed, why
Never logged
- The face image itself — never written to disk, never cached, never logged
- The raw embedding — only the encrypted version exists in the database
- The decrypted embedding — exists in memory for ~5ms during comparison, then zeroed
- IP addresses — we don’t log client IP addresses
- Device fingerprints — we don’t collect device information
Data retention and deletion
Default data retention is 90 days, configurable per customer. After the retention period, embeddings and verification logs are automatically purged. Customers can also trigger immediate deletion:
DELETE /enroll/{user_id}
// Immediately removes the encrypted embedding
// Verification logs remain for audit but the
// biometric data is permanently gone
Deletion is irreversible. There is no soft-delete, no recycle bin, no “undo.” When an embedding is deleted, the encrypted bytes are overwritten and the database row is removed. The user would need to re-enroll with a new face capture to use Lorica again.
GDPR compliance by design
Lorica’s architecture was designed from day one to satisfy GDPR requirements without retrofitting:
- Data minimization — we collect the absolute minimum: one face embedding per user. No photos, no names, no email addresses, no PII beyond what your platform provides as a user_id.
- Purpose limitation — embeddings are used exclusively for verification. They cannot be repurposed for surveillance, marketing, or profiling.
- Storage limitation — configurable retention with automatic expiration. Default 90 days.
- Right to erasure —
DELETE /enroll/{user_id}provides immediate, complete deletion. - Right to access —
GET /enroll/{user_id}returns enrollment status (not the embedding itself, which is meaningless to a human). - Data protection by design — authenticated encryption at rest, encryption in transit (TLS 1.2+), memory zeroing after use.
Our published policies cover every detail: biometric privacy policy, data retention policy, and security policy.
The bottom line
If your compliance team asks “do you store face photos?” the answer is no. If they ask “can someone reconstruct a face from what you store?” the answer is no — it’s mathematically impossible. If they ask “is the stored data encrypted?” the answer is yes — authenticated encryption with integrity checking. If they ask “can we delete it?” the answer is immediately and permanently.
That’s the architecture. Built for the compliance conversation, not retrofitted after it.