@neofaceid/web-sdk 1.4.2 → 1.6.0

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.
@@ -1118,6 +1118,7 @@ var ErrorType = /* @__PURE__ */ ((ErrorType2) => {
1118
1118
  ErrorType2["PERSON_NOT_FOUND"] = "PersonNotFoundError";
1119
1119
  ErrorType2["INITIALIZATION_ERROR"] = "InitializationError";
1120
1120
  ErrorType2["CAMERA_ERROR"] = "CameraError";
1121
+ ErrorType2["NO_CAMERA"] = "NoCameraError";
1121
1122
  ErrorType2["CAPTURE_ERROR"] = "CaptureError";
1122
1123
  ErrorType2["NOT_FOUND"] = "NotFoundError";
1123
1124
  ErrorType2["UNKNOWN"] = "UnknownError";
@@ -1528,7 +1529,7 @@ const recognizeBiometric = async (image, applicationToken, livenessCheck = true,
1528
1529
  const data = await response.json();
1529
1530
  return {
1530
1531
  success: data.success,
1531
- personId: data.person_id,
1532
+ // personId is intentionally NOT returned for security reasons
1532
1533
  confidenceScore: data.confidence_score,
1533
1534
  accessToken: data.access_token,
1534
1535
  payload: data.payload
@@ -1592,7 +1593,8 @@ const simpleIdentification = async (documentType, documentNumber, applicationTok
1592
1593
  throw new NeoFaceError("Unknown error occurred", ErrorType.NETWORK_ERROR);
1593
1594
  }
1594
1595
  };
1595
- const recognizeByPurpose = async (image, applicationToken, purpose, confidenceThreshold = 0.8) => {
1596
+ const recognizeByPurpose = async (image, applicationToken, purpose, confidenceThreshold = 0.8, signature, sessionData) => {
1597
+ var _a2;
1596
1598
  ensureSecureContext();
1597
1599
  const controller = createTimeoutController();
1598
1600
  const compressedImage = await compressImage(image);
@@ -1606,18 +1608,22 @@ const recognizeByPurpose = async (image, applicationToken, purpose, confidenceTh
1606
1608
  reader.readAsDataURL(compressedImage);
1607
1609
  });
1608
1610
  try {
1611
+ const requestBody = {
1612
+ biometric_data: base64Image,
1613
+ type_of_identification: "FACE",
1614
+ purpose,
1615
+ confidence_threshold: confidenceThreshold
1616
+ };
1617
+ if (signature) {
1618
+ requestBody.signature = signature;
1619
+ }
1609
1620
  const response = await fetch(`${API_BASE_URL}/api/v1/external/recognition/purpose/`, {
1610
1621
  method: "POST",
1611
1622
  headers: {
1612
1623
  "Content-Type": "application/json",
1613
1624
  "X-App-Token": applicationToken
1614
1625
  },
1615
- body: JSON.stringify({
1616
- biometric_data: base64Image,
1617
- type_of_identification: "FACE",
1618
- purpose,
1619
- confidence_threshold: confidenceThreshold
1620
- }),
1626
+ body: JSON.stringify(requestBody),
1621
1627
  signal: controller.signal
1622
1628
  });
1623
1629
  if (!response.ok) {
@@ -1629,10 +1635,16 @@ const recognizeByPurpose = async (image, applicationToken, purpose, confidenceTh
1629
1635
  const data = await response.json();
1630
1636
  return {
1631
1637
  success: data.success,
1632
- personId: data.person_id,
1638
+ personName: data.person_name || ((_a2 = data.person) == null ? void 0 : _a2.name),
1639
+ email: data.email || (sessionData == null ? void 0 : sessionData.email),
1640
+ cpf: data.cpf || (sessionData == null ? void 0 : sessionData.cpf),
1633
1641
  confidenceScore: data.confidence_score,
1634
1642
  accessToken: data.access_token,
1635
- payload: data.payload
1643
+ payload: data.payload,
1644
+ // Return signature and sessionId for external integrations
1645
+ signature,
1646
+ sessionId: sessionData == null ? void 0 : sessionData.sessionId
1647
+ // Note: personId is intentionally NOT returned for security reasons
1636
1648
  };
1637
1649
  } catch (error) {
1638
1650
  if (error instanceof Error) {
@@ -1915,6 +1927,79 @@ const identifyPerson = async (image, applicationToken) => {
1915
1927
  throw new NeoFaceError("Unknown error occurred", ErrorType.NETWORK_ERROR);
1916
1928
  }
1917
1929
  };
1930
+ const registerBiometric = async (personId, faceImage, applicationToken) => {
1931
+ ensureSecureContext();
1932
+ if (!personId) {
1933
+ throw new NeoFaceError("Person ID is required", ErrorType.VALIDATION_ERROR);
1934
+ }
1935
+ if (!faceImage) {
1936
+ throw new NeoFaceError("Face image is required", ErrorType.VALIDATION_ERROR);
1937
+ }
1938
+ const controller = createTimeoutController();
1939
+ const compressedImage = await compressImage(faceImage);
1940
+ const base64Image = await new Promise((resolve, reject) => {
1941
+ const reader = new FileReader();
1942
+ reader.onload = () => {
1943
+ const result = reader.result;
1944
+ resolve(result.split(",")[1]);
1945
+ };
1946
+ reader.onerror = reject;
1947
+ reader.readAsDataURL(compressedImage);
1948
+ });
1949
+ try {
1950
+ const response = await fetch(`${API_BASE_URL}/api/v1/identity-data/`, {
1951
+ method: "POST",
1952
+ headers: {
1953
+ "Content-Type": "application/json",
1954
+ "X-App-Token": applicationToken
1955
+ },
1956
+ body: JSON.stringify({
1957
+ person: personId,
1958
+ type_of_identification: "FACE",
1959
+ biometric_data: base64Image
1960
+ }),
1961
+ signal: controller.signal
1962
+ });
1963
+ if (!response.ok) {
1964
+ if (response.status === 401 || response.status === 403) {
1965
+ throw new NeoFaceError("Invalid or expired application token, or insufficient permissions", ErrorType.INVALID_TOKEN);
1966
+ }
1967
+ if (response.status === 400) {
1968
+ try {
1969
+ const errorData = await response.json();
1970
+ const errorMessage = errorData.message || errorData.error || "Invalid biometric data";
1971
+ throw new NeoFaceError(errorMessage, ErrorType.VALIDATION_ERROR);
1972
+ } catch (parseError) {
1973
+ if (parseError instanceof NeoFaceError) {
1974
+ throw parseError;
1975
+ }
1976
+ throw new NeoFaceError("Invalid biometric data", ErrorType.VALIDATION_ERROR);
1977
+ }
1978
+ }
1979
+ throw new NeoFaceError(`Server returned status ${response.status}`, ErrorType.NETWORK);
1980
+ }
1981
+ const data = await response.json();
1982
+ return {
1983
+ success: true,
1984
+ message: "Biometric data registered successfully",
1985
+ identity_data_id: data.id,
1986
+ type_of_identification: data.type_of_identification,
1987
+ have_biometric_data: data.have_biometric_data,
1988
+ created_at: data.created_at
1989
+ };
1990
+ } catch (error) {
1991
+ if (error instanceof Error) {
1992
+ if (error.name === "AbortError") {
1993
+ throw new NeoFaceError("Request timed out", ErrorType.NETWORK);
1994
+ }
1995
+ if (error instanceof NeoFaceError) {
1996
+ throw error;
1997
+ }
1998
+ throw new NeoFaceError(error.message, ErrorType.NETWORK);
1999
+ }
2000
+ throw new NeoFaceError("Unknown error occurred", ErrorType.NETWORK_ERROR);
2001
+ }
2002
+ };
1918
2003
  const modalReducer$1 = (state, action) => {
1919
2004
  switch (action.type) {
1920
2005
  case "PERMISSION_GRANTED":
@@ -4669,6 +4754,116 @@ class EmailPasswordModal {
4669
4754
  }
4670
4755
  const MAX_ATTEMPTS = 3;
4671
4756
  const RETRY_DELAY = 500;
4757
+ async function captureFaceSilently() {
4758
+ return new Promise((resolve, reject) => {
4759
+ const video = document.createElement("video");
4760
+ video.style.position = "fixed";
4761
+ video.style.top = "-9999px";
4762
+ video.style.left = "-9999px";
4763
+ video.style.width = "1px";
4764
+ video.style.height = "1px";
4765
+ video.style.opacity = "0";
4766
+ video.setAttribute("autoplay", "");
4767
+ video.setAttribute("muted", "");
4768
+ video.setAttribute("playsinline", "");
4769
+ const canvas = document.createElement("canvas");
4770
+ canvas.style.display = "none";
4771
+ let stream = null;
4772
+ let faceDetectionAttempts = 0;
4773
+ const MAX_FACE_DETECTION_ATTEMPTS = 10;
4774
+ const cleanup = () => {
4775
+ if (stream) {
4776
+ stream.getTracks().forEach((track) => track.stop());
4777
+ }
4778
+ if (video.parentElement) {
4779
+ video.parentElement.removeChild(video);
4780
+ }
4781
+ if (canvas.parentElement) {
4782
+ canvas.parentElement.removeChild(canvas);
4783
+ }
4784
+ };
4785
+ document.body.appendChild(video);
4786
+ document.body.appendChild(canvas);
4787
+ navigator.mediaDevices.getUserMedia({
4788
+ video: {
4789
+ width: { ideal: 640 },
4790
+ height: { ideal: 480 },
4791
+ facingMode: "user"
4792
+ },
4793
+ audio: false
4794
+ }).then((mediaStream) => {
4795
+ stream = mediaStream;
4796
+ video.srcObject = stream;
4797
+ video.play();
4798
+ const tryCapture = () => {
4799
+ if (!video.videoWidth || !video.videoHeight) {
4800
+ if (faceDetectionAttempts < MAX_FACE_DETECTION_ATTEMPTS) {
4801
+ faceDetectionAttempts++;
4802
+ setTimeout(tryCapture, 100);
4803
+ return;
4804
+ }
4805
+ cleanup();
4806
+ reject(new NeoFaceError("Câmera não está pronta", ErrorType.CAMERA_ERROR));
4807
+ return;
4808
+ }
4809
+ canvas.width = video.videoWidth;
4810
+ canvas.height = video.videoHeight;
4811
+ const ctx = canvas.getContext("2d");
4812
+ if (!ctx) {
4813
+ cleanup();
4814
+ reject(new Error("Failed to get canvas context"));
4815
+ return;
4816
+ }
4817
+ const detectFace2 = async () => {
4818
+ try {
4819
+ const detection = await faceapi.detectSingleFace(
4820
+ video,
4821
+ new faceapi.TinyFaceDetectorOptions({ inputSize: 160, scoreThreshold: 0.4 })
4822
+ );
4823
+ return !!detection;
4824
+ } catch {
4825
+ return false;
4826
+ }
4827
+ };
4828
+ detectFace2().then((hasFace) => {
4829
+ if (!hasFace && faceDetectionAttempts < MAX_FACE_DETECTION_ATTEMPTS) {
4830
+ faceDetectionAttempts++;
4831
+ setTimeout(tryCapture, 200);
4832
+ return;
4833
+ }
4834
+ ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
4835
+ canvas.toBlob(
4836
+ (blob) => {
4837
+ cleanup();
4838
+ if (blob) {
4839
+ resolve(blob);
4840
+ } else {
4841
+ reject(new Error("Failed to capture image"));
4842
+ }
4843
+ },
4844
+ "image/jpeg",
4845
+ 0.85
4846
+ );
4847
+ });
4848
+ };
4849
+ video.onloadedmetadata = () => {
4850
+ setTimeout(tryCapture, 800);
4851
+ };
4852
+ video.onerror = () => {
4853
+ cleanup();
4854
+ reject(new NeoFaceError("Erro ao acessar câmera", ErrorType.CAMERA_ERROR));
4855
+ };
4856
+ }).catch((error) => {
4857
+ cleanup();
4858
+ reject(
4859
+ new NeoFaceError(
4860
+ "Não foi possível acessar a câmera: " + error.message,
4861
+ ErrorType.CAMERA_ERROR
4862
+ )
4863
+ );
4864
+ });
4865
+ });
4866
+ }
4672
4867
  async function detectFaceContinuously(video, minDetectionTime = 3e3, detectionInterval = 200) {
4673
4868
  return new Promise((resolve) => {
4674
4869
  let faceDetectedCount = 0;
@@ -4891,6 +5086,11 @@ async function executeBiometricLoginFlow(options) {
4891
5086
  tryLogin();
4892
5087
  }, 300);
4893
5088
  }
5089
+ const biometricLoginFlow = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
5090
+ __proto__: null,
5091
+ captureFaceSilently,
5092
+ executeBiometricLoginFlow
5093
+ }, Symbol.toStringTag, { value: "Module" }));
4894
5094
  async function startFaceLogin(options) {
4895
5095
  try {
4896
5096
  const isValidToken = await validateToken(options.applicationToken);
@@ -5218,8 +5418,8 @@ const biometricDetection = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.
5218
5418
  initializeBiometricDetection,
5219
5419
  isAdvancedDetectionAvailable
5220
5420
  }, Symbol.toStringTag, { value: "Module" }));
5221
- const VERSION = "1.4.2";
5222
- const RELEASE_DATE = "2025-11-23";
5421
+ const VERSION = "1.6.0";
5422
+ const RELEASE_DATE = "2025-12-01";
5223
5423
  class OnboardingCaptureModal {
5224
5424
  constructor(options) {
5225
5425
  __publicField(this, "overlay", null);
@@ -5443,6 +5643,284 @@ const startOnboarding = async (options) => {
5443
5643
  onError(new NeoFaceError(message, ErrorType.UNKNOWN));
5444
5644
  }
5445
5645
  };
5646
+ class NeoFaceID {
5647
+ /**
5648
+ * Creates a new NeoFaceID instance
5649
+ * @param config Configuration object
5650
+ * @throws NeoFaceError if signature format is invalid
5651
+ */
5652
+ constructor(config) {
5653
+ __publicField(this, "appToken");
5654
+ __publicField(this, "baseUrl");
5655
+ __publicField(this, "signature");
5656
+ __publicField(this, "sessionData");
5657
+ var _a2;
5658
+ this.appToken = config.appToken;
5659
+ this.baseUrl = config.baseUrl || (((_a2 = { "BASE_URL": "/", "MODE": "production", "DEV": false, "PROD": true, "SSR": false }) == null ? void 0 : _a2.VITE_API_BASE_URL) || "http://localhost:8000");
5660
+ this.signature = config.signature;
5661
+ this.sessionData = config.sessionData;
5662
+ if (this.signature && !this.validateSignatureFormat(this.signature)) {
5663
+ throw new NeoFaceError(
5664
+ "Invalid signature format. Expected HMAC-SHA256 hex string (minimum 64 characters)",
5665
+ ErrorType.VALIDATION_ERROR
5666
+ );
5667
+ }
5668
+ if (this.sessionData) {
5669
+ if (!this.sessionData.email || !this.sessionData.cpf || !this.sessionData.sessionId) {
5670
+ throw new NeoFaceError(
5671
+ "Session data must include email, cpf, and sessionId",
5672
+ ErrorType.VALIDATION_ERROR
5673
+ );
5674
+ }
5675
+ }
5676
+ }
5677
+ /**
5678
+ * Validates the format of a signature
5679
+ * HMAC-SHA256 produces a 64-character hexadecimal string
5680
+ * @param signature The signature to validate
5681
+ * @returns true if valid, false otherwise
5682
+ */
5683
+ validateSignatureFormat(signature) {
5684
+ return /^[a-f0-9]{64,}$/i.test(signature);
5685
+ }
5686
+ /**
5687
+ * Captures multiple face frames for biometric recognition
5688
+ * @param options Capture options
5689
+ * @returns Promise that resolves to an array of image blobs
5690
+ * @throws NeoFaceError if capture fails
5691
+ */
5692
+ async captureFaceFrames(options) {
5693
+ const { numFrames, livenessCheck } = options;
5694
+ if (numFrames < 1 || numFrames > 10) {
5695
+ throw new NeoFaceError(
5696
+ "Number of frames must be between 1 and 10",
5697
+ ErrorType.VALIDATION_ERROR
5698
+ );
5699
+ }
5700
+ const frames = [];
5701
+ try {
5702
+ const { captureFaceSilently: captureFaceSilently2 } = await Promise.resolve().then(() => biometricLoginFlow);
5703
+ for (let i = 0; i < numFrames; i++) {
5704
+ const frame = await captureFaceSilently2();
5705
+ frames.push(frame);
5706
+ if (livenessCheck && i < numFrames - 1) {
5707
+ await new Promise((resolve) => setTimeout(resolve, 300));
5708
+ }
5709
+ }
5710
+ return frames;
5711
+ } catch (error) {
5712
+ if (error instanceof NeoFaceError) {
5713
+ throw error;
5714
+ }
5715
+ throw new NeoFaceError(
5716
+ `Failed to capture face frames: ${error instanceof Error ? error.message : "Unknown error"}`,
5717
+ ErrorType.CAPTURE_ERROR
5718
+ );
5719
+ }
5720
+ }
5721
+ /**
5722
+ * Performs login recognition using biometric data
5723
+ *
5724
+ * This method is designed for external integrations that require
5725
+ * signature validation and session management.
5726
+ *
5727
+ * @param options Recognition options
5728
+ * @returns Promise that resolves to recognition result
5729
+ * @throws NeoFaceError if recognition fails
5730
+ *
5731
+ * @example
5732
+ * ```typescript
5733
+ * const result = await sdk.loginRecognition({
5734
+ * biometricData: await sdk.captureFaceFrames({
5735
+ * numFrames: 5,
5736
+ * livenessCheck: true
5737
+ * }),
5738
+ * typeOfIdentification: 'FACE',
5739
+ * purpose: 'LOGIN',
5740
+ * confidenceThreshold: 0.8
5741
+ * });
5742
+ *
5743
+ * // Result includes signature and sessionId for callback validation
5744
+ * console.log(result.signature, result.sessionId);
5745
+ * ```
5746
+ */
5747
+ async loginRecognition(options) {
5748
+ const {
5749
+ biometricData,
5750
+ typeOfIdentification,
5751
+ purpose,
5752
+ confidenceThreshold = 0.8
5753
+ } = options;
5754
+ const imageBlobs = Array.isArray(biometricData) ? biometricData : [biometricData];
5755
+ if (imageBlobs.length === 0) {
5756
+ throw new NeoFaceError(
5757
+ "At least one biometric data frame is required",
5758
+ ErrorType.VALIDATION_ERROR
5759
+ );
5760
+ }
5761
+ const primaryImage = imageBlobs[0];
5762
+ try {
5763
+ const result = await recognizeByPurpose(
5764
+ primaryImage,
5765
+ this.appToken,
5766
+ purpose,
5767
+ confidenceThreshold,
5768
+ this.signature,
5769
+ this.sessionData
5770
+ );
5771
+ if (!result.success) {
5772
+ throw new NeoFaceError(
5773
+ "Recognition failed",
5774
+ ErrorType.RECOGNITION_FAILED
5775
+ );
5776
+ }
5777
+ if (!result.personName || !result.email || !result.cpf) {
5778
+ throw new NeoFaceError(
5779
+ "Incomplete recognition result: missing personName, email, or cpf",
5780
+ ErrorType.RECOGNITION_FAILED
5781
+ );
5782
+ }
5783
+ return {
5784
+ success: true,
5785
+ personName: result.personName,
5786
+ email: result.email,
5787
+ cpf: result.cpf,
5788
+ signature: result.signature,
5789
+ sessionId: result.sessionId,
5790
+ confidenceScore: result.confidenceScore,
5791
+ accessToken: result.accessToken
5792
+ };
5793
+ } catch (error) {
5794
+ if (error instanceof NeoFaceError) {
5795
+ throw error;
5796
+ }
5797
+ throw new NeoFaceError(
5798
+ `Login recognition failed: ${error instanceof Error ? error.message : "Unknown error"}`,
5799
+ ErrorType.RECOGNITION_FAILED
5800
+ );
5801
+ }
5802
+ }
5803
+ }
5804
+ const PHOTO_INSTRUCTIONS = [
5805
+ "Olhe diretamente para a câmera",
5806
+ "Vire levemente a cabeça para a esquerda",
5807
+ "Vire levemente a cabeça para a direita",
5808
+ "Mostre o polegar para cima (👍) e olhe para a câmera"
5809
+ ];
5810
+ const TOTAL_PHOTOS = 4;
5811
+ const authorizeOperation = async (applicationToken, cpf, options) => {
5812
+ if (!applicationToken) {
5813
+ throw new NeoFaceError("Application token is required", ErrorType.VALIDATION_ERROR);
5814
+ }
5815
+ if (!cpf) {
5816
+ throw new NeoFaceError("CPF is required", ErrorType.VALIDATION_ERROR);
5817
+ }
5818
+ const cpfClean = cpf.replace(/\D/g, "");
5819
+ if (cpfClean.length !== 11) {
5820
+ throw new NeoFaceError("Invalid CPF format", ErrorType.VALIDATION_ERROR);
5821
+ }
5822
+ const capturedPhotos = [];
5823
+ const captureDelay = (options == null ? void 0 : options.captureDelay) || 2e3;
5824
+ try {
5825
+ if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
5826
+ throw new NeoFaceError("Camera not available", ErrorType.NO_CAMERA);
5827
+ }
5828
+ const stream = await navigator.mediaDevices.getUserMedia({
5829
+ video: {
5830
+ facingMode: "user",
5831
+ width: { ideal: 1280 },
5832
+ height: { ideal: 720 }
5833
+ }
5834
+ });
5835
+ const video = document.createElement("video");
5836
+ video.srcObject = stream;
5837
+ video.autoplay = true;
5838
+ video.playsInline = true;
5839
+ await new Promise((resolve) => {
5840
+ video.onloadedmetadata = () => {
5841
+ video.play();
5842
+ resolve();
5843
+ };
5844
+ });
5845
+ const canvas = document.createElement("canvas");
5846
+ canvas.width = video.videoWidth;
5847
+ canvas.height = video.videoHeight;
5848
+ const ctx = canvas.getContext("2d");
5849
+ if (!ctx) {
5850
+ throw new NeoFaceError("Failed to get canvas context", ErrorType.CAPTURE_ERROR);
5851
+ }
5852
+ for (let i = 0; i < TOTAL_PHOTOS; i++) {
5853
+ const instruction = PHOTO_INSTRUCTIONS[i];
5854
+ if (options == null ? void 0 : options.onProgress) {
5855
+ options.onProgress(i + 1, TOTAL_PHOTOS, instruction);
5856
+ }
5857
+ if (i > 0) {
5858
+ await new Promise((resolve) => setTimeout(resolve, captureDelay));
5859
+ }
5860
+ ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
5861
+ const blob = await new Promise((resolve, reject) => {
5862
+ canvas.toBlob(
5863
+ (blob2) => {
5864
+ if (blob2) {
5865
+ resolve(blob2);
5866
+ } else {
5867
+ reject(new Error("Failed to capture photo"));
5868
+ }
5869
+ },
5870
+ "image/jpeg",
5871
+ 0.9
5872
+ );
5873
+ });
5874
+ capturedPhotos.push(blob);
5875
+ if (options == null ? void 0 : options.onPhotoTaken) {
5876
+ options.onPhotoTaken(i + 1, blob);
5877
+ }
5878
+ }
5879
+ stream.getTracks().forEach((track) => track.stop());
5880
+ const lastPhoto = capturedPhotos[TOTAL_PHOTOS - 1];
5881
+ const sessionData = {
5882
+ cpf: cpfClean,
5883
+ email: "",
5884
+ // Not required for authorization
5885
+ sessionId: `auth_${Date.now()}_${Math.random().toString(36).substring(7)}`
5886
+ };
5887
+ const recognitionResult = await recognizeByPurpose(
5888
+ lastPhoto,
5889
+ applicationToken,
5890
+ "AUTHORIZATION",
5891
+ 0.8,
5892
+ // Confidence threshold
5893
+ void 0,
5894
+ // No signature for now
5895
+ sessionData
5896
+ );
5897
+ if (!recognitionResult.success) {
5898
+ throw new NeoFaceError(
5899
+ "Authorization failed: Person not recognized",
5900
+ ErrorType.RECOGNITION_FAILED
5901
+ );
5902
+ }
5903
+ return {
5904
+ success: true,
5905
+ authorizationHash: sessionData.sessionId,
5906
+ // TEMPORARY: Using sessionId as hash
5907
+ name: recognitionResult.personName,
5908
+ birthDate: void 0,
5909
+ // Should come from backend
5910
+ cpf: recognitionResult.cpf || cpfClean,
5911
+ confidenceScore: recognitionResult.confidenceScore,
5912
+ message: "Authorization successful"
5913
+ };
5914
+ } catch (error) {
5915
+ if (error instanceof NeoFaceError) {
5916
+ throw error;
5917
+ }
5918
+ if (error instanceof Error) {
5919
+ throw new NeoFaceError(error.message, ErrorType.CAPTURE_ERROR);
5920
+ }
5921
+ throw new NeoFaceError("Unknown error during authorization", ErrorType.UNKNOWN);
5922
+ }
5923
+ };
5446
5924
  function start(applicationToken, callbacks) {
5447
5925
  const container = document.createElement("div");
5448
5926
  container.id = "neoface-modal-container";
@@ -5513,8 +5991,10 @@ export {
5513
5991
  FaceCaptureModal,
5514
5992
  FallbackPrompt,
5515
5993
  NeoFaceError,
5994
+ NeoFaceID,
5516
5995
  RELEASE_DATE,
5517
5996
  VERSION,
5997
+ authorizeOperation,
5518
5998
  biometricLogin,
5519
5999
  biometricLoginWithFallback,
5520
6000
  completeOnboarding,
@@ -5527,6 +6007,7 @@ export {
5527
6007
  recognize,
5528
6008
  recognizeBiometric,
5529
6009
  recognizeByPurpose,
6010
+ registerBiometric,
5530
6011
  registerPersonWithBiometric,
5531
6012
  registerPersonWithoutFace,
5532
6013
  simpleIdentification,