@incodetech/core 0.0.0-dev-20260911-aec162f0 → 0.0.0-dev-20260914-8aef7789

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/dist/{FaceDetectionProvider-Cn1wS-sA.d.ts → BaseWasmProvider-CO0GfaHM.d.ts} +7 -37
  2. package/dist/{BrowserDiagnosticsCryptoProvider-8sT0QLgq.esm.js → BrowserDiagnosticsCryptoProvider-BoYzmYY5.esm.js} +1 -1
  3. package/dist/{onDeviceFaceResults-hle2Ci9l.esm.js → FaceDetectionProvider-0bWjPgW5.esm.js} +219 -340
  4. package/dist/FaceDetectionProvider-CyLxkzRP.d.ts +36 -0
  5. package/dist/{IIdCaptureCapability-DDWlQzhi.d.ts → IIdCaptureCapability-nfpic2z2.d.ts} +7 -3
  6. package/dist/{IWasmUtilCapability-SNPhmIwB.d.ts → IWasmUtilCapability-DaP6pfHq.d.ts} +10 -4
  7. package/dist/{MotionSensorProvider-Vlyhbcty.esm.js → MotionSensorProvider-BnZ8_1Sk.esm.js} +1 -1
  8. package/dist/{StreamCanvasCapture-D2XcXCZ4.esm.js → StreamCanvasCapture-C9jtgBdT.esm.js} +2 -2
  9. package/dist/{deepsightService-MZOpj7Vp.d.ts → StreamCanvasCapture-D9Dz8kqB.d.ts} +54 -41
  10. package/dist/ae-signature.esm.js +1 -1
  11. package/dist/{apiError-XdhqSAmg.esm.js → apiError-CixFeCyt.esm.js} +1 -1
  12. package/dist/authentication.d.ts +3 -3
  13. package/dist/authentication.esm.js +2 -2
  14. package/dist/{authenticationManager-DqBOkMzk.esm.js → authenticationManager-CN26fkJa.esm.js} +4 -4
  15. package/dist/{authenticationManager-BCkV6CSG.d.ts → authenticationManager-D7UUqgnN.d.ts} +1 -1
  16. package/dist/{authenticationStateMachine-Cto_G5bN.esm.js → authenticationStateMachine-CUXpIxAD.esm.js} +6 -62
  17. package/dist/avatar.d.ts +1 -1
  18. package/dist/avatar.esm.js +1 -1
  19. package/dist/{backCameraStream-DE_5qY04.esm.js → backCameraStream-BOtyQowf.esm.js} +75 -18
  20. package/dist/{camera-_2sXMXiF.esm.js → camera-sIa9ceW2.esm.js} +19 -1
  21. package/dist/camera.esm.js +1 -1
  22. package/dist/{canvas-E1zGkel4.esm.js → canvas-BxFzWTt-.esm.js} +19 -0
  23. package/dist/createCameraCycleOwnership-DQ5-F2oW.esm.js +826 -0
  24. package/dist/{createFaceAvatar-DQKaRise.esm.js → createFaceAvatar-BNHdeFj8.esm.js} +2 -2
  25. package/dist/{createFaceAvatar-pUEkdk4X.d.ts → createFaceAvatar-CTM9aj9Q.d.ts} +12 -6
  26. package/dist/curp-validation.d.ts +1 -1
  27. package/dist/{curpValidationManager-cSd2MrOQ.d.ts → curpValidationManager-CTJB2RsD.d.ts} +1 -1
  28. package/dist/{deepsightLoader-Dwr1zKFa.esm.js → deepsightLoader-Dhz9T_KJ.esm.js} +19 -53
  29. package/dist/document-capture.esm.js +2 -2
  30. package/dist/{documentCaptureManager-BTpHZMgW.esm.js → documentCaptureManager-BwcbMwo5.esm.js} +1 -1
  31. package/dist/{documentCaptureStateMachine-CPizkpcg.esm.js → documentCaptureStateMachine-F8SCOtL_.esm.js} +4 -4
  32. package/dist/dynamic-forms.esm.js +2 -2
  33. package/dist/{dynamicFormsManager-Cmh84Nz4.esm.js → dynamicFormsManager-CNBrBOR3.esm.js} +1 -1
  34. package/dist/{dynamicFormsStateMachine-DZr7Ugvy.esm.js → dynamicFormsStateMachine-Bo2qrjHB.esm.js} +1 -1
  35. package/dist/ekyb.d.ts +1 -1
  36. package/dist/ekyb.esm.js +3 -3
  37. package/dist/{ekybManager-Dc2tT9fu.esm.js → ekybManager-D8DdfRAD.esm.js} +1 -1
  38. package/dist/{ekybStateMachine-GSEMOiHn.esm.js → ekybStateMachine-oPCbEFob.esm.js} +1 -1
  39. package/dist/electronic-signature.esm.js +1 -1
  40. package/dist/{electronicSignatureManager-CpLuqw7T.esm.js → electronicSignatureManager-DkKQ07vx.esm.js} +1 -1
  41. package/dist/extensibility.d.ts +11 -58
  42. package/dist/extensibility.esm.js +13 -13
  43. package/dist/{faceCaptureManagerFactory-kDmbL0I7.esm.js → faceCaptureManagerFactory-D_EjQnnE.esm.js} +19 -4
  44. package/dist/{faceCaptureManagerFactory-CzUr_ZPq.d.ts → faceCaptureManagerFactory-DqrYpjA5.d.ts} +24 -12
  45. package/dist/{faceCaptureSetup-CAGBnLVx.esm.js → faceCaptureSetup-WeO8-TfR.esm.js} +999 -382
  46. package/dist/{feature-management-B6CtmH1O.esm.js → feature-management-BEqf3Sr3.esm.js} +1 -1
  47. package/dist/feature-management.esm.js +1 -1
  48. package/dist/fiscal-qr.esm.js +1 -1
  49. package/dist/{fiscalQrManager-DI6uOffY.esm.js → fiscalQrManager-Bp_-3LJr.esm.js} +3 -3
  50. package/dist/flow-events.d.ts +1 -1
  51. package/dist/flow.d.ts +6 -6
  52. package/dist/flow.esm.js +3 -3
  53. package/dist/{flowCompletionService-BpoZDpAn.esm.js → flowCompletionService-DELbVeL5.esm.js} +1 -1
  54. package/dist/{flowServices-BVnSStkh.esm.js → flowServices-Brr2fh_c.esm.js} +5 -5
  55. package/dist/geolocation.esm.js +2 -2
  56. package/dist/{geolocationManager-CLm86P8G.esm.js → geolocationManager-CtVZDjng.esm.js} +1 -1
  57. package/dist/{geolocationStateMachine-Bi3vy7Wl.esm.js → geolocationStateMachine-tjsYcMhr.esm.js} +1 -1
  58. package/dist/home.d.ts +1 -1
  59. package/dist/id-selfie-flow.d.ts +3 -3
  60. package/dist/id-selfie-flow.esm.js +10 -10
  61. package/dist/id.d.ts +4 -4
  62. package/dist/id.esm.js +35 -44
  63. package/dist/{idCaptureDefaults-BLsd7shz.esm.js → idCaptureDefaults-C66YvkgN.esm.js} +19 -14
  64. package/dist/{idCaptureManager-DW1GeEUk.d.ts → idCaptureManager-DE_jyr5X.d.ts} +98 -37
  65. package/dist/{idCaptureManager-BUTdcmaD.esm.js → idCaptureManager-zjul9YdZ.esm.js} +27 -17
  66. package/dist/{idCaptureServices-fzIhBqAK.esm.js → idCaptureServices-UXYCBZPK.esm.js} +80 -20
  67. package/dist/{idCaptureStateMachine-Cp2_revF.esm.js → idCaptureStateMachine-D3pqfK2Z.esm.js} +1954 -1082
  68. package/dist/{index-1PoJuUJ-.d.ts → index-BGxFwnld.d.ts} +1 -1
  69. package/dist/index.d.ts +1 -1
  70. package/dist/index.esm.js +1 -1
  71. package/dist/mandatory-consent.d.ts +2 -2
  72. package/dist/{mandatoryConsentManager-BJnylLZO.d.ts → mandatoryConsentManager-CZwhsUlO.d.ts} +1 -1
  73. package/dist/{permissionGuards-DxbvOoZJ.esm.js → permissionGuards-o1JLtewE.esm.js} +1 -1
  74. package/dist/{permissionServices-f7nBnW5P.esm.js → permissionServices-7lzEiOsO.esm.js} +3 -3
  75. package/dist/personhood.d.ts +5 -5
  76. package/dist/personhood.esm.js +8 -8
  77. package/dist/qe-signature.esm.js +1 -1
  78. package/dist/{runChildModule-BPlX2IDO.esm.js → runChildModule-BDlvNMrA.esm.js} +1 -1
  79. package/dist/{safeStorage-Dp9m6aOh.esm.js → safeStorage-1O9k0ulP.esm.js} +8 -8
  80. package/dist/{sdkVersion-Dr9_E3d9.esm.js → sdkVersion-CS_0s_Lc.esm.js} +1 -1
  81. package/dist/selfie.d.ts +4 -4
  82. package/dist/selfie.esm.js +12 -74
  83. package/dist/{selfieManager-BdP-RgH4.esm.js → selfieManager-BouB9yUQ.esm.js} +4 -4
  84. package/dist/{selfieManager-Bg_Xwe4p.d.ts → selfieManager-DZ3u_WN9.d.ts} +1 -1
  85. package/dist/{selfieStateMachine-B8vFeT39.esm.js → selfieStateMachine-TGfI9hNp.esm.js} +22 -31
  86. package/dist/{session-C2THUsQZ.esm.js → session-m9j27bHm.esm.js} +3 -3
  87. package/dist/session.d.ts +1 -1
  88. package/dist/session.esm.js +4 -4
  89. package/dist/{sessionInitializer-CEycxhm4.esm.js → sessionInitializer-CUpgbHzs.esm.js} +4 -4
  90. package/dist/{setup-D6yz9se2.d.ts → setup-CEX95gJ1.d.ts} +11 -6
  91. package/dist/{setup-BHJ3-fhX.esm.js → setup-CfNAVG-d.esm.js} +12 -11
  92. package/dist/{trueSightService-DLzYznkh.esm.js → trueSightService-TqmmYye3.esm.js} +4 -4
  93. package/dist/types-BhHF-CuL.d.ts +6 -0
  94. package/dist/{types-DJ2OM9rw.d.ts → types-BzuUebkB.d.ts} +1 -1
  95. package/dist/{types-DzmqFoCH.d.ts → types-CBctcPeF.d.ts} +1 -1
  96. package/dist/{types-BBI4-s9u2.d.ts → types-CoOlCUp82.d.ts} +5 -5
  97. package/dist/{types-hSqUyXyw.d.ts → types-DL0CXuWv.d.ts} +3 -3
  98. package/dist/types-Ds928RiU.d.ts +1 -0
  99. package/dist/{types-_pWNFY1F.d.ts → types-eLtVBhon.d.ts} +1 -1
  100. package/dist/video-selfie.d.ts +3 -3
  101. package/dist/video-selfie.esm.js +5 -5
  102. package/dist/{videoSelfieCameraWarmer-D5E12WjL.esm.js → videoSelfieCameraWarmer-C-cESczy.esm.js} +9 -9
  103. package/dist/{videoSelfieStepDetector-B8TvFDNK.d.ts → videoSelfieStepDetector-CdXIFh9s.d.ts} +4 -4
  104. package/dist/virtualCameraCheck-WOloJ-do.esm.js +48 -0
  105. package/dist/{warmup-BOM-sD-6.esm.js → warmup-CUUnwYxe.esm.js} +282 -90
  106. package/dist/{warmup-CXHBgvFC.d.ts → warmup-Cis2p6O0.d.ts} +13 -2
  107. package/dist/wasm.d.ts +9 -3
  108. package/dist/wasm.esm.js +10 -4
  109. package/dist/{wasmDsFlagSync-C3k_VK9o.esm.js → wasmDsFlagSync-BJtLh2XK.esm.js} +1 -1
  110. package/dist/{wasmWebClient-BJCaFeBL.esm.js → wasmWebClient-B7baE-Wf.esm.js} +223 -2
  111. package/dist/workflow.d.ts +1 -1
  112. package/dist/workflow.esm.js +15 -15
  113. package/package.json +1 -1
  114. package/dist/imageFile-CLaua6xO.esm.js +0 -69
  115. package/dist/types-m4t_cT5J.d.ts +0 -6
  116. package/dist/{Face2DProvider-UUQt_vRC.esm.js → Face2DProvider-BF48sz5c.esm.js} +1 -1
  117. package/dist/{PrivacyLensProvider-D8PS7AJa.esm.js → PrivacyLensProvider-EwnC_C5n.esm.js} +1 -1
  118. package/dist/{selfieErrorUtils-C6gC06J7.esm.js → selfieErrorUtils-C77GXJH6.esm.js} +1 -1
