1use flamingo_verifier_sealed_types::{
2 ComparisonRole, FailureReason, ImageFailureReason, ImageRole, InputFailureReason,
3 ValidationTarget,
4};
5use thiserror::Error;
6
7use super::RequestIntegrityError;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, uniffi::Enum)]
11pub enum FlamingoMatchRejection {
12 MalformedInputs,
14 InvalidHashesJson,
16 ThumbnailHashMismatch,
18 InvalidThreshold,
20 InputRejected {
22 reason: FlamingoInputFailureReason,
24 image: Option<FlamingoImageRole>,
26 limit_bytes: Option<u64>,
28 },
29 MatchBelowThreshold {
31 comparison: FlamingoComparison,
33 },
34 ImageRejected {
36 image: FlamingoImageRole,
38 reason: FlamingoImageFailureReason,
40 target: Option<FlamingoValidationTarget>,
42 },
43 MatchingFailed {
45 comparison: FlamingoComparison,
47 },
48 Internal,
50}
51#[derive(Debug, Clone, Copy, PartialEq, Eq, uniffi::Enum)]
53pub enum FlamingoComparison {
54 OrbSelfie,
56 OrbChallenge,
58 SelfieChallenge,
60}
61#[derive(Debug, Clone, Copy, PartialEq, Eq, uniffi::Enum)]
63pub enum FlamingoImageRole {
64 OrbCredential,
66 LiveSelfie,
68 RtmsChallenge,
70}
71#[derive(Debug, Error, uniffi::Error)]
73pub enum FlamingoError {
74 #[error("invalid {attribute}: {reason}")]
76 InvalidInput {
77 attribute: String,
79 reason: String,
81 kind: FlamingoInputFailureKind,
83 limit_bytes: Option<u64>,
85 },
86 #[error("invalid Flamingo verifier configuration: {0}")]
88 Configuration(String),
89 #[error("Flamingo request integrity failed: {0}")]
91 RequestIntegrity(RequestIntegrityError),
92 #[error("Flamingo service error ({code})")]
94 Service {
95 code: String,
97 allow_retry: bool,
99 },
100 #[error("Flamingo request timed out")]
102 Timeout,
103 #[error("Flamingo transport failed: {details}")]
105 Transport {
106 details: String,
108 },
109 #[error("invalid Flamingo response at {stage:?}")]
111 InvalidResponse {
112 stage: FlamingoResponseStage,
114 },
115 #[error("Flamingo attestation failed: {details}")]
117 Attestation {
118 details: String,
120 },
121 #[error("Flamingo channel failed: {details}")]
123 Channel {
124 details: String,
126 },
127 #[error("invalid Flamingo signing key")]
129 InvalidSigningKey,
130 #[error("invalid Flamingo match statement")]
132 StatementInvalid,
133 #[error("Flamingo reassignment retry exhausted")]
135 ReassignmentRequired,
136}
137
138impl From<FailureReason> for FlamingoMatchRejection {
139 fn from(value: FailureReason) -> Self {
140 match value {
141 FailureReason::MalformedInputs => Self::MalformedInputs,
142 FailureReason::InvalidHashesJson => Self::InvalidHashesJson,
143 FailureReason::ThumbnailHashMismatch => Self::ThumbnailHashMismatch,
144 FailureReason::InvalidThreshold => Self::InvalidThreshold,
145 FailureReason::InputRejected {
146 reason,
147 image,
148 limit_bytes,
149 } => Self::InputRejected {
150 reason: reason.into(),
151 image: image.map(Into::into),
152 limit_bytes,
153 },
154 FailureReason::Internal => Self::Internal,
155 FailureReason::MatchBelowThreshold(comparison) => {
156 Self::MatchBelowThreshold {
157 comparison: comparison.into(),
158 }
159 }
160 FailureReason::MatchingFailed(comparison) => Self::MatchingFailed {
161 comparison: comparison.into(),
162 },
163 FailureReason::ImageRejected {
164 image,
165 reason,
166 target,
167 } => Self::ImageRejected {
168 image: image.into(),
169 reason: reason.into(),
170 target: target.map(Into::into),
171 },
172 }
173 }
174}
175impl From<ComparisonRole> for FlamingoComparison {
176 fn from(value: ComparisonRole) -> Self {
177 match value {
178 ComparisonRole::OrbSelfie => Self::OrbSelfie,
179 ComparisonRole::OrbChallenge => Self::OrbChallenge,
180 ComparisonRole::SelfieChallenge => Self::SelfieChallenge,
181 }
182 }
183}
184impl From<ImageRole> for FlamingoImageRole {
185 fn from(value: ImageRole) -> Self {
186 match value {
187 ImageRole::OrbCredential => Self::OrbCredential,
188 ImageRole::LiveSelfie => Self::LiveSelfie,
189 ImageRole::RtmsChallenge => Self::RtmsChallenge,
190 }
191 }
192}
193#[derive(Debug, Clone, Copy, PartialEq, Eq, uniffi::Enum)]
195pub enum FlamingoImageFailureReason {
196 InvalidImage,
198 TemplateFailed,
200 TooManyFaces,
202 ImageTooDark,
204 ImageTooBright,
206 IlluminationVariance,
208 FaceTooSmall,
210 FaceTooBig,
212 FaceResolutionTooLow,
214 FaceTooHigh,
216 FaceTooLow,
218 FaceTooFarLeft,
220 FaceTooFarRight,
222 HeadPoseYaw,
224 HeadPosePitchTooHigh,
226 HeadPosePitchTooLow,
228 HeadPoseRoll,
230 LowQuality,
232 SunglassesOcclusionDetected,
234 GlassesOcclusionDetected,
236 MaskOcclusionDetected,
238 OtherOcclusionDetected,
240 HairOcclusionDetected,
242 FasOcclusionDetected,
244 SpoofDetected,
246 DepthSpoofDetected,
248 ThermalSpoofDetected,
250 AgeBelowThreshold,
252 NoFaceDetected,
254 EyesClosed,
256 NonNeutralExpression,
258 LandmarksAlignment,
260 FaceOverexposed,
262 FaceUnderexposed,
264 SegmentationOcclusionProportion,
266 BrightArtifacts,
268 LightGuardScoreTooLow,
270 LowContrast,
272 MeshExpressionScore,
274 HighColorDistortion,
276 UnevenLighting,
278 BlurryFace,
280 NoisyThermalImage,
282}
283impl From<ImageFailureReason> for FlamingoImageFailureReason {
284 fn from(value: ImageFailureReason) -> Self {
285 match value {
286 ImageFailureReason::InvalidImage => Self::InvalidImage,
287 ImageFailureReason::TemplateFailed => Self::TemplateFailed,
288 ImageFailureReason::TooManyFaces => Self::TooManyFaces,
289 ImageFailureReason::ImageTooDark => Self::ImageTooDark,
290 ImageFailureReason::ImageTooBright => Self::ImageTooBright,
291 ImageFailureReason::IlluminationVariance => Self::IlluminationVariance,
292 ImageFailureReason::FaceTooSmall => Self::FaceTooSmall,
293 ImageFailureReason::FaceTooBig => Self::FaceTooBig,
294 ImageFailureReason::FaceResolutionTooLow => Self::FaceResolutionTooLow,
295 ImageFailureReason::FaceTooHigh => Self::FaceTooHigh,
296 ImageFailureReason::FaceTooLow => Self::FaceTooLow,
297 ImageFailureReason::FaceTooFarLeft => Self::FaceTooFarLeft,
298 ImageFailureReason::FaceTooFarRight => Self::FaceTooFarRight,
299 ImageFailureReason::HeadPoseYaw => Self::HeadPoseYaw,
300 ImageFailureReason::HeadPosePitchTooHigh => Self::HeadPosePitchTooHigh,
301 ImageFailureReason::HeadPosePitchTooLow => Self::HeadPosePitchTooLow,
302 ImageFailureReason::HeadPoseRoll => Self::HeadPoseRoll,
303 ImageFailureReason::LowQuality => Self::LowQuality,
304 ImageFailureReason::SunglassesOcclusionDetected => {
305 Self::SunglassesOcclusionDetected
306 }
307 ImageFailureReason::GlassesOcclusionDetected => {
308 Self::GlassesOcclusionDetected
309 }
310 ImageFailureReason::MaskOcclusionDetected => Self::MaskOcclusionDetected,
311 ImageFailureReason::OtherOcclusionDetected => Self::OtherOcclusionDetected,
312 ImageFailureReason::HairOcclusionDetected => Self::HairOcclusionDetected,
313 ImageFailureReason::FasOcclusionDetected => Self::FasOcclusionDetected,
314 ImageFailureReason::SpoofDetected => Self::SpoofDetected,
315 ImageFailureReason::DepthSpoofDetected => Self::DepthSpoofDetected,
316 ImageFailureReason::ThermalSpoofDetected => Self::ThermalSpoofDetected,
317 ImageFailureReason::AgeBelowThreshold => Self::AgeBelowThreshold,
318 ImageFailureReason::NoFaceDetected => Self::NoFaceDetected,
319 ImageFailureReason::EyesClosed => Self::EyesClosed,
320 ImageFailureReason::NonNeutralExpression => Self::NonNeutralExpression,
321 ImageFailureReason::LandmarksAlignment => Self::LandmarksAlignment,
322 ImageFailureReason::FaceOverexposed => Self::FaceOverexposed,
323 ImageFailureReason::FaceUnderexposed => Self::FaceUnderexposed,
324 ImageFailureReason::SegmentationOcclusionProportion => {
325 Self::SegmentationOcclusionProportion
326 }
327 ImageFailureReason::BrightArtifacts => Self::BrightArtifacts,
328 ImageFailureReason::LightGuardScoreTooLow => Self::LightGuardScoreTooLow,
329 ImageFailureReason::LowContrast => Self::LowContrast,
330 ImageFailureReason::MeshExpressionScore => Self::MeshExpressionScore,
331 ImageFailureReason::HighColorDistortion => Self::HighColorDistortion,
332 ImageFailureReason::UnevenLighting => Self::UnevenLighting,
333 ImageFailureReason::BlurryFace => Self::BlurryFace,
334 ImageFailureReason::NoisyThermalImage => Self::NoisyThermalImage,
335 }
336 }
337}
338
339#[derive(Debug, Clone, Copy, PartialEq, Eq, uniffi::Enum)]
341pub enum FlamingoValidationTarget {
342 Image,
344 IlluminatedFrame,
346 UnilluminatedFrame,
348 LightGuardPair,
350}
351impl From<ValidationTarget> for FlamingoValidationTarget {
352 fn from(value: ValidationTarget) -> Self {
353 match value {
354 ValidationTarget::Image => Self::Image,
355 ValidationTarget::IlluminatedFrame => Self::IlluminatedFrame,
356 ValidationTarget::UnilluminatedFrame => Self::UnilluminatedFrame,
357 ValidationTarget::LightGuardPair => Self::LightGuardPair,
358 }
359 }
360}
361
362#[derive(Debug, Clone, Copy, PartialEq, Eq, uniffi::Enum)]
364pub enum FlamingoInputFailureReason {
365 MissingImage,
367 MissingSource,
369 InvalidMatchingFrame,
371 EmptyImage,
373 ImageTooLarge,
375 TotalImagesTooLarge,
377}
378impl From<InputFailureReason> for FlamingoInputFailureReason {
379 fn from(value: InputFailureReason) -> Self {
380 match value {
381 InputFailureReason::MissingImage => Self::MissingImage,
382 InputFailureReason::MissingSource => Self::MissingSource,
383 InputFailureReason::InvalidMatchingFrame => Self::InvalidMatchingFrame,
384 InputFailureReason::EmptyImage => Self::EmptyImage,
385 InputFailureReason::ImageTooLarge => Self::ImageTooLarge,
386 InputFailureReason::TotalImagesTooLarge => Self::TotalImagesTooLarge,
387 }
388 }
389}
390
391#[derive(Debug, Clone, Copy, PartialEq, Eq, uniffi::Enum)]
393pub enum FlamingoInputFailureKind {
394 Empty,
396 TooLarge,
398 TotalTooLarge,
400 InvalidThreshold,
402}
403
404#[derive(Debug, Clone, Copy, PartialEq, Eq, uniffi::Enum)]
406pub enum FlamingoResponseStage {
407 Assignment,
409 HostMessage,
411 MatchResult,
413}