MS-1491 Spoof check implementation#1735
Conversation
There was a problem hiding this comment.
Pull request overview
Implements face spoof-check support for ROC v3 captures, including configuration parsing, UI states for “validating”/“failed validation”, and propagation of spoof scores into capture events and API payload mappings.
Changes:
- Adds a spoof-check API to
FaceDetectorwith ROC v3 implementation (others return “not available”). - Introduces project custom-config parsing + use case to enable/disable spoof checks for ROC v3 and to configure thresholds/attempts/UI timings.
- Extends face capture flow/UI and event payloads to record spoof score / skip reasons, with updated API mapping and tests.
Reviewed changes
Copilot reviewed 26 out of 26 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| infra/resources/src/main/res/values/strings.xml | Adds UI strings for validating and validation failure states. |
| infra/events/src/test/java/com/simprints/infra/events/event/domain/models/face/FaceCaptureEventTest.kt | Updates event test data to include spoof fields and named args. |
| infra/events/src/main/java/com/simprints/infra/events/event/domain/models/FaceCaptureEvent.kt | Adds spoof fields to payload face model + skip-reason enum. |
| infra/events/src/debug/java/com/simprints/infra/events/sampledata/EventFactoryUtils.kt | Updates debug sample event factory to include spoof fields. |
| infra/event-sync/src/test/java/com/simprints/infra/eventsync/event/remote/models/face/ApiFaceCapturePayloadTest.kt | Extends API mapping tests for spoof fields + refactors result mapping tests. |
| infra/event-sync/src/test/java/com/simprints/infra/eventsync/event/EventValidationUtils.kt | Updates JSON validation expectations for spoof fields in face capture payloads. |
| infra/event-sync/src/main/java/com/simprints/infra/eventsync/event/remote/models/ApiFaceCapturePayload.kt | Adds spoof fields + skip-reason enum to API payload model and mapping. |
| infra/config-store/src/test/java/com/simprints/infra/config/store/models/ExperimentalProjectConfigurationTest.kt | Adds tests for spoof-check custom config parsing defaults/validation. |
| infra/config-store/src/main/java/com/simprints/infra/config/store/models/FaceConfiguration.kt | Introduces spoof-check configuration and mode enum. |
| infra/config-store/src/main/java/com/simprints/infra/config/store/models/ExperimentalProjectConfiguration.kt | Adds spoof-check custom config parsing with defaults and coercion. |
| face/infra/simface/src/main/java/com/simprints/face/infra/simface/detection/SimFaceDetector.kt | Adds no-op spoofCheck() stub returning NOT_AVAILABLE. |
| face/infra/roc-v3/src/main/java/com/simprints/face/infra/rocv3/detection/RocV3Detector.kt | Implements ROC v3 spoof check (scaling, landmarks/IOD gating, score computation). |
| face/infra/roc-v1/src/main/java/com/simprints/face/infra/rocv1/detection/RocV1Detector.kt | Adds no-op spoofCheck() stub returning NOT_AVAILABLE. |
| face/infra/base-bio-sdk/src/main/java/com/simprints/face/infra/basebiosdk/detection/SpoofCheckResult.kt | Adds shared model for spoof score + optional skip reason. |
| face/infra/base-bio-sdk/src/main/java/com/simprints/face/infra/basebiosdk/detection/FaceDetector.kt | Expands detector interface to include spoofCheck(). |
| face/capture/src/test/java/com/simprints/face/capture/usecases/SimpleCaptureEventReporterTest.kt | Adds tests for mapping spoof skip reasons into capture events. |
| face/capture/src/test/java/com/simprints/face/capture/usecases/GetSpoofCheckConfigurationUseCaseTest.kt | Adds unit tests for enabling spoof-check config only for ROC v3. |
| face/capture/src/test/java/com/simprints/face/capture/screens/livefeedback/LiveFeedbackFragmentViewModelTest.kt | Adds validation/reset behavior tests for recorded/enforced spoof modes. |
| face/capture/src/test/java/com/simprints/face/capture/screens/livefeedback/LiveFeedbackAutoCaptureFragmentViewModelTest.kt | Adds auto-capture validation behavior tests and updates process() signature usage. |
| face/capture/src/test/java/com/simprints/face/capture/screens/livefeedback/CropToTargetOverlayAnalyzerTest.kt | Updates analyzer callback signature to include original + cropped bitmaps. |
| face/capture/src/main/java/com/simprints/face/capture/usecases/SimpleCaptureEventReporter.kt | Records spoof score/skip reason into FaceCaptureEvent payloads. |
| face/capture/src/main/java/com/simprints/face/capture/usecases/GetSpoofCheckConfigurationUseCase.kt | Introduces use case to derive spoof-check config gated on ROC v3. |
| face/capture/src/main/java/com/simprints/face/capture/screens/livefeedback/LiveFeedbackFragmentViewModel.kt | Adds validating/failed states, runs spoof checks, and enforces recapture attempts. |
| face/capture/src/main/java/com/simprints/face/capture/screens/livefeedback/LiveFeedbackFragment.kt | Renders validating/failed UI and wires progress updates + analyzer callback changes. |
| face/capture/src/main/java/com/simprints/face/capture/screens/livefeedback/CropToTargetOverlayAnalyzer.kt | Now returns both original and cropped bitmaps for spoof check + detection. |
| face/capture/src/main/java/com/simprints/face/capture/models/FaceDetection.kt | Stores original bitmap + spoofCheckResult on detections. |
…IOD stays in the required range
bbb82fe to
ea62fcd
Compare
|
|
||
| @Keep | ||
| @Serializable | ||
| enum class Result { |
There was a problem hiding this comment.
@luhmirin-s Don't you need to add the SPOOFED result too?
There was a problem hiding this comment.
That is a good question, it was obvious in the initial version of the document where spoof check was part of the feedback loop. Spoof detection is now fully separate process and these result values are taken directly from the feedback loop statuses.
We could add the value and assign it after the check, but I think it might be unnecessary since the score is already present in the face data,
There was a problem hiding this comment.
But if the face is spoofed, it means that we would not use the FaceCapture and SID will not extract the template for it no?
There was a problem hiding this comment.
And in this case what would be the result in the FaceCapture, VALID even if it's not valid?
There was a problem hiding this comment.
Since the spoof check is a computation heavy operation (it takes tens of ms to extract template and couple hundred to spoof check), it is done after all "valid" captures are gathered. So the capture can be "valid" (there is a face in the right position), but still have a high probability of being spoofed.
There was a problem hiding this comment.
Let's chat only in the design doc so that it would be easier for other people to look at it comment on it
There was a problem hiding this comment.
Added the value. Only marking the captures in the event just before saving it to the database, so that it does not interfere with existing UI logic.
|
I discussed this with Jon and we decided that the current state is "good enough" for a first version as we are not sure how prevalent this state will be how disruptive it should be. It is very likely that "enforced" mode would not be used in this version to gather some real-life data first.
There are custom config fields to adjust UI timing specifically for this reason. |




JIRA ticket
Will be released in: 2026.3.0
Design document
Notable changes
Screen.Recording.2026-07-07.at.15.59.36.mov
Custom config
Will be added to the documentation before merging this PR.
Testing guidance
"spoofCheckMode": "ENFORCED"and try to run identification flows:"spoofCheckMode": "RECORDED"and try to run identification flows:Additional work checklist