@@ -1,15 +1,20 @@
1
+ import { t as getTimestamp } from "./IBrowserEnvironmentCapability-DEaRRk-R.esm.js";
1
2
  import { r as getToken } from "./api-Bx3gKW_y.esm.js";
3
+ import { l as trueSightLog, m as isTrueSightTesting } from "./trueSightService-TqmmYye3.esm.js";
4
+ import "./sessionInitializer-CUpgbHzs.esm.js";
5
+ import { t as addDeviceStats } from "./stats-DkK-f8JT.esm.js";
2
6
  import { t as isAndroid } from "./platform-DkcRc9JV.esm.js";
3
- import { i as assign, r as sendTo, t as setup } from "./xstate.esm-BuFLFuzz.esm.js";
7
+ import { i as assign, n as enqueueActions, r as sendTo, t as setup } from "./xstate.esm-BuFLFuzz.esm.js";
4
8
  import { n as fromPromise, t as fromCallback } from "./xstate-actors.esm-BXeQ-Ucz.esm.js";
5
- import { n as invokeRequestPermissionActor, t as checkPermission } from "./permissionServices-f7nBnW5P.esm.js";
6
- import { c as sendLabelInspectionEvent, d as stopRecording, f as stopStream, l as startDetection, o as initializeCamera, s as initializeDeepsightSession, u as startRecordingSession } from "./onDeviceFaceResults-hle2Ci9l.esm.js";
7
- import { i as uploadDeepsightVideo } from "./recordingsRepository-CCWy13M-.esm.js";
9
+ import { n as invokeRequestPermissionActor, t as checkPermission } from "./permissionServices-7lzEiOsO.esm.js";
10
+ import { a as sendLabelInspectionEvent, c as stopRecording, i as initializeDeepsightSession, l as stopStream, r as initializeCamera, s as startRecordingSession, t as FaceDetectionProvider } from "./FaceDetectionProvider-0bWjPgW5.esm.js";
8
11
  import { t as FACE_ERROR_CODES } from "./types-BN5RPPIZ.esm.js";
9
- import { n as releaseFaceAvatarWarmup, r as warmFaceAvatar, t as createFaceAvatar } from "./createFaceAvatar-DQKaRise.esm.js";
10
- import { t as StreamCanvasCapture } from "./StreamCanvasCapture-D2XcXCZ4.esm.js";
11
- import { n as needsMotionPrimeOnlyFromPermission, r as resolveStoredPermissionResult, t as isReadyForCaptureFromPermission } from "./permissionGuards-DxbvOoZJ.esm.js";
12
- import { n as flagFaceManualReview, t as imageFileToDataUrl } from "./imageFile-CLaua6xO.esm.js";
12
+ import { a as flagFaceManualReview, i as imageFileToDataUrl, n as runProtectedAttempt, r as cameraCycleProvider, s as PROTECTED_CAPTURE_TARGET, t as createCameraCycleOwnership } from "./createCameraCycleOwnership-DQ5-F2oW.esm.js";
13
+ import { n as releaseFaceAvatarWarmup, r as warmFaceAvatar, t as createFaceAvatar } from "./createFaceAvatar-BNHdeFj8.esm.js";
14
+ import { t as IncodeCanvas } from "./canvas-BxFzWTt-.esm.js";
15
+ import { n as needsMotionPrimeOnlyFromPermission, r as resolveStoredPermissionResult, t as isReadyForCaptureFromPermission } from "./permissionGuards-o1JLtewE.esm.js";
16
+ import { i as uploadDeepsightVideo } from "./recordingsRepository-CCWy13M-.esm.js";
17
+ import { t as getDeviceClass } from "./getDeviceClass-5NYZg9s6.esm.js";
13
18
  import { n as getAdaptiveMediaRecorderOptions, t as MultipartRecordingService } from "./multipartRecordingService-B3C_zlev.esm.js";
14
19
  //#region src/internal/avatar/concealment.ts
15
20
  /**
@@ -269,6 +274,31 @@ const manualFaceUploadMachine = setup({
269
274
  }
270
275
  });
271
276
  //#endregion
277
+ //#region ../infra/src/providers/wasm/createProtectedFaceCaptureCapabilities.ts
278
+ /**
279
+ * Infrastructure composition boundary for one protected still-face attempt.
280
+ * Core receives capability interfaces and never constructs or reaches for the
281
+ * process-wide WASM providers directly.
282
+ */
283
+ function createProtectedFaceCaptureCapabilities() {
284
+ return {
285
+ cycle: cameraCycleProvider,
286
+ faceDetection: new FaceDetectionProvider()
287
+ };
288
+ }
289
+ //#endregion
290
+ //#region src/internal/faceCapture/faceCaptureDiagnostics.ts
291
+ const FACE_CAMERA_DIAGNOSTIC_PREFIX = "[Incode face camera]";
292
+ /**
293
+ * Emits one bounded lifecycle line only for SDK testing sessions. The payload
294
+ * deliberately excludes media, native results, tokens, request data, and
295
+ * errors so a browser console recording cannot retain capture data.
296
+ */
297
+ function logFaceCameraDiagnostic(event, fields) {
298
+ if (!isTrueSightTesting()) return;
299
+ console.debug(`${FACE_CAMERA_DIAGNOSTIC_PREFIX} ${event} ${JSON.stringify(fields)}`);
300
+ }
301
+ //#endregion
272
302
  //#region ../infra/src/media/VideoTrimmer.ts
273
303
  async function getDurationBySeek(videoBlob) {
274
304
  const video = document.createElement("video");
@@ -555,6 +585,12 @@ var MultipartFaceRecordingService = class {
555
585
  }
556
586
  return { recordingId: null };
557
587
  }
