Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions 02-architecture/BIOMETRIC_ENGINE_ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ After migration, all real-time detection logic moves into the engine library. Th
| | P2 (Enhancement — deferrable to Phase 3+): | |
| | +-------------------+ +--------------------+ +-----------------+ | |
| | | PassiveLiveness | | EmbeddingComputer | | CardDetector | | |
| | | Detector | | (MobileFaceNet) | | (ONNX YOLO) | | |
| | | Detector | | (Facenet512 ONNX) | | (ONNX YOLO) | | |
| | +-------------------+ +--------------------+ +-----------------+ | |
| +=====================================================================+ |
| | |
Expand Down Expand Up @@ -278,7 +278,7 @@ Nice to have. Server-side alternatives exist for all of these.
| Component | Responsibility | Server Fallback |
|-----------|---------------|-----------------|
| `PassiveLivenessDetector` | Texture/color/moire liveness scoring | Server-side liveness via `biometric-processor` is the primary authority. Client-side is supplementary. Gabor convolution is expensive; defer to Phase 3. |
| `EmbeddingComputer` | ONNX face embeddings | Server-side DeepFace embedding via REST API. **Note:** MobileFaceNet was removed per ADR 0003 (2026-04-18); the active client path is geometry-512 (landmark-based fallback). |
| `EmbeddingComputer` | ONNX face embeddings | Server-side DeepFace embedding via REST API is the legacy/default path (flag OFF). **Note:** MobileFaceNet was removed per ADR 0003 (2026-04-18) for licensing. The client-side embedding path (flag `app.auth.client-side-embedding`, default OFF) computes the **authoritative Facenet512 embedding in the browser** via onnxruntime-web and uploads only the 512-d vector — the raw face image never leaves the device; the server keeps the image→Facenet512 path as fallback and owns the pgvector match + liveness verdict + decision either way. See [CLIENT_SIDE_ML_PLAN](../plans/CLIENT_SIDE_ML_PLAN.md). |
| `CardDetector` | ONNX YOLO card detection | None — client-only in production; the server-side YOLO card path was removed (web-app #111) |

---
Expand Down
4 changes: 2 additions & 2 deletions 09-auth-flows/01-PLATFORM_CAPABILITY_MATRIX.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ FIVUCSAS supports **5 client platforms** and **10 authentication methods** acros
- **Input**: Live camera feed for face capture
- **Platforms**: All camera-equipped devices
- **Dependencies**: Biometric Processor API (FastAPI), front-facing camera
- **Processing**: Server-side (image sent to biometric-processor for embedding extraction/matching)
- **Processing**: Server-authoritative matching + liveness verdict. Legacy/default path (flag OFF): the browser pre-filters and uploads the image; biometric-processor extracts the Facenet512 embedding and matches. Client-side embedding path (flag `app.auth.client-side-embedding`, default OFF): the browser computes the Facenet512 embedding via onnxruntime-web and uploads only the 512-d vector (raw image never leaves the device); the server matches against enrolled templates. Either way the server owns the match + liveness verdict + accept/reject decision.
- **Quality Requirements**: Minimum face size 112x112px, centered, well-lit, eyes open
- **Anti-Spoofing**: Passive liveness detection (texture analysis) + optional active challenges (blink, smile)
- **Anti-Spoofing**: Passive liveness detection (texture analysis) + active Biometric Puzzle (randomized challenge, server re-scored)
- **Enrollment**: 1-3 face images captured with quality validation
- **Offline Capable**: No (requires biometric processor)

Expand Down
18 changes: 17 additions & 1 deletion adr/0004-facenet512-server-authoritative.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
# ADR 0004: Facenet512 as the server-authoritative face embedding

**Status**: Accepted
**Status**: Accepted; **amended 2026-06-11** (see note below)
**Date**: 2026-04-18
**Deciders**: Biometric processing, security, backend

> **Amendment (2026-06-11) — client-side embedding option.** The encoder choice
> (DeepFace **Facenet512**, **512-dim**, cosine match) is unchanged and remains the
> single platform-wide embedding shape. What changed: a flag-gated path
> (`app.auth.client-side-embedding`, default OFF) computes that **same Facenet512
> embedding in the browser** (onnxruntime-web, exported from our own SHA-pinned
> weights) and uploads **only the 512-d vector** — the raw face image never leaves
> the device. When the flag is ON, the client embedding is the **authoritative**
> template/probe (re-enroll on the client pipeline so probe and template share
> preprocessing); the server still owns the pgvector match, the liveness verdict, and
> the accept/reject decision, and the legacy image→Facenet512 path is retained as
> fallback. This supersedes the §Decision claim that the client embedding is "a
> different model / shape … never compared against `face_embeddings`": the *old*
> `geometry-512` pre-filter (ADR 0003) was indeed different, but the *new*
> client-side Facenet512 is identical to the server encoder by design. See
> [`plans/CLIENT_SIDE_ML_PLAN.md`](../plans/CLIENT_SIDE_ML_PLAN.md) (v3.0).

## Context

Once we accepted that the client-side embedding cannot make auth decisions (ADR 0003), the next question was which model the *server* should run as the authoritative face encoder. The biometric-processor service stack includes DeepFace, which exposes a handful of backends (`Facenet`, `Facenet512`, `ArcFace`, `OpenFace`, `VGG-Face`, `DeepFace`, etc.). The choice determines:
Expand Down
Loading