588
+ pauseForBackground() {
589
+ this.service.pause();
590
+ }
591
+ async resumeFromBackground() {
592
+ this.service.resume();
593
+ }
558
594
  async stopAndGetVideo() {
559
595
  try {
560
596
  await this.service.stop();
@@ -619,14 +655,671 @@ var InjectedRecordingService = class {
619
655
  */
620
656
  function createRecordingService(params) {
621
657
  if (params.config.onDeviceFaceResultsSubmissionEnabled === true) return;
658
+ if (params.localDelivery === true) return params.config.enableFaceRecording === true || params.config.deepsightLiveness === "VIDEOLIVENESS" ? new LocalRecordingService(params.wasmUtil, null) : void 0;
622
659
  if (params.config.deepsightLiveness === "VIDEOLIVENESS") return new LocalRecordingService(params.wasmUtil, params.sessionToken);
623
660
  if (params.config.enableFaceRecording === true) return params.config.recording?.capability ? new InjectedRecordingService(params.config) : new MultipartFaceRecordingService();
624
661
  }
625
662
  //#endregion
663
+ //#region src/internal/faceCapture/protectedFaceAttempt.ts
664
+ const ON_DEVICE_MANUAL_CAPTURE_TIMEOUT_MS = 2147483647;
665
+ var ProtectedFaceRecorderHooks = class {
666
+ constructor(config, dependencies, delivery) {
667
+ this.config = config;
668
+ this.dependencies = dependencies;
669
+ this.delivery = delivery;
670
+ this.mode = config.onDeviceFaceResultsSubmissionEnabled === true || config.enableFaceRecording !== true && config.deepsightLiveness !== "VIDEOLIVENESS" ? "none" : "finalizeBeforePoc";
671
+ }
672
+ async start(unprotectedStream) {
673
+ if (this.mode === "none") return;
674
+ const wasmUtil = await this.dependencies.getWasmUtil();
675
+ this.service = createRecordingService({
676
+ config: this.config,
677
+ wasmUtil,
678
+ sessionToken: getToken(),
679
+ localDelivery: this.delivery === "local"
680
+ });
681
+ await this.service?.start(unprotectedStream);
682
+ }
683
+ async prepareForPoc() {
684
+ if (!this.service) return {};
685
+ if (this.delivery === "local") {
686
+ try {
687
+ const result = await this.service.stopAndGetVideo();
688
+ this.captureOnlyVideoBase64 = result.videoBase64;
689
+ } catch {
690
+ this.captureOnlyVideoBase64 = void 0;
691
+ }
692
+ return {};
693
+ }
694
+ return this.service.stop();
695
+ }
696
+ async resumeAfterPoc() {}
697
+ pauseForBackground() {
698
+ this.service?.pauseForBackground?.();
699
+ }
700
+ async resumeFromBackground(unprotectedStream) {
701
+ await this.service?.resumeFromBackground?.(unprotectedStream);
702
+ }
703
+ dispose() {
704
+ try {
705
+ this.service?.cleanup();
706
+ } finally {
707
+ this.service = void 0;
708
+ }
709
+ }
710
+ takeCaptureOnlyVideo() {
711
+ const video = this.captureOnlyVideoBase64;
712
+ this.captureOnlyVideoBase64 = void 0;
713
+ return video;
714
+ }
715
+ };
716
+ let nextAttemptNumber = 1;
717
+ /**
718
+ * Private composition object for one still-face attempt. It owns provider
719
+ * callbacks and raw-stream handoff outside XState; the machine sees only the
720
+ * presentation stream/canvas and allowlisted semantic results.
721
+ */
722
+ var ProtectedFaceAttemptRuntime = class ProtectedFaceAttemptRuntime {
723
+ constructor(options) {
724
+ this.options = options;
725
+ this.attemptId = `face-${nextAttemptNumber++}`;
726
+ this.acquiredUsingBackCamera = false;
727
+ this.rawHandedOff = false;
728
+ this.rawStreamReleased = false;
729
+ this.released = false;
730
+ this.recorderTransferred = false;
731
+ this.pendingSignals = [];
732
+ this.provider = options.faceDetection;
733
+ this.recorder = new ProtectedFaceRecorderHooks(options.config, options.dependencies, options.delivery);
734
+ this.cycleOwnership = createCameraCycleOwnership(options.cycle);
735
+ }
736
+ get delivery() {
737
+ return this.options.delivery;
738
+ }
739
+ get usingBackCamera() {
740
+ return this.acquiredUsingBackCamera;
741
+ }
742
+ setDeepsightService(service) {
743
+ if (this.released || this.deepsightService) return;
744
+ this.deepsightService = service;
745
+ }
746
+ async preAcquire() {
747
+ await this.acquireRawStream();
748
+ }
749
+ subscribeSignals(listener) {
750
+ if (this.released) return () => void 0;
751
+ this.signalListener = listener;
752
+ const queued = this.pendingSignals;
753
+ this.pendingSignals = [];
754
+ queued.forEach(listener);
755
+ return () => {
756
+ if (this.signalListener === listener) this.signalListener = void 0;
757
+ };
758
+ }
759
+ toActorInput(onStartupTiming) {
760
+ this.recorderTransferred = true;
761
+ return {
762
+ attemptId: this.attemptId,
763
+ target: this.options.target,
764
+ workflow: this.options.config.onDeviceFaceResultsSubmissionEnabled === true ? 5 : 4,
765
+ streamSource: {
766
+ kind: "acquire",
767
+ acquire: async () => {
768
+ const result = await this.acquireRawStream();
769
+ this.rawHandedOff = true;
770
+ return {
771
+ stream: result.stream,
772
+ constraints: result.constraints
773
+ };
774
+ }
775
+ },
776
+ cycle: this.options.cycle,
777
+ cycleOwnership: this.cycleOwnership,
778
+ recorder: this.recorder,
779
+ releaseUnadoptedStream: (stream) => stopStream(stream),
780
+ configureWorkflow: () => this.configureWorkflow(),
781
+ runPrc: () => this.runPrc(),
782
+ runPoc: () => this.runPoc(),
783
+ onStartupTiming,
784
+ faceResults: this.provider
785
+ };
786
+ }
787
+ createUploadCommand(recordingId) {
788
+ const token = getToken();
789
+ const config = {
790
+ headers: token ? { "X-Incode-Hardware-Id": token } : void 0,
791
+ timeout: 3e4
792
+ };
793
+ if (this.options.config.onDeviceFaceResultsSubmissionEnabled === true) return {
794
+ type: "UPLOAD_FACE_RESULTS",
795
+ config
796
+ };
797
+ const validRecordingId = recordingId && recordingId.trim().length > 0 ? recordingId : void 0;
798
+ if (this.options.target === PROTECTED_CAPTURE_TARGET.authentication) return {
799
+ type: "UPLOAD_PROTECTED",
800
+ request: {
801
+ target: PROTECTED_CAPTURE_TARGET.authentication,
802
+ extras: {
803
+ deviceClass: getDeviceClass(),
804
+ hint: this.options.authHint,
805
+ ...validRecordingId ? { recordingId: validRecordingId } : {}
806
+ },
807
+ config
808
+ }
809
+ };
810
+ return {
811
+ type: "UPLOAD_PROTECTED",
812
+ request: {
813
+ target: PROTECTED_CAPTURE_TARGET.selfie,
814
+ extras: { deviceClass: getDeviceClass() },
815
+ config: {
816
+ ...config,
817
+ params: {
818
+ imageType: "selfie",
819
+ ...validRecordingId ? { recordingId: validRecordingId } : {}
820
+ }
821
+ }
822
+ }
823
+ };
824
+ }
825
+ mapProtectedResult(result) {
826
+ if (result.kind === "onDeviceFace") return {};
827
+ if (result.kind === "authentication") return {
828
+ overallStatus: result.overallStatus,
829
+ captureAttemptsLimit: {
830
+ max: this.options.config.captureAttempts ?? this.options.config.numberOfAttempts ?? 3,
831
+ remaining: result.attemptsRemaining ?? 0
832
+ },
833
+ candidate: "",
834
+ error: {
835
+ name: result.errorName ?? "",
836
+ message: result.errorName ?? ""
837
+ }
838
+ };
839
+ return result;
840
+ }
841
+ takeCaptureOnlyVideo() {
842
+ return this.recorder.takeCaptureOnlyVideo();
843
+ }
844
+ next() {
845
+ return new ProtectedFaceAttemptRuntime(this.options);
846
+ }
847
+ release() {
848
+ if (this.released) return;
849
+ this.released = true;
850
+ this.signalListener = void 0;
851
+ this.pendingSignals = [];
852
+ if (!this.recorderTransferred) try {
853
+ this.recorder.dispose();
854
+ } catch {}
855
+ try {
856
+ Promise.resolve(this.provider.dispose()).catch(() => void 0);
857
+ } catch {}
858
+ this.cycleOwnership.releaseByController();
859
+ if (!this.rawHandedOff) this.acquired?.then(({ stream }) => this.releaseRawStream(stream), () => void 0);
860
+ }
861
+ async acquireRawStream() {
862
+ if (!this.acquired) this.acquired = this.options.acquireCamera(this.provider);
863
+ const result = await this.acquired;
864
+ this.acquiredUsingBackCamera = result.usingBackCamera;
865
+ if (this.released) {
866
+ this.releaseRawStream(result.stream);
867
+ throw new Error("Protected face attempt was released");
868
+ }
869
+ return result;
870
+ }
871
+ async configureWorkflow() {
872
+ await this.provider.initialize({
873
+ autocaptureInterval: this.options.config.onDeviceFaceResultsSubmissionEnabled === true ? ON_DEVICE_MANUAL_CAPTURE_TIMEOUT_MS : this.options.config.autoCaptureTimeout * 1e3,
874
+ useOnDeviceWorkflow: this.options.config.onDeviceFaceResultsSubmissionEnabled === true
875
+ });
876
+ if (this.released) return;
877
+ this.provider.setChecksEnabled({
878
+ lenses: this.options.config.validateLenses ?? false,
879
+ mask: this.options.config.validateFaceMask ?? false,
880
+ closedEyes: this.options.config.validateClosedEyes ?? false,
881
+ headWear: this.options.config.validateHeadCover ?? false,
882
+ occlusion: false
883
+ });
884
+ this.provider.setCallbacks({
885
+ onFarAway: () => this.emitDetection("tooFar"),
886
+ onTooClose: () => this.emitDetection("tooClose"),
887
+ onTooManyFaces: () => this.emitDetection("tooManyFaces"),
888
+ onNoFace: () => this.emitDetection("idle"),
889
+ onCenterFace: () => this.emitDetection("centerFace"),
890
+ onGetReady: () => this.emitDetection("getReady"),
891
+ onGetReadyFinished: () => this.emitDetection("getReadyFinished"),
892
+ onDark: () => {
893
+ if (this.options.config.validateBrightness) this.emitDetection("dark");
894
+ },
895
+ onBlur: () => this.emitDetection("blur"),
896
+ onFaceAngle: () => this.emitDetection("faceAngle"),
897
+ onLenses: () => {
898
+ if (this.options.config.validateLenses) this.emitDetection("lenses");
899
+ },
900
+ onMask: () => {
901
+ if (this.options.config.validateFaceMask) this.emitDetection("faceMask");
902
+ },
903
+ onEyesClosed: () => {
904
+ if (this.options.config.validateClosedEyes) this.emitDetection("eyesClosed");
905
+ },
906
+ onHeadWear: () => {
907
+ if (this.options.config.validateHeadCover) this.emitDetection("headWear");
908
+ },
909
+ onFaceOccluded: () => this.emitDetection("faceOcclusion"),
910
+ onSwitchToManualCapture: () => {
911
+ if (this.options.config.onDeviceFaceResultsSubmissionEnabled !== true) this.emitDetection("manualCapture");
912
+ },
913
+ onCapture: (canvas) => {
914
+ this.emit({
915
+ type: "autoCapture",
916
+ preview: canvas.canvas
917
+ });
918
+ }
919
+ });
920
+ this.emitDetection("detecting");
921
+ }
922
+ async runPrc() {
923
+ if (this.options.delivery === "protected") await this.attachProtectedCameraMetadata();
924
+ if (this.released) return;
925
+ const wasmUtil = await this.options.dependencies.getWasmUtil();
926
+ if (this.released) return;
927
+ await wasmUtil.prc();
928
+ }
929
+ async runPoc() {
930
+ if (this.options.delivery === "local") return;
931
+ const deepsight = this.deepsightService;
932
+ if (!deepsight) throw new Error("Protected face Deepsight is not ready");
933
+ await deepsight.performVirtualCameraCheck(getToken(), "SELFIE");
934
+ if (this.released) return;
935
+ try {
936
+ await deepsight.finalizeProtectedCaptureMetadata();
937
+ } catch {
938
+ trueSightLog("warning", "deepsight", "faceScan", "protected capture metadata finalization failed");
939
+ }
940
+ if (this.released) return;
941
+ try {
942
+ addDeviceStats({
943
+ frontIdStatsAnalysisStatus: "",
944
+ backIdStatsAnalysisStatus: "",
945
+ selfieStatsAnalysisStatus: deepsight.getAnalysisStatus(),
946
+ motionStatus: deepsight.getMotionStatus()
947
+ });
948
+ } catch {}
949
+ const logs = deepsight.getPipelineState();
950
+ this.options.dependencies.trackCaptureAttemptFinished?.({ logs });
951
+ }
952
+ async attachProtectedCameraMetadata() {
953
+ const deepsight = this.deepsightService;
954
+ if (!deepsight) return;
955
+ try {
956
+ const { stream } = await this.acquireRawStream();
957
+ const [videoTrack] = stream.getVideoTracks();
958
+ if (videoTrack) await deepsight.checkVirtualCamera(videoTrack);
959
+ } catch {
960
+ trueSightLog("warning", "deepsight", "faceScan", "protected camera metadata attachment failed");
961
+ }
962
+ }
963
+ emitDetection(status) {
964
+ this.emit({
965
+ type: "detection",
966
+ status
967
+ });
968
+ }
969
+ emit(signal) {
970
+ if (this.released) return;
971
+ if (this.signalListener) this.signalListener(signal);
972
+ else this.pendingSignals.push(signal);
973
+ }
974
+ releaseRawStream(stream) {
975
+ if (this.rawHandedOff || this.rawStreamReleased) return;
976
+ this.rawStreamReleased = true;
977
+ try {
978
+ stopStream(stream);
979
+ } catch {}
980
+ }
981
+ };
982
+ //#endregion
983
+ //#region src/internal/faceCapture/protectedFaceController.ts
984
+ /**
985
+ * Binds one face-machine variant to a fixed native target and delivery mode.
986
+ * The capability-bearing runtime and lifecycle input never leave this callback
987
+ * actor's closure, so parent snapshots contain only presentation/output data.
988
+ */
989
+ function createProtectedFaceControllerActor(options) {
990
+ return fromCallback(({ sendBack, receive }) => {
991
+ let controllerInput;
992
+ let runtime;
993
+ let deepsightService;
994
+ let deepsightState = "idle";
995
+ let signalCleanup;
996
+ let lifecycleCleanup;
997
+ let sendLifecycle;
998
+ let committedPreview;
999
+ let pendingAutoPreview;
1000
+ let recording = {};
1001
+ let generation = 0;
1002
+ let active = true;
1003
+ let diagnosticAttempt = 0;
1004
+ let diagnosticStartedAt;
1005
+ const logDiagnostic = (event, fields = {}) => {
1006
+ if (diagnosticStartedAt === void 0) return;
1007
+ logFaceCameraDiagnostic(event, {
1008
+ attempt: diagnosticAttempt,
1009
+ target: options.target === PROTECTED_CAPTURE_TARGET.authentication ? "authentication" : "selfie",
1010
+ delivery: options.delivery,
1011
+ elapsedMs: Math.round(getTimestamp() - diagnosticStartedAt),
1012
+ ...fields
1013
+ });
1014
+ };
1015
+ const getControllerInput = () => {
1016
+ if (!controllerInput) throw new Error("Protected face controller is not bound");
1017
+ return controllerInput;
1018
+ };
1019
+ const ensureRuntime = () => {
1020
+ if (!runtime) {
1021
+ const input = getControllerInput();
1022
+ const capabilities = options.createCapabilities();
1023
+ runtime = new ProtectedFaceAttemptRuntime({
1024
+ config: input.config,
1025
+ dependencies: input.dependencies,
1026
+ target: options.target,
1027
+ delivery: options.delivery,
1028
+ authHint: input.authHint,
1029
+ faceDetection: capabilities.faceDetection,
1030
+ cycle: capabilities.cycle,
1031
+ acquireCamera: (provider) => initializeCamera({
1032
+ config: input.config,
1033
+ provider
1034
+ })
1035
+ });
1036
+ if (deepsightService) runtime.setDeepsightService(deepsightService);
1037
+ }
1038
+ return runtime;
1039
+ };
1040
+ const releaseCurrent = (reason) => {
1041
+ logDiagnostic("attempt-release", { releaseReason: reason });
1042
+ diagnosticStartedAt = void 0;
1043
+ generation += 1;
1044
+ signalCleanup?.();
1045
+ signalCleanup = void 0;
1046
+ sendLifecycle?.({
1047
+ type: "RELEASE",
1048
+ reason
1049
+ });
1050
+ sendLifecycle = void 0;
1051
+ lifecycleCleanup?.();
1052
+ lifecycleCleanup = void 0;
1053
+ runtime?.release();
1054
+ runtime = void 0;
1055
+ try {
1056
+ deepsightService?.cleanup();
1057
+ } catch {}
1058
+ deepsightService = void 0;
1059
+ deepsightState = "idle";
1060
+ committedPreview = void 0;
1061
+ pendingAutoPreview = void 0;
1062
+ recording = {};
1063
+ };
1064
+ const initializeDeepsight = () => {
1065
+ if (deepsightState === "ready") {
1066
+ sendBack({ type: "PROTECTED_DEEPSIGHT_READY" });
1067
+ return;
1068
+ }
1069
+ if (deepsightState === "initializing") return;
1070
+ deepsightState = "initializing";
1071
+ const input = getControllerInput();
1072
+ const ownerGeneration = generation;
1073
+ options.initializeDeepsight({
1074
+ ds: input.config.ds,
1075
+ storage: input.dependencies.storage
1076
+ }).then((service) => {
1077
+ if (!active || generation !== ownerGeneration) {
1078
+ try {
1079
+ service.cleanup();
1080
+ } catch {}
1081
+ return;
1082
+ }
1083
+ deepsightService = service;
1084
+ deepsightState = "ready";
1085
+ runtime?.setDeepsightService(service);
1086
+ sendBack({ type: "PROTECTED_DEEPSIGHT_READY" });
1087
+ const preview = pendingAutoPreview;
1088
+ pendingAutoPreview = void 0;
1089
+ if (preview) queueMicrotask(() => {
1090
+ if (active && generation === ownerGeneration) sendBack({
1091
+ type: "PROTECTED_NATIVE_AUTO_CAPTURE",
1092
+ preview
1093
+ });
1094
+ });
1095
+ }, () => {
1096
+ if (!active || generation !== ownerGeneration) return;
1097
+ deepsightState = "failed";
1098
+ sendBack({ type: "PROTECTED_DEEPSIGHT_FAILED" });
1099
+ }).finally(() => {
1100
+ if (generation === ownerGeneration) {}
1101
+ });
1102
+ };
1103
+ const finalizeLocalCapture = async (owner, ownerGeneration) => {
1104
+ const preview = committedPreview;
1105
+ if (!preview) throw new Error("selfieCaptureOnly: no captured image");
1106
+ let metadata = "";
1107
+ try {
1108
+ metadata = deepsightService?.getMetadata() ?? "";
1109
+ } catch {
1110
+ metadata = "";
1111
+ }
1112
+ const canvas = new IncodeCanvas(preview);
1113
+ const blobData = canvas.getBlobData();
1114
+ if (!blobData) throw new Error("selfieCaptureOnly: failed to build image blob");
1115
+ const result = {
1116
+ imageBase64: canvas.getBase64Image() ?? "",
1117
+ blob: blobData.blob,
1118
+ url: blobData.url,
1119
+ metadata,
1120
+ videoBase64: owner.takeCaptureOnlyVideo()
1121
+ };
1122
+ if (active && runtime === owner && generation === ownerGeneration) {
1123
+ sendBack({
1124
+ type: "PROTECTED_LOCAL_DONE",
1125
+ attemptId: owner.attemptId,
1126
+ result
1127
+ });
1128
+ logDiagnostic("upload-complete");
1129
+ }
1130
+ };
1131
+ const forwardLifecycleEvent = (event, owner, ownerGeneration) => {
1132
+ if (!active || runtime !== owner || generation !== ownerGeneration) return;
1133
+ switch (event.type) {
1134
+ case "PROTECTED_ATTEMPT_READY":
1135
+ logDiagnostic("camera-ready");
1136
+ sendBack({
1137
+ ...event,
1138
+ usingBackCamera: owner.usingBackCamera
1139
+ });
1140
+ return;
1141
+ case "PROTECTED_AUTO_COMMITTED":
1142
+ case "PROTECTED_MANUAL_COMMITTED":
1143
+ logDiagnostic("capture-selected", { captureKind: event.type === "PROTECTED_AUTO_COMMITTED" ? "auto" : "manual" });
1144
+ committedPreview = event.preview;
1145
+ sendBack(event);
1146
+ return;
1147
+ case "PROTECTED_ATTEMPT_FINALIZED":
1148
+ logDiagnostic("attempt-finalized");
1149
+ recording = event.recording;
1150
+ sendBack(event);
1151
+ return;
1152
+ case "PROTECTED_UPLOAD_DONE":
1153
+ if (event.result.kind === "id") {
1154
+ sendBack({
1155
+ type: "PROTECTED_ATTEMPT_FAILED",
1156
+ attemptId: event.attemptId,
1157
+ failure: {
1158
+ stage: "upload",
1159
+ code: "protected-attempt-unexpected-result"
1160
+ }
1161
+ });
1162
+ return;
1163
+ }
1164
+ sendBack({
1165
+ type: "PROTECTED_UPLOAD_MAPPED",
1166
+ attemptId: event.attemptId,
1167
+ response: owner.mapProtectedResult(event.result)
1168
+ });
1169
+ logDiagnostic("upload-complete");
1170
+ return;
1171
+ case "PROTECTED_ATTEMPT_FAILED":
1172
+ logDiagnostic("attempt-failed", {
1173
+ failureStage: event.failure.stage,
1174
+ failureCode: event.failure.code
1175
+ });
1176
+ sendBack(event);
1177
+ return;
1178
+ default: sendBack(event);
1179
+ }
1180
+ };
1181
+ const start = (visible) => {
1182
+ if (lifecycleCleanup) {
1183
+ sendLifecycle?.({ type: visible ? "FOREGROUND" : "BACKGROUND" });
1184
+ return;
1185
+ }
1186
+ const owner = ensureRuntime();
1187
+ diagnosticAttempt += 1;
1188
+ diagnosticStartedAt = getTimestamp();
1189
+ logDiagnostic("attempt-start");
1190
+ const ownerGeneration = generation;
1191
+ signalCleanup = owner.subscribeSignals((signal) => {
1192
+ if (!active || runtime !== owner || generation !== ownerGeneration) return;
1193
+ if (signal.type === "detection") {
1194
+ sendBack({
1195
+ type: "DETECTION_UPDATE",
1196
+ status: signal.status
1197
+ });
1198
+ return;
1199
+ }
1200
+ if (deepsightState === "ready") sendBack({
1201
+ type: "PROTECTED_NATIVE_AUTO_CAPTURE",
1202
+ preview: signal.preview
1203
+ });
1204
+ else pendingAutoPreview ??= signal.preview;
1205
+ });
1206
+ lifecycleCleanup = runProtectedAttempt({
1207
+ input: owner.toActorInput((timing) => {
1208
+ logDiagnostic("camera-startup", timing);
1209
+ }),
1210
+ sendBack: (event) => forwardLifecycleEvent(event, owner, ownerGeneration),
1211
+ receive: (listener) => {
1212
+ sendLifecycle = listener;
1213
+ }
1214
+ });
1215
+ sendLifecycle?.({ type: visible ? "FOREGROUND" : "BACKGROUND" });
1216
+ };
1217
+ receive((command) => {
1218
+ if (command.type === "BIND_PROTECTED_FACE_CONTROLLER") {
1219
+ controllerInput ??= command.input;
1220
+ return;
1221
+ }
1222
+ switch (command.type) {
1223
+ case "INITIALIZE_DEEPSIGHT":
1224
+ initializeDeepsight();
1225
+ return;
1226
+ case "PRE_ACQUIRE": {
1227
+ const owner = ensureRuntime();
1228
+ const ownerGeneration = generation;
1229
+ owner.preAcquire().then(() => {
1230
+ if (active && runtime === owner && generation === ownerGeneration) sendBack({
1231
+ type: "PROTECTED_PRE_ACQUIRE_DONE",
1232
+ usingBackCamera: owner.usingBackCamera
1233
+ });
1234
+ }, (error) => {
1235
+ if (active && runtime === owner && generation === ownerGeneration) sendBack({
1236
+ type: "PROTECTED_PRE_ACQUIRE_FAILED",
1237
+ error
1238
+ });
1239
+ });
1240
+ return;
1241
+ }
1242
+ case "START":
1243
+ start(command.visible);
1244
+ return;
1245
+ case "AUTO_CAPTURED":
1246
+ case "MANUAL_CAPTURE":
1247
+ case "FINALIZE":
1248
+ if (deepsightState !== "ready") return;
1249
+ sendLifecycle?.(command);
1250
+ return;
1251
+ case "BACKGROUND":
1252
+ case "FOREGROUND":
1253
+ sendLifecycle?.(command);
1254
+ return;
1255
+ case "UPLOAD": {
1256
+ const owner = runtime;
1257
+ if (!owner) return;
1258
+ logDiagnostic("upload-start");
1259
+ if (options.delivery === "protected") {
1260
+ sendLifecycle?.(owner.createUploadCommand(recording.recordingId));
1261
+ return;
1262
+ }
1263
+ finalizeLocalCapture(owner, generation).catch(() => {
1264
+ if (active && runtime === owner) sendBack({
1265
+ type: "PROTECTED_ATTEMPT_FAILED",
1266
+ attemptId: owner.attemptId,
1267
+ failure: {
1268
+ stage: "upload",
1269
+ code: "protected-attempt-local-finalize-failed"
1270
+ }
1271
+ });
1272
+ });
1273
+ return;
1274
+ }
1275
+ case "RESET":
1276
+ releaseCurrent("retry");
1277
+ return;
1278
+ case "RELEASE": releaseCurrent(command.reason);
1279
+ }
1280
+ });
1281
+ return () => {
1282
+ active = false;
1283
+ releaseCurrent("externalStop");
1284
+ };
1285
+ });
1286
+ }
1287
+ //#endregion
1288
+ //#region src/internal/faceCapture/protectedFaceComposition.ts
1289
+ /**
1290
+ * Private composition root for protected still-face variants. Provider
1291
+ * construction remains in Infra; the controller receives only capability
1292
+ * interfaces/factories and owns them in its callback closure.
1293
+ */
1294
+ function createDefaultProtectedFaceControllerActor(options) {
1295
+ return createProtectedFaceControllerActor({
1296
+ ...options,
1297
+ createCapabilities: createProtectedFaceCaptureCapabilities,
1298
+ initializeDeepsight: initializeDeepsightSession
1299
+ });
1300
+ }
1301
+ //#endregion
626
1302
  //#region src/internal/faceCapture/faceCaptureSetup.ts
627
1303
  const getAttemptsFromConfig = (config) => {
628
1304
  return config.captureAttempts ?? config.numberOfAttempts ?? 3;
629
1305
  };
1306
+ /**
1307
+ * The protected face controller is invoked at the machine root, so a started
1308
+ * machine has it for its whole lifetime and every guarded send below behaves
1309
+ * like a plain `sendTo`. Harnesses that start the machine from a resolved
1310
+ * snapshot carry no children (the Storybook state stories seed managers that
1311
+ * way), and XState throws on a send to a missing actor, so each send checks
1312
+ * for the controller first.
1313
+ *
1314
+ * Only sends that run after the machine has started may use this guard. A
1315
+ * root `entry` action runs inside the initial transition, before the actor
1316
+ * has a committed snapshot; XState delivers a plain `sendTo` from there
1317
+ * through its deferred-actor path, whereas this check cannot see the child
1318
+ * yet and would skip the send.
1319
+ */
1320
+ function isProtectedFaceControllerRunning(self) {
1321
+ return self.getSnapshot()?.children?.["protectedFaceController"] !== void 0;
1322
+ }
630
1323
  const faceCaptureMachine = setup({
631
1324
  types: {
632
1325
  context: {},
@@ -640,46 +1333,9 @@ const faceCaptureMachine = setup({
640
1333
  requestPermission: fromPromise(async ({ input }) => {
641
1334
  return invokeRequestPermissionActor(input);
642
1335
  }),
643
- initializeCamera: fromPromise(async ({ input }) => {
644
- return initializeCamera({
645
- config: input.config,
646
- deepsightService: input.deepsightService
647
- });
648
- }),
649
- runDetection: fromCallback(({ input, sendBack }) => {
650
- if (!input.frameCapturer || !input.provider) {
651
- sendBack({
652
- type: "DETECTION_UPDATE",
653
- status: "error"
654
- });
655
- return () => {};
656
- }
657
- if (input.manualCaptureTriggered) {
658
- sendBack({
659
- type: "DETECTION_UPDATE",
660
- status: "manualCapture"
661
- });
662
- return () => {};
663
- }
664
- const { cleanup, reset } = startDetection({
665
- config: input.config,
666
- capturer: input.frameCapturer,
667
- onUpdate: (status) => sendBack({
668
- type: "DETECTION_UPDATE",
669
- status
670
- }),
671
- onSuccess: (canvas, faceCoordinates) => sendBack({
672
- type: "DETECTION_SUCCESS",
673
- canvas,
674
- faceCoordinates
675
- }),
676
- provider: input.provider
677
- });
678
- sendBack({
679
- type: "DETECTION_RESET_READY",
680
- reset
681
- });
682
- return cleanup;
1336
+ protectedFaceController: createDefaultProtectedFaceControllerActor({
1337
+ target: PROTECTED_CAPTURE_TARGET.selfie,
1338
+ delivery: "protected"
683
1339
  }),
684
1340
  runAvatar: fromCallback(({ input, sendBack }) => {
685
1341
  const { obfuscateWithAvatar, avatarVariant } = concealmentToAvatar(input.config.selfieConcealmentOption);
@@ -713,115 +1369,61 @@ const faceCaptureMachine = setup({
713
1369
  handle?.stop();
714
1370
  };
715
1371
  }),
716
- initializeDeepsightSession: fromPromise(async ({ input }) => {
717
- return await initializeDeepsightSession({
718
- ds: input.ds,
719
- storage: input.storage
720
- });
721
- }),
722
- startRecording: fromPromise(async ({ input }) => {
723
- if (!input.stream) return input.recordingService;
724
- const wasmUtil = await input.dependencies.getWasmUtil();
725
- const sessionToken = getToken();
726
- const service = input.recordingService ?? createRecordingService({
727
- config: input.config,
728
- wasmUtil,
729
- sessionToken
730
- });
731
- if (service) await service.start(input.stream);
732
- return service;
733
- }),
734
- checkVirtualCamera: fromPromise(async ({ input }) => {
735
- if (!input.deepsightService || !input.stream) return false;
736
- const videoTrack = input.stream.getVideoTracks()[0];
737
- if (!videoTrack) return false;
738
- return input.deepsightService.checkVirtualCamera(videoTrack);
739
- }),
740
1372
  manualUploadMachine: manualFaceUploadMachine,
741
1373
  prepareFaceUpload: fromPromise(async () => {
742
1374
  throw new Error("prepareFaceUpload must be provided by variant");
743
1375
  }),
744
- uploadFace: fromPromise(async () => {
745
- throw new Error("uploadFace must be provided by variant");
746
- }),
1376
+ uploadFace: fromPromise(async () => new Promise(() => {})),
747
1377
  processFace: fromPromise(async () => {
748
1378
  throw new Error("processFace must be provided by variant");
749
1379
  })
750
1380
  },
751
1381
  actions: {
752
- stopMediaStream: assign(({ context }) => {
753
- context.frameCapturer?.dispose();
754
- if (context.stream) stopStream(context.stream);
755
- context.provider?.dispose();
1382
+ bindProtectedFaceController: sendTo("protectedFaceController", ({ context }) => ({
1383
+ type: "BIND_PROTECTED_FACE_CONTROLLER",
1384
+ input: {
1385
+ config: context.config,
1386
+ dependencies: context.dependencies,
1387
+ authHint: context.authHint
1388
+ }
1389
+ })),
1390
+ stopMediaStream: assign(() => {
756
1391
  return {
757
1392
  stream: void 0,
758
- provider: void 0,
759
- frameCapturer: void 0,
760
1393
  avatarCanvas: void 0,
761
1394
  usingBackCamera: false
762
1395
  };
763
1396
  }),
764
- setStreamAndCapturer: assign({
765
- stream: ({ event }) => {
766
- if ("output" in event) return event.output.stream;
767
- },
768
- provider: ({ event }) => {
769
- if ("output" in event) return event.output.provider;
770
- },
771
- frameCapturer: ({ event }) => {
772
- if ("output" in event) return new StreamCanvasCapture(event.output.stream);
773
- },
774
- usingBackCamera: ({ event }) => {
775
- if ("output" in event) return event.output.usingBackCamera;
776
- return false;
777
- }
778
- }),
1397
+ setCameraPreAcquired: assign({ usingBackCamera: ({ event }) => event.usingBackCamera }),
779
1398
  trackTutorial: () => void 0,
780
1399
  trackContinue: () => {},
781
- resetContext: assign(({ context }) => ({
782
- stream: void 0,
783
- provider: void 0,
784
- frameCapturer: void 0,
785
- usingBackCamera: false,
786
- error: void 0,
787
- detectionStatus: "idle",
788
- capturedImage: void 0,
789
- faceCoordinates: void 0,
790
- uploadResponse: void 0,
791
- processResponse: void 0,
792
- recordingService: void 0,
793
- attemptsRemaining: getAttemptsFromConfig(context.config),
794
- uploadError: void 0,
795
- permissionResult: void 0,
796
- resetDetection: void 0,
797
- deepsightService: void 0,
798
- manualCaptureTriggered: false,
799
- captureOnlyResult: void 0,
800
- avatarCanvas: void 0
801
- })),
802
- resetDetection: ({ context }) => {
803
- context.resetDetection?.();
804
- },
805
- captureImage: assign({ capturedImage: ({ context }) => {
806
- if (context.capturedImage) return context.capturedImage;
807
- return context.frameCapturer?.getLatestCanvas() ?? void 0;
808
- } }),
809
- captureLatestFrame: assign({ capturedImage: ({ context }) => {
810
- return context.frameCapturer?.getLatestCanvas() ?? void 0;
811
- } }),
1400
+ resetContext: assign(({ context }) => {
1401
+ return {
1402
+ stream: void 0,
1403
+ usingBackCamera: false,
1404
+ error: void 0,
1405
+ detectionStatus: "idle",
1406
+ capturedImage: void 0,
1407
+ faceCoordinates: void 0,
1408
+ uploadResponse: void 0,
1409
+ processResponse: void 0,
1410
+ attemptsRemaining: getAttemptsFromConfig(context.config),
1411
+ uploadError: void 0,
1412
+ permissionResult: void 0,
1413
+ deepsightReady: false,
1414
+ manualCaptureTriggered: false,
1415
+ captureOnlyResult: void 0,
1416
+ avatarCanvas: void 0
1417
+ };
1418
+ }),
812
1419
  clearUploadFailure: assign({
813
1420
  uploadError: () => void 0,
814
1421
  detectionStatus: () => "idle",
815
1422
  capturedImage: () => void 0
816
1423
  }),
817
- prepareStreamForRetry: assign(({ context }) => {
818
- context.frameCapturer?.dispose();
819
- if (context.stream) stopStream(context.stream);
820
- context.provider?.dispose();
1424
+ clearProtectedAttempt: assign(() => {
821
1425
  return {
822
1426
  stream: void 0,
823
- provider: void 0,
824
- frameCapturer: void 0,
825
1427
  avatarCanvas: void 0,
826
1428
  usingBackCamera: false
827
1429
  };
@@ -829,25 +1431,15 @@ const faceCaptureMachine = setup({
829
1431
  decrementAttemptsRemaining: assign(({ context }) => ({ attemptsRemaining: context.attemptsRemaining - 1 })),
830
1432
  setUploadErrorFromUploadValidation: assign({ uploadError: () => FACE_ERROR_CODES.SERVER }),
831
1433
  setTerminalError: assign({ error: () => "Authentication failed" }),
832
- clearRecordingService: assign({ recordingService: () => void 0 }),
833
- stopRecordingService: ({ context }) => {
834
- context.recordingService?.stop().catch(() => {
835
- console.warn("[faceCapture] Recording finalization failed");
836
- });
837
- },
838
- cleanup: ({ context }) => {
839
- context.deepsightService?.cleanup();
840
- },
1434
+ cleanup: () => void 0,
841
1435
  setPermissionResultFromEvent: assign({ permissionResult: ({ event }) => event.output }),
842
1436
  setPermissionDenied: assign({ permissionResult: () => "denied" }),
843
1437
  setPermissionPrompt: assign({ permissionResult: () => "prompt" }),
844
1438
  setPermissionRefresh: assign({ permissionResult: () => "refresh" }),
845
- setDeepsightServiceFromEvent: assign({ deepsightService: ({ event }) => event.output }),
1439
+ setDeepsightReady: assign({ deepsightReady: () => true }),
1440
+ setDeepsightNotReady: assign({ deepsightReady: () => false }),
846
1441
  setErrorFromEvent: assign({ error: ({ event }) => String(event.error) }),
847
1442
  setDetectionStatusDetecting: assign({ detectionStatus: ({ context }) => context.manualCaptureTriggered ? "manualCapture" : "detecting" }),
848
- setRecordingServiceFromEvent: assign({ recordingService: ({ context, event }) => {
849
- return event.output ?? context.recordingService;
850
- } }),
851
1443
  setDetectionStatusFromEvent: assign({ detectionStatus: ({ event }) => event.status }),
852
1444
  setManualCaptureTriggered: assign({ manualCaptureTriggered: ({ context, event }) => {
853
1445
  const status = event.status;
@@ -855,11 +1447,27 @@ const faceCaptureMachine = setup({
855
1447
  } }),
856
1448
  setAvatarCanvas: assign({ avatarCanvas: ({ event }) => event.canvas }),
857
1449
  clearAvatarCanvas: assign({ avatarCanvas: () => void 0 }),
858
- setResetDetectionFromEvent: assign({ resetDetection: ({ event }) => event.reset }),
859
1450
  setCapturedImageFromEvent: assign({
860
1451
  capturedImage: ({ event }) => event.canvas,
861
1452
  faceCoordinates: ({ event }) => event.faceCoordinates
862
1453
  }),
1454
+ setProtectedAttemptReady: assign({
1455
+ stream: ({ event }) => event.displayStream,
1456
+ usingBackCamera: ({ event }) => event.usingBackCamera
1457
+ }),
1458
+ setProtectedCommittedPreview: assign({
1459
+ capturedImage: ({ event }) => new IncodeCanvas(event.preview),
1460
+ faceCoordinates: () => void 0,
1461
+ detectionStatus: () => "success"
1462
+ }),
1463
+ setProtectedFinalization: assign({
1464
+ uploadRecordingId: ({ event }) => event.recording.recordingId ?? null,
1465
+ stream: ({ context, event }) => event.displayStream ?? context.stream
1466
+ }),
1467
+ setProtectedUploadResponse: assign({ uploadResponse: ({ event }) => event.response }),
1468
+ setProtectedLocalResult: assign({ captureOnlyResult: ({ event }) => event.result }),
1469
+ setProtectedFailure: assign({ error: ({ event }) => event.failure.code }),
1470
+ setProtectedVisibility: assign({ protectedVisible: ({ event }) => event.visible }),
863
1471
  setUploadPreparationFromEvent: assign({
864
1472
  encryptedBase64Image: ({ event }) => event.output.encryptedBase64Image,
865
1473
  uploadRecordingId: ({ event }) => event.output.recordingId
@@ -889,7 +1497,56 @@ const faceCaptureMachine = setup({
889
1497
  releaseFaceAvatarWarmup();
890
1498
  },
891
1499
  noOp: () => void 0,
892
- forwardToManualUpload: sendTo("manualUpload", ({ event }) => event)
1500
+ forwardToManualUpload: sendTo("manualUpload", ({ event }) => event),
1501
+ sendProtectedPreAcquire: enqueueActions(({ enqueue, self }) => {
1502
+ if (!isProtectedFaceControllerRunning(self)) return;
1503
+ enqueue.sendTo("protectedFaceController", { type: "PRE_ACQUIRE" });
1504
+ }),
1505
+ startProtectedAttempt: enqueueActions(({ enqueue, self, context }) => {
1506
+ if (!isProtectedFaceControllerRunning(self)) return;
1507
+ enqueue.sendTo("protectedFaceController", {
1508
+ type: "START",
1509
+ visible: context.protectedVisible
1510
+ });
1511
+ }),
1512
+ initializeProtectedDeepsight: enqueueActions(({ enqueue, self }) => {
1513
+ if (!isProtectedFaceControllerRunning(self)) return;
1514
+ enqueue.sendTo("protectedFaceController", { type: "INITIALIZE_DEEPSIGHT" });
1515
+ }),
1516
+ resetProtectedController: enqueueActions(({ enqueue, self }) => {
1517
+ if (!isProtectedFaceControllerRunning(self)) return;
1518
+ enqueue.sendTo("protectedFaceController", { type: "RESET" });
1519
+ }),
1520
+ sendProtectedAutoCapture: enqueueActions(({ enqueue, self, event }) => {
1521
+ if (!isProtectedFaceControllerRunning(self)) return;
1522
+ enqueue.sendTo("protectedFaceController", {
1523
+ type: "AUTO_CAPTURED",
1524
+ preview: event.preview
1525
+ });
1526
+ }),
1527
+ sendProtectedManualCapture: enqueueActions(({ enqueue, self }) => {
1528
+ if (!isProtectedFaceControllerRunning(self)) return;
1529
+ enqueue.sendTo("protectedFaceController", { type: "MANUAL_CAPTURE" });
1530
+ }),
1531
+ sendProtectedFinalize: enqueueActions(({ enqueue, self }) => {
1532
+ if (!isProtectedFaceControllerRunning(self)) return;
1533
+ enqueue.sendTo("protectedFaceController", { type: "FINALIZE" });
1534
+ }),
1535
+ sendProtectedUploadIfNeeded: enqueueActions(({ enqueue, self }) => {
1536
+ if (!isProtectedFaceControllerRunning(self)) return;
1537
+ enqueue.sendTo("protectedFaceController", { type: "UPLOAD" });
1538
+ }),
1539
+ sendProtectedVisibility: enqueueActions(({ enqueue, self, event }) => {
1540
+ if (!isProtectedFaceControllerRunning(self)) return;
1541
+ enqueue.sendTo("protectedFaceController", { type: event.visible ? "FOREGROUND" : "BACKGROUND" });
1542
+ }),
1543
+ releaseProtectedAttempt: enqueueActions(({ enqueue, self, event }) => {
1544
+ if (!isProtectedFaceControllerRunning(self)) return;
1545
+ enqueue.sendTo("protectedFaceController", {
1546
+ type: "RELEASE",
1547
+ reason: event.reason ?? "externalStop"
1548
+ });
1549
+ })
893
1550
  },
894
1551
  guards: {
895
1552
  hasShowTutorial: ({ context }) => context.config.showTutorial,
@@ -914,9 +1571,12 @@ const faceCaptureMachine = setup({
914
1571
  return false;
915
1572
  },
916
1573
  hasStream: ({ context }) => context.stream !== void 0,
917
- isCameraAndDeepsightReady: ({ context }) => context.stream !== void 0 && context.deepsightService !== void 0,
1574
+ isCameraAndDeepsightReady: ({ context }) => context.stream !== void 0 && context.deepsightReady,
918
1575
  hasAttemptsRemaining: ({ context }) => context.attemptsRemaining > 0,
919
1576
  hasCapturedImage: ({ context }) => context.capturedImage !== void 0,
1577
+ canCommitProtectedManual: ({ context }) => context.manualCaptureTriggered && context.config.onDeviceFaceResultsSubmissionEnabled !== true,
1578
+ isProtectedManualRefusal: ({ event }) => event.failure.stage === "manualCommit",
1579
+ isProtectedUploadFailure: ({ event }) => event.failure.stage === "upload",
920
1580
  hasUploadValidationError: () => false,
921
1581
  isTerminalUploadError: () => false,
922
1582
  isNoAttemptsTerminal: () => false
@@ -924,13 +1584,12 @@ const faceCaptureMachine = setup({
924
1584
  }).createMachine({
925
1585
  id: "faceCapture",
926
1586
  initial: "idle",
1587
+ entry: "bindProtectedFaceController",
927
1588
  context: ({ input }) => ({
928
1589
  config: input.config,
929
1590
  dependencies: input.dependencies,
930
1591
  authHint: input.authHint,
931
1592
  stream: void 0,
932
- provider: void 0,
933
- frameCapturer: void 0,
934
1593
  usingBackCamera: false,
935
1594
  error: void 0,
936
1595
  detectionStatus: "idle",
@@ -938,20 +1597,28 @@ const faceCaptureMachine = setup({
938
1597
  faceCoordinates: void 0,
939
1598
  uploadResponse: void 0,
940
1599
  processResponse: void 0,
941
- recordingService: void 0,
942
1600
  attemptsRemaining: getAttemptsFromConfig(input.config),
943
1601
  uploadError: void 0,
944
1602
  permissionResult: void 0,
945
- resetDetection: void 0,
946
- deepsightService: void 0,
1603
+ deepsightReady: false,
947
1604
  encryptedBase64Image: void 0,
948
1605
  uploadRecordingId: void 0,
949
1606
  manualCaptureTriggered: false,
950
1607
  captureOnlyResult: void 0,
951
1608
  avatarCanvas: void 0,
952
- faceFeed: void 0
1609
+ faceFeed: void 0,
1610
+ protectedVisible: true
953
1611
  }),
954
- on: { QUIT: { target: "#faceCapture.closed" } },
1612
+ invoke: {
1613
+ id: "protectedFaceController",
1614
+ src: "protectedFaceController"
1615
+ },
1616
+ on: {
1617
+ QUIT: { target: "#faceCapture.closed" },
1618
+ PROTECTED_VISIBILITY: { actions: "setProtectedVisibility" },
1619
+ PROTECTED_DEEPSIGHT_READY: { actions: "setDeepsightReady" },
1620
+ PROTECTED_DEEPSIGHT_FAILED: { actions: "setDeepsightNotReady" }
1621
+ },
955
1622
  states: {
956
1623
  idle: { on: { LOAD: [
957
1624
  {
@@ -965,8 +1632,12 @@ const faceCaptureMachine = setup({
965
1632
  { target: "loading" }
966
1633
  ] } },
967
1634
  loading: {
968
- entry: ["preloadRecordingProvider", "warmAvatarProvider"],
969
- invoke: [{
1635
+ entry: [
1636
+ "preloadRecordingProvider",
1637
+ "warmAvatarProvider",
1638
+ "initializeProtectedDeepsight"
1639
+ ],
1640
+ invoke: {
970
1641
  id: "checkPermissionLoading",
971
1642
  src: "checkPermission",
972
1643
  onDone: [{
@@ -977,16 +1648,7 @@ const faceCaptureMachine = setup({
977
1648
  target: "permissions",
978
1649
  actions: "setPermissionResultFromEvent"
979
1650
  }]
980
- }, {
981
- id: "loadingInitDeepsight",
982
- src: "initializeDeepsightSession",
983
- input: ({ context }) => ({
984
- ds: context.config.ds,
985
- storage: context.dependencies.storage
986
- }),
987
- onDone: { actions: "setDeepsightServiceFromEvent" },
988
- onError: { actions: "noOp" }
989
- }]
1651
+ }
990
1652
  },
991
1653
  tutorial: {
992
1654
  initial: "checkingPermission",
@@ -1018,40 +1680,36 @@ const faceCaptureMachine = setup({
1018
1680
  cameraInit: {
1019
1681
  initial: "initializingDeepsight",
1020
1682
  states: {
1021
- initializingDeepsight: { invoke: {
1022
- id: "tutorialInitDeepsight",
1023
- src: "initializeDeepsightSession",
1024
- input: ({ context }) => ({
1025
- ds: context.config.ds,
1026
- storage: context.dependencies.storage
1027
- }),
1028
- onDone: {
1029
- target: "initializingStream",
1030
- actions: "setDeepsightServiceFromEvent"
1031
- },
1032
- onError: { target: "#faceCapture.tutorial.ready" }
1033
- } },
1034
- initializingStream: { invoke: {
1035
- id: "tutorialInitCamera",
1036
- src: "initializeCamera",
1037
- input: ({ context }) => ({
1038
- config: context.config,
1039
- dependencies: context.dependencies,
1040
- deepsightService: context.deepsightService
1041
- }),
1042
- onDone: {
1043
- target: "ready",
1044
- actions: "setStreamAndCapturer"
1045
- },
1046
- onError: [{
1047
- target: "#faceCapture.tutorial.ready",
1048
- guard: "isPermissionDeniedError",
1049
- actions: "setPermissionDenied"
1050
- }, {
1051
- target: "#faceCapture.tutorial.ready",
1052
- actions: "setErrorFromEvent"
1053
- }]
1054
- } },
1683
+ initializingDeepsight: {
1684
+ entry: "initializeProtectedDeepsight",
1685
+ on: {
1686
+ PROTECTED_DEEPSIGHT_READY: {
1687
+ target: "initializingStream",
1688
+ actions: "setDeepsightReady"
1689
+ },
1690
+ PROTECTED_DEEPSIGHT_FAILED: {
1691
+ target: "#faceCapture.tutorial.ready",
1692
+ actions: "setDeepsightNotReady"
1693
+ }
1694
+ }
1695
+ },
1696
+ initializingStream: {
1697
+ entry: "sendProtectedPreAcquire",
1698
+ on: {
1699
+ PROTECTED_PRE_ACQUIRE_DONE: {
1700
+ target: "ready",
1701
+ actions: "setCameraPreAcquired"
1702
+ },
1703
+ PROTECTED_PRE_ACQUIRE_FAILED: [{
1704
+ target: "#faceCapture.tutorial.ready",
1705
+ guard: "isPermissionDeniedError",
1706
+ actions: "setPermissionDenied"
1707
+ }, {
1708
+ target: "#faceCapture.tutorial.ready",
1709
+ actions: "setErrorFromEvent"
1710
+ }]
1711
+ }
1712
+ },
1055
1713
  ready: { type: "final" }
1056
1714
  }
1057
1715
  },
@@ -1073,21 +1731,21 @@ const faceCaptureMachine = setup({
1073
1731
  states: {
1074
1732
  idle: { always: [{
1075
1733
  target: "initializingDeepsight",
1076
- guard: ({ context }) => context.deepsightService === void 0
1734
+ guard: ({ context }) => !context.deepsightReady
1077
1735
  }, { target: "readyForNext" }] },
1078
- initializingDeepsight: { invoke: {
1079
- id: "initializeDeepsightTutorial",
1080
- src: "initializeDeepsightSession",
1081
- input: ({ context }) => ({
1082
- ds: context.config.ds,
1083
- storage: context.dependencies.storage
1084
- }),
1085
- onDone: {
1086
- target: "readyForNext",
1087
- actions: "setDeepsightServiceFromEvent"
1088
- },
1089
- onError: { target: "readyForNext" }
1090
- } },
1736
+ initializingDeepsight: {
1737
+ entry: "initializeProtectedDeepsight",
1738
+ on: {
1739
+ PROTECTED_DEEPSIGHT_READY: {
1740
+ target: "readyForNext",
1741
+ actions: "setDeepsightReady"
1742
+ },
1743
+ PROTECTED_DEEPSIGHT_FAILED: {
1744
+ target: "readyForNext",
1745
+ actions: "setDeepsightNotReady"
1746
+ }
1747
+ }
1748
+ },
1091
1749
  readyForNext: { on: { NEXT_STEP: {
1092
1750
  target: "#faceCapture.tutorial.waitingForPermission",
1093
1751
  actions: "trackContinue"
@@ -1117,26 +1775,30 @@ const faceCaptureMachine = setup({
1117
1775
  }
1118
1776
  },
1119
1777
  permissions: {
1120
- entry: ["preloadRecordingProvider", "warmAvatarProvider"],
1778
+ entry: [
1779
+ "preloadRecordingProvider",
1780
+ "warmAvatarProvider",
1781
+ "initializeProtectedDeepsight"
1782
+ ],
1121
1783
  initial: "checkingDeepsight",
1122
1784
  states: {
1123
1785
  checkingDeepsight: { always: [{
1124
1786
  target: "initializingDeepsight",
1125
- guard: ({ context }) => context.deepsightService === void 0
1787
+ guard: ({ context }) => !context.deepsightReady
1126
1788
  }, { target: "idle" }] },
1127
- initializingDeepsight: { invoke: {
1128
- id: "initializeDeepsightPerms",
1129
- src: "initializeDeepsightSession",
1130
- input: ({ context }) => ({
1131
- ds: context.config.ds,
1132
- storage: context.dependencies.storage
1133
- }),
1134
- onDone: {
1135
- target: "idle",
1136
- actions: "setDeepsightServiceFromEvent"
1137
- },
1138
- onError: { target: "idle" }
1139
- } },
1789
+ initializingDeepsight: {
1790
+ entry: "initializeProtectedDeepsight",
1791
+ on: {
1792
+ PROTECTED_DEEPSIGHT_READY: {
1793
+ target: "idle",
1794
+ actions: "setDeepsightReady"
1795
+ },
1796
+ PROTECTED_DEEPSIGHT_FAILED: {
1797
+ target: "idle",
1798
+ actions: "setDeepsightNotReady"
1799
+ }
1800
+ }
1801
+ },
1140
1802
  idle: {
1141
1803
  invoke: {
1142
1804
  id: "checkPermissionIdle",
@@ -1210,172 +1872,117 @@ const faceCaptureMachine = setup({
1210
1872
  }
1211
1873
  },
1212
1874
  capture: {
1213
- entry: ["preloadRecordingProvider", "warmAvatarProvider"],
1875
+ entry: [
1876
+ "preloadRecordingProvider",
1877
+ "warmAvatarProvider",
1878
+ "initializeProtectedDeepsight",
1879
+ "startProtectedAttempt"
1880
+ ],
1214
1881
  initial: "checkingDeepsight",
1215
1882
  exit: [
1883
+ "releaseProtectedAttempt",
1216
1884
  "stopMediaStream",
1217
- "stopRecordingService",
1218
- "clearRecordingService",
1219
1885
  "cleanup"
1220
1886
  ],
1221
- states: {
1222
- checkingDeepsight: { always: [{
1223
- target: "initializingDeepsight",
1224
- guard: ({ context }) => context.deepsightService === void 0
1225
- }, { target: "checkingStream" }] },
1226
- initializingDeepsight: { invoke: {
1227
- id: "initializeDeepsightCapture",
1228
- src: "initializeDeepsightSession",
1229
- input: ({ context }) => ({
1230
- ds: context.config.ds,
1231
- storage: context.dependencies.storage
1232
- }),
1233
- onDone: {
1234
- target: "checkingStream",
1235
- actions: ["setDeepsightServiceFromEvent"]
1236
- },
1237
- onError: { target: "#faceCapture.permissions" }
1238
- } },
1239
- checkingStream: { always: [
1887
+ on: {
1888
+ PROTECTED_ATTEMPT_READY: { actions: "setProtectedAttemptReady" },
1889
+ PROTECTED_VISIBILITY: { actions: ["setProtectedVisibility", "sendProtectedVisibility"] },
1890
+ PROTECTED_APPLY_VISIBILITY: { actions: "sendProtectedVisibility" },
1891
+ PROTECTED_ATTEMPT_FAILED: [
1240
1892
  {
1241
- target: "initializingDeepsight",
1242
- guard: ({ context }) => context.deepsightService === void 0
1893
+ target: ".detecting",
1894
+ guard: "isProtectedManualRefusal"
1243
1895
  },
1244
1896
  {
1245
- target: "detecting",
1246
- guard: "hasStream"
1247
- },
1248
- { target: "initializing" }
1249
- ] },
1250
- initializing: { invoke: {
1251
- id: "initializeCamera",
1252
- src: "initializeCamera",
1253
- input: ({ context }) => ({
1254
- config: context.config,
1255
- dependencies: context.dependencies,
1256
- deepsightService: context.deepsightService
1257
- }),
1258
- onDone: {
1259
- target: "detecting",
1260
- actions: ["setStreamAndCapturer"]
1897
+ target: ".uploadError",
1898
+ guard: "isProtectedUploadFailure",
1899
+ actions: "setServerErrorAndDecrement"
1261
1900
  },
1262
- onError: [{
1263
- target: "#faceCapture.permissions",
1264
- guard: "isPermissionDeniedError",
1265
- actions: "setPermissionDenied"
1266
- }, {
1901
+ {
1267
1902
  target: "#faceCapture.error",
1268
- actions: "setErrorFromEvent"
1269
- }]
1903
+ actions: "setProtectedFailure"
1904
+ }
1905
+ ],
1906
+ PROTECTED_ATTEMPT_RELEASED: { actions: "noOp" }
1907
+ },
1908
+ states: {
1909
+ checkingDeepsight: { always: [{
1910
+ target: "initializingDeepsight",
1911
+ guard: ({ context }) => !context.deepsightReady
1912
+ }, { target: "initializing" }] },
1913
+ initializingDeepsight: {
1914
+ entry: "initializeProtectedDeepsight",
1915
+ on: {
1916
+ PROTECTED_DEEPSIGHT_READY: {
1917
+ target: "initializing",
1918
+ actions: "setDeepsightReady"
1919
+ },
1920
+ PROTECTED_DEEPSIGHT_FAILED: {
1921
+ target: "#faceCapture.permissions",
1922
+ actions: "setDeepsightNotReady"
1923
+ }
1924
+ }
1925
+ },
1926
+ checkingStream: { always: "initializing" },
1927
+ initializing: { always: {
1928
+ target: "detecting",
1929
+ guard: "isCameraAndDeepsightReady"
1270
1930
  } },
1271
1931
  detecting: {
1272
1932
  entry: ["setDetectionStatusDetecting"],
1273
- invoke: [
1274
- {
1275
- id: "checkVirtualCamera",
1276
- src: "checkVirtualCamera",
1277
- input: ({ context }) => ({
1278
- stream: context.stream,
1279
- deepsightService: context.deepsightService
1280
- }),
1281
- onDone: [{
1282
- target: "#faceCapture.processing",
1283
- guard: ({ event }) => event.output === true,
1284
- actions: "sendLabelInspection"
1285
- }],
1286
- onError: { actions: "noOp" }
1287
- },
1288
- {
1289
- id: "startRecording",
1290
- src: "startRecording",
1291
- input: ({ context }) => ({
1292
- config: context.config,
1293
- dependencies: context.dependencies,
1294
- recordingService: context.recordingService,
1295
- stream: context.stream
1296
- }),
1297
- onDone: { actions: "setRecordingServiceFromEvent" },
1298
- onError: { actions: "noOp" }
1299
- },
1300
- {
1301
- id: "runDetection",
1302
- src: "runDetection",
1303
- input: ({ context }) => ({
1304
- frameCapturer: context.frameCapturer,
1305
- provider: context.provider,
1306
- config: context.config,
1307
- manualCaptureTriggered: context.manualCaptureTriggered,
1308
- faceFeed: context.faceFeed
1309
- })
1310
- },
1311
- {
1312
- id: "runAvatar",
1313
- src: "runAvatar",
1314
- input: ({ context }) => ({
1315
- stream: context.stream,
1316
- config: context.config,
1317
- faceFeed: context.faceFeed
1318
- })
1319
- }
1320
- ],
1933
+ invoke: {
1934
+ id: "runAvatar",
1935
+ src: "runAvatar",
1936
+ input: ({ context }) => ({
1937
+ stream: context.stream,
1938
+ config: context.config,
1939
+ faceFeed: context.faceFeed
1940
+ })
1941
+ },
1321
1942
  exit: ["clearAvatarCanvas"],
1322
1943
  on: {
1323
1944
  DETECTION_UPDATE: { actions: ["setDetectionStatusFromEvent", "setManualCaptureTriggered"] },
1324
1945
  AVATAR_READY: { actions: "setAvatarCanvas" },
1325
- DETECTION_RESET_READY: { actions: "setResetDetectionFromEvent" },
1326
- DETECTION_SUCCESS: {
1946
+ PROTECTED_NATIVE_AUTO_CAPTURE: { actions: "sendProtectedAutoCapture" },
1947
+ PROTECTED_AUTO_COMMITTED: {
1327
1948
  target: "capturing",
1328
- actions: "setCapturedImageFromEvent"
1949
+ actions: "setProtectedCommittedPreview"
1329
1950
  },
1330
- MANUAL_CAPTURE: { target: "capturingManual" }
1951
+ MANUAL_CAPTURE: {
1952
+ target: "capturingManual",
1953
+ guard: "canCommitProtectedManual",
1954
+ actions: "sendProtectedManualCapture"
1955
+ }
1331
1956
  }
1332
1957
  },
1333
1958
  capturing: {
1334
- entry: ["captureImage"],
1335
- always: [{
1959
+ entry: ["sendProtectedFinalize"],
1960
+ on: { PROTECTED_ATTEMPT_FINALIZED: {
1336
1961
  target: "preparingUpload",
1337
- guard: "hasCapturedImage"
1338
- }, {
1339
- target: "uploadError",
1340
- actions: "setServerErrorAndDecrement"
1341
- }]
1962
+ actions: "setProtectedFinalization"
1963
+ } }
1342
1964
  },
1343
- capturingManual: {
1344
- entry: ["captureLatestFrame"],
1345
- always: [{
1965
+ capturingManual: { on: {
1966
+ PROTECTED_MANUAL_COMMITTED: { actions: ["setProtectedCommittedPreview", "sendProtectedFinalize"] },
1967
+ PROTECTED_ATTEMPT_FINALIZED: {
1346
1968
  target: "preparingUpload",
1347
- guard: "hasCapturedImage"
1348
- }, {
1349
- target: "uploadError",
1350
- actions: "setServerErrorAndDecrement"
1351
- }]
1352
- },
1353
- preparingUpload: { invoke: {
1354
- id: "prepareFaceUpload",
1355
- src: "prepareFaceUpload",
1356
- input: ({ context }) => context,
1357
- onDone: {
1358
- target: "uploading",
1359
- actions: "setUploadPreparationFromEvent"
1360
- },
1361
- onError: {
1362
- target: "uploadError",
1363
- actions: "setServerErrorAndDecrement"
1969
+ actions: "setProtectedFinalization"
1364
1970
  }
1365
1971
  } },
1366
- uploading: { invoke: {
1367
- id: "uploadFace",
1368
- src: "uploadFace",
1369
- input: ({ context }) => context,
1370
- onDone: {
1371
- target: "validatingUpload",
1372
- actions: "setUploadResponseFromEvent"
1373
- },
1374
- onError: {
1375
- target: "uploadError",
1376
- actions: "setServerErrorAndDecrement"
1972
+ preparingUpload: { always: "uploading" },
1973
+ uploading: {
1974
+ entry: "sendProtectedUploadIfNeeded",
1975
+ on: {
1976
+ PROTECTED_UPLOAD_MAPPED: {
1977
+ target: "validatingUpload",
1978
+ actions: "setProtectedUploadResponse"
1979
+ },
1980
+ PROTECTED_LOCAL_DONE: {
1981
+ target: "validatingUpload",
1982
+ actions: "setProtectedLocalResult"
1983
+ }
1377
1984
  }
1378
- } },
1985
+ },
1379
1986
  validatingUpload: { always: [
1380
1987
  {
1381
1988
  target: "#faceCapture.error",
@@ -1391,12 +1998,14 @@ const faceCaptureMachine = setup({
1391
1998
  ] },
1392
1999
  uploadError: { on: { RETRY_CAPTURE: [
1393
2000
  {
1394
- target: "checkingStream",
2001
+ target: "#faceCapture.capture",
2002
+ reenter: true,
1395
2003
  guard: "hasAttemptsRemaining",
1396
2004
  actions: [
1397
- "resetDetection",
1398
2005
  "clearUploadFailure",
1399
- "prepareStreamForRetry"
2006
+ "setDeepsightNotReady",
2007
+ "resetProtectedController",
2008
+ "clearProtectedAttempt"
1400
2009
  ]
1401
2010
  },
1402
2011
  {
@@ -1410,17 +2019,17 @@ const faceCaptureMachine = setup({
1410
2019
  }
1411
2020
  ] } },
1412
2021
  success: {
1413
- entry: [
1414
- "stopRecordingService",
1415
- "clearRecordingService",
1416
- "cleanup"
1417
- ],
2022
+ entry: "cleanup",
1418
2023
  after: { 3e3: { target: "#faceCapture.processing" } }
1419
2024
  }
1420
2025
  }
1421
2026
  },
1422
2027
  manualUpload: {
1423
- entry: ["stopMediaStream", "releaseAvatarWarmup"],
2028
+ entry: [
2029
+ "releaseProtectedAttempt",
2030
+ "stopMediaStream",
2031
+ "releaseAvatarWarmup"
2032
+ ],
1424
2033
  invoke: {
1425
2034
  id: "manualUpload",
1426
2035
  src: "manualUploadMachine",
@@ -1469,21 +2078,29 @@ const faceCaptureMachine = setup({
1469
2078
  }
1470
2079
  },
1471
2080
  finished: {
1472
- entry: ["stopMediaStream", "releaseAvatarWarmup"],
2081
+ entry: [
2082
+ "releaseProtectedAttempt",
2083
+ "stopMediaStream",
2084
+ "releaseAvatarWarmup"
2085
+ ],
1473
2086
  type: "final"
1474
2087
  },
1475
2088
  closed: {
1476
- entry: ["stopMediaStream", "releaseAvatarWarmup"],
2089
+ entry: [
2090
+ "releaseProtectedAttempt",
2091
+ "stopMediaStream",
2092
+ "releaseAvatarWarmup"
2093
+ ],
1477
2094
  type: "final"
1478
2095
  },
1479
2096
  error: {
1480
2097
  entry: ["stopMediaStream", "releaseAvatarWarmup"],
1481
2098
  on: { RESET: {
1482
2099
  target: "idle",
1483
- actions: "resetContext"
2100
+ actions: ["resetProtectedController", "resetContext"]
1484
2101
  } }
1485
2102
  }
1486
2103
  }
1487
2104
  });
1488
2105
  //#endregion
1489
- export { manualFaceUploadMachine as n, concealmentToAvatar as r, faceCaptureMachine as t };
2106
+ export { concealmentToAvatar as i, createDefaultProtectedFaceControllerActor as n, manualFaceUploadMachine as r, faceCaptureMachine as t };