vesant-sdk 1.5.0 → 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.
Files changed (66) hide show
  1. package/README.md +5 -3
  2. package/dist/{client-3cBb_Pp-.d.ts → client-Bd9a5o0C.d.ts} +11 -3
  3. package/dist/{client-DKqyESgT.d.mts → client-C4g596fI.d.mts} +11 -3
  4. package/dist/{client-BQRONu8q.d.mts → client-CIon-bGS.d.mts} +1 -1
  5. package/dist/{client-BQRONu8q.d.ts → client-CIon-bGS.d.ts} +1 -1
  6. package/dist/compliance/index.d.mts +18 -5
  7. package/dist/compliance/index.d.ts +18 -5
  8. package/dist/compliance/index.js +202 -38
  9. package/dist/compliance/index.js.map +1 -1
  10. package/dist/compliance/index.mjs +202 -38
  11. package/dist/compliance/index.mjs.map +1 -1
  12. package/dist/decisions/index.d.mts +2 -2
  13. package/dist/decisions/index.d.ts +2 -2
  14. package/dist/decisions/index.js +3 -1
  15. package/dist/decisions/index.js.map +1 -1
  16. package/dist/decisions/index.mjs +3 -1
  17. package/dist/decisions/index.mjs.map +1 -1
  18. package/dist/geolocation/index.d.mts +4 -4
  19. package/dist/geolocation/index.d.ts +4 -4
  20. package/dist/geolocation/index.js +3 -1
  21. package/dist/geolocation/index.js.map +1 -1
  22. package/dist/geolocation/index.mjs +3 -1
  23. package/dist/geolocation/index.mjs.map +1 -1
  24. package/dist/index.d.mts +537 -9
  25. package/dist/index.d.ts +537 -9
  26. package/dist/index.js +473 -147
  27. package/dist/index.js.map +1 -1
  28. package/dist/index.mjs +472 -145
  29. package/dist/index.mjs.map +1 -1
  30. package/dist/kyc/core.d.mts +3 -3
  31. package/dist/kyc/core.d.ts +3 -3
  32. package/dist/kyc/core.js +3 -1
  33. package/dist/kyc/core.js.map +1 -1
  34. package/dist/kyc/core.mjs +3 -1
  35. package/dist/kyc/core.mjs.map +1 -1
  36. package/dist/kyc/index.d.mts +7 -3
  37. package/dist/kyc/index.d.ts +7 -3
  38. package/dist/kyc/index.js +3 -1
  39. package/dist/kyc/index.js.map +1 -1
  40. package/dist/kyc/index.mjs +3 -1
  41. package/dist/kyc/index.mjs.map +1 -1
  42. package/dist/react.d.mts +4 -4
  43. package/dist/react.d.ts +4 -4
  44. package/dist/react.js +1 -1
  45. package/dist/react.js.map +1 -1
  46. package/dist/react.mjs +1 -1
  47. package/dist/react.mjs.map +1 -1
  48. package/dist/risk-profile/index.d.mts +4 -4
  49. package/dist/risk-profile/index.d.ts +4 -4
  50. package/dist/risk-profile/index.js +3 -1
  51. package/dist/risk-profile/index.js.map +1 -1
  52. package/dist/risk-profile/index.mjs +3 -1
  53. package/dist/risk-profile/index.mjs.map +1 -1
  54. package/dist/scores/index.d.mts +2 -2
  55. package/dist/scores/index.d.ts +2 -2
  56. package/dist/scores/index.js +3 -1
  57. package/dist/scores/index.js.map +1 -1
  58. package/dist/scores/index.mjs +3 -1
  59. package/dist/scores/index.mjs.map +1 -1
  60. package/dist/{types-_hsTA3Ez.d.mts → types-1RzYeSal.d.mts} +1 -1
  61. package/dist/{types-B1OzEQR3.d.mts → types-B4Ezqo7V.d.mts} +1 -1
  62. package/dist/{types-B1OzEQR3.d.ts → types-B4Ezqo7V.d.ts} +1 -1
  63. package/dist/{types-BnL66DB3.d.ts → types-X5Md_dD_.d.ts} +1 -1
  64. package/dist/webhooks/index.d.mts +1 -1
  65. package/dist/webhooks/index.d.ts +1 -1
  66. package/package.json +6 -1
@@ -222,7 +222,7 @@ function createConsoleLogger() {
222
222
  }
223
223
 
224
224
  // src/core/version.ts
225
- var SDK_VERSION = "1.5.0";
225
+ var SDK_VERSION = "1.6.0";
226
226
 
227
227
  // src/shared/browser-utils.ts
228
228
  function generateUUID() {
@@ -510,6 +510,8 @@ var BaseClient = class {
510
510
  return new VesantError(message, "FORBIDDEN", 403);
511
511
  case 404:
512
512
  return new VesantError(message, "NOT_FOUND", 404);
513
+ case 409:
514
+ return new VesantError(message, "DUPLICATE_PROFILE", 409);
513
515
  case 429: {
514
516
  const retryAfter = data.retry_after || data.retryAfter;
515
517
  return new RateLimitError(retryAfter);
@@ -1436,17 +1438,34 @@ var ComplianceClient = class {
1436
1438
  const startTime = Date.now();
1437
1439
  this.validateRegistrationRequest(request);
1438
1440
  let geoVerification = null;
1441
+ let cipherTextResult;
1439
1442
  try {
1440
1443
  if (this.config.debug) {
1441
1444
  this.logger.debug("Starting registration verification", { customerId: request.customerId });
1442
1445
  }
1443
- geoVerification = await this.geoClient.verifyIP({
1444
- ip_address: request.ipAddress,
1445
- user_id: request.customerId,
1446
- event_type: "registration",
1447
- device_fingerprint: request.deviceFingerprint
1448
- }, requestOptions);
1449
- const blockReasons = this.evaluateRegistrationBlock(geoVerification);
1446
+ const customerData = request.cipherText ? {
1447
+ full_name: request.fullName,
1448
+ email: request.emailAddress,
1449
+ phone: request.phoneNumber,
1450
+ date_of_birth: request.dateOfBirth
1451
+ } : void 0;
1452
+ [cipherTextResult, geoVerification] = await Promise.all([
1453
+ this.executeCipherTextValidation(
1454
+ request.cipherText,
1455
+ request.customerId,
1456
+ "registration",
1457
+ request.ipAddress,
1458
+ customerData,
1459
+ requestOptions
1460
+ ),
1461
+ this.geoClient.verifyIP({
1462
+ ip_address: request.ipAddress,
1463
+ user_id: request.customerId,
1464
+ event_type: "registration",
1465
+ device_fingerprint: request.deviceFingerprint
1466
+ }, requestOptions)
1467
+ ]);
1468
+ const blockReasons = this.evaluateRegistrationBlock(geoVerification, cipherTextResult);
1450
1469
  if (blockReasons.length > 0) {
1451
1470
  if (this.config.debug) {
1452
1471
  this.logger.debug("Registration blocked at geo stage", { blockReasons });
@@ -1458,7 +1477,8 @@ var ComplianceClient = class {
1458
1477
  requiresKYC: false,
1459
1478
  requiresEDD: false,
1460
1479
  blockReasons,
1461
- processingTime: Date.now() - startTime
1480
+ processingTime: Date.now() - startTime,
1481
+ cipherTextValidation: cipherTextResult
1462
1482
  };
1463
1483
  }
1464
1484
  const profile = await this.riskClient.createProfile({
@@ -1493,7 +1513,8 @@ var ComplianceClient = class {
1493
1513
  requiresKYC,
1494
1514
  requiresEDD,
1495
1515
  blockReasons: [],
1496
- processingTime: Date.now() - startTime
1516
+ processingTime: Date.now() - startTime,
1517
+ cipherTextValidation: cipherTextResult
1497
1518
  };
1498
1519
  } catch (error) {
1499
1520
  if (this.config.debug) {
@@ -1521,7 +1542,7 @@ var ComplianceClient = class {
1521
1542
  * @param geoVerification - Geolocation verification result
1522
1543
  * @returns Array of block reasons (empty if allowed)
1523
1544
  */
1524
- evaluateRegistrationBlock(geoVerification) {
1545
+ evaluateRegistrationBlock(geoVerification, cipherTextResult) {
1525
1546
  const blockReasons = [];
1526
1547
  if (geoVerification.is_blocked) {
1527
1548
  blockReasons.push(...geoVerification.risk_reasons);
@@ -1555,6 +1576,20 @@ var ComplianceClient = class {
1555
1576
  blockReasons.push("critical_risk_level");
1556
1577
  }
1557
1578
  }
1579
+ if (cipherTextResult) {
1580
+ if (!cipherTextResult.valid) {
1581
+ blockReasons.push("ciphertext_validation_failed");
1582
+ }
1583
+ if (cipherTextResult.risk?.is_blocked) {
1584
+ blockReasons.push(...cipherTextResult.risk.block_reasons || []);
1585
+ }
1586
+ if (cipherTextResult.risk?.location_mismatch) {
1587
+ blockReasons.push("gps_ip_location_mismatch");
1588
+ }
1589
+ }
1590
+ if (geoVerification.gps_required && !cipherTextResult) {
1591
+ blockReasons.push("gps_verification_required");
1592
+ }
1558
1593
  return [...new Set(blockReasons)];
1559
1594
  }
1560
1595
  /**
@@ -1685,7 +1720,15 @@ var ComplianceClient = class {
1685
1720
  if (this.config.debug) {
1686
1721
  this.logger.debug("Starting login verification", { customerId: request.customerId });
1687
1722
  }
1688
- const [geoVerification, profileResult] = await Promise.all([
1723
+ const [cipherTextResult, geoVerification, profileResult] = await Promise.all([
1724
+ this.executeCipherTextValidation(
1725
+ request.cipherText,
1726
+ request.customerId,
1727
+ "login",
1728
+ request.ipAddress,
1729
+ void 0,
1730
+ requestOptions
1731
+ ),
1689
1732
  this.geoClient.verifyIP({
1690
1733
  ip_address: request.ipAddress,
1691
1734
  user_id: request.customerId,
@@ -1694,10 +1737,23 @@ var ComplianceClient = class {
1694
1737
  }, requestOptions),
1695
1738
  this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null)
1696
1739
  ]);
1740
+ const loginBlockReasons = this.getBlockReasons(geoVerification, profileResult || {}, cipherTextResult);
1741
+ const isBlocked = !geoVerification.is_compliant || geoVerification.is_blocked || !!cipherTextResult?.risk?.is_blocked || cipherTextResult?.valid === false || geoVerification.gps_required && !cipherTextResult;
1742
+ if (isBlocked && !profileResult) {
1743
+ return {
1744
+ allowed: false,
1745
+ geolocation: geoVerification,
1746
+ profile: null,
1747
+ requiresStepUp: false,
1748
+ blockReasons: loginBlockReasons,
1749
+ processingTime: Date.now() - startTime,
1750
+ cipherTextValidation: cipherTextResult
1751
+ };
1752
+ }
1697
1753
  let profile;
1698
1754
  if (profileResult) {
1699
1755
  profile = profileResult;
1700
- if (this.shouldUpdateProfile(profile, geoVerification.location.city)) {
1756
+ if (!isBlocked && this.shouldUpdateProfile(profile, geoVerification.location.city)) {
1701
1757
  profile = await this.riskClient.updateProfile(profile.id, {
1702
1758
  last_recorded_activity: (/* @__PURE__ */ new Date()).toISOString(),
1703
1759
  location: `${geoVerification.location.city}, ${geoVerification.location.country}`,
@@ -1710,15 +1766,15 @@ var ComplianceClient = class {
1710
1766
  }
1711
1767
  profile = await this.createProfileFromGeo(request.customerId, geoVerification);
1712
1768
  }
1713
- const isAllowed = geoVerification.is_compliant && !geoVerification.is_blocked && profile.customer_status !== "suspended";
1714
- const requiresStepUp = geoVerification.risk_level === "high" || geoVerification.risk_level === "critical";
1769
+ const requiresStepUp = geoVerification.risk_level === "high" || geoVerification.risk_level === "critical" || cipherTextResult?.risk?.location_mismatch === true;
1715
1770
  return {
1716
- allowed: isAllowed,
1771
+ allowed: !isBlocked && profile.customer_status !== "suspended",
1717
1772
  geolocation: geoVerification,
1718
1773
  profile,
1719
1774
  requiresStepUp,
1720
- blockReasons: this.getBlockReasons(geoVerification, profile),
1721
- processingTime: Date.now() - startTime
1775
+ blockReasons: isBlocked || profile.customer_status === "suspended" ? this.getBlockReasons(geoVerification, profile, cipherTextResult) : [],
1776
+ processingTime: Date.now() - startTime,
1777
+ cipherTextValidation: cipherTextResult
1722
1778
  };
1723
1779
  } catch (error) {
1724
1780
  throw new ComplianceError("Login verification failed", error instanceof Error ? error.message : void 0);
@@ -1765,27 +1821,55 @@ var ComplianceClient = class {
1765
1821
  currency: request.currency
1766
1822
  });
1767
1823
  }
1768
- const [geoVerification, profile] = await Promise.all([
1824
+ const [cipherTextResult, geoVerification, profileResult] = await Promise.all([
1825
+ this.executeCipherTextValidation(
1826
+ request.cipherText,
1827
+ request.customerId,
1828
+ "transaction",
1829
+ request.ipAddress,
1830
+ void 0,
1831
+ requestOptions
1832
+ ),
1769
1833
  this.geoClient.verifyIP({
1770
1834
  ip_address: request.ipAddress,
1771
1835
  user_id: request.customerId,
1772
1836
  event_type: "transaction",
1773
1837
  device_fingerprint: request.deviceFingerprint
1774
1838
  }, requestOptions),
1775
- this.riskClient.getProfile(request.customerId, requestOptions)
1839
+ this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null)
1776
1840
  ]);
1841
+ const geoBlocked = !geoVerification.is_compliant || geoVerification.is_blocked || !!cipherTextResult?.risk?.is_blocked || cipherTextResult?.valid === false || geoVerification.gps_required && !cipherTextResult;
1842
+ if (geoBlocked && !profileResult) {
1843
+ return {
1844
+ allowed: false,
1845
+ geolocation: geoVerification,
1846
+ profile: null,
1847
+ transactionRisk: { score: 0, level: "low", factors: [], allowed: false, requiresManualReview: false },
1848
+ requiresApproval: false,
1849
+ blockReasons: this.getTransactionBlockReasons(
1850
+ geoVerification,
1851
+ { score: 0, level: "low", factors: [], allowed: false, requiresManualReview: false },
1852
+ true,
1853
+ cipherTextResult
1854
+ ),
1855
+ processingTime: Date.now() - startTime,
1856
+ cipherTextValidation: cipherTextResult
1857
+ };
1858
+ }
1859
+ const profile = profileResult;
1777
1860
  const transactionRisk = this.calculateTransactionRisk(
1778
1861
  request.amount,
1779
1862
  request.currency,
1780
1863
  geoVerification,
1781
- profile
1864
+ profile,
1865
+ cipherTextResult
1782
1866
  );
1783
1867
  const jurisdictionAllowed = this.checkJurisdictionLimits(
1784
1868
  request.amount,
1785
1869
  request.currency,
1786
1870
  geoVerification.jurisdiction
1787
1871
  );
1788
- const isAllowed = geoVerification.is_compliant && !geoVerification.is_blocked && jurisdictionAllowed && transactionRisk.allowed;
1872
+ const isAllowed = !geoBlocked && jurisdictionAllowed && transactionRisk.allowed && profile.customer_status !== "suspended";
1789
1873
  return {
1790
1874
  allowed: isAllowed,
1791
1875
  geolocation: geoVerification,
@@ -1795,9 +1879,11 @@ var ComplianceClient = class {
1795
1879
  blockReasons: this.getTransactionBlockReasons(
1796
1880
  geoVerification,
1797
1881
  transactionRisk,
1798
- jurisdictionAllowed
1882
+ jurisdictionAllowed,
1883
+ cipherTextResult
1799
1884
  ),
1800
- processingTime: Date.now() - startTime
1885
+ processingTime: Date.now() - startTime,
1886
+ cipherTextValidation: cipherTextResult
1801
1887
  };
1802
1888
  } catch (error) {
1803
1889
  throw new ComplianceError("Transaction verification failed", error instanceof Error ? error.message : void 0);
@@ -1812,12 +1898,22 @@ var ComplianceClient = class {
1812
1898
  async verifyEvent(request, requestOptions) {
1813
1899
  const startTime = Date.now();
1814
1900
  this.validateEventRequest(request);
1815
- const geoVerification = await this.geoClient.verifyIP({
1816
- ip_address: request.ipAddress,
1817
- user_id: request.customerId,
1818
- event_type: request.eventType,
1819
- device_fingerprint: request.deviceFingerprint
1820
- }, requestOptions);
1901
+ const [cipherTextResult, geoVerification] = await Promise.all([
1902
+ this.executeCipherTextValidation(
1903
+ request.cipherText,
1904
+ request.customerId,
1905
+ request.eventType,
1906
+ request.ipAddress,
1907
+ void 0,
1908
+ requestOptions
1909
+ ),
1910
+ this.geoClient.verifyIP({
1911
+ ip_address: request.ipAddress,
1912
+ user_id: request.customerId,
1913
+ event_type: request.eventType,
1914
+ device_fingerprint: request.deviceFingerprint
1915
+ }, requestOptions)
1916
+ ]);
1821
1917
  if (this.config.autoCreateProfiles) {
1822
1918
  try {
1823
1919
  const profile = await this.riskClient.getProfile(request.customerId, requestOptions);
@@ -1830,11 +1926,26 @@ var ComplianceClient = class {
1830
1926
  }
1831
1927
  }
1832
1928
  }
1929
+ const cipherTextBlocked = cipherTextResult ? !cipherTextResult.valid || cipherTextResult.risk?.is_blocked === true : false;
1930
+ const blockReasons = [...geoVerification.risk_reasons];
1931
+ if (cipherTextResult) {
1932
+ if (!cipherTextResult.valid) {
1933
+ blockReasons.push("ciphertext_validation_failed");
1934
+ }
1935
+ if (cipherTextResult.risk?.is_blocked) {
1936
+ blockReasons.push(...cipherTextResult.risk.block_reasons || []);
1937
+ }
1938
+ }
1939
+ const gpsBlocked = geoVerification.gps_required && !cipherTextResult;
1940
+ if (gpsBlocked) {
1941
+ blockReasons.push("gps_verification_required");
1942
+ }
1833
1943
  return {
1834
- allowed: geoVerification.is_compliant && !geoVerification.is_blocked,
1944
+ allowed: geoVerification.is_compliant && !geoVerification.is_blocked && !cipherTextBlocked && !gpsBlocked,
1835
1945
  geolocation: geoVerification,
1836
- blockReasons: geoVerification.risk_reasons,
1837
- processingTime: Date.now() - startTime
1946
+ blockReasons: [...new Set(blockReasons)],
1947
+ processingTime: Date.now() - startTime,
1948
+ cipherTextValidation: cipherTextResult
1838
1949
  };
1839
1950
  }
1840
1951
  // ============================================================================
@@ -1863,7 +1974,29 @@ var ComplianceClient = class {
1863
1974
  kyc_status: "pending"
1864
1975
  });
1865
1976
  }
1866
- calculateTransactionRisk(amount, currency, geoVerification, profile) {
1977
+ /**
1978
+ * Execute cipherText validation with graceful degradation.
1979
+ * Returns undefined if cipherText is not provided or validation fails.
1980
+ */
1981
+ async executeCipherTextValidation(cipherText, userId, eventType, ipAddress, customerData, requestOptions) {
1982
+ if (!cipherText) return void 0;
1983
+ try {
1984
+ return await this.geoClient.validateCipherText(
1985
+ cipherText,
1986
+ userId,
1987
+ eventType,
1988
+ ipAddress,
1989
+ customerData,
1990
+ requestOptions
1991
+ );
1992
+ } catch (err) {
1993
+ this.logger.warn("CipherText validation failed, proceeding with IP-only", {
1994
+ error: err instanceof Error ? err.message : "Unknown error"
1995
+ });
1996
+ return void 0;
1997
+ }
1998
+ }
1999
+ calculateTransactionRisk(amount, currency, geoVerification, profile, cipherTextResult) {
1867
2000
  if (!this._currencyRatesCustomized && !this._currencyRatesWarned) {
1868
2001
  this._currencyRatesWarned = true;
1869
2002
  this.logger.warn(
@@ -1896,6 +2029,15 @@ var ComplianceClient = class {
1896
2029
  riskScore += 50;
1897
2030
  factors.push("account_suspended");
1898
2031
  }
2032
+ if (cipherTextResult) {
2033
+ if (cipherTextResult.risk?.location_mismatch) {
2034
+ riskScore += 20;
2035
+ factors.push("gps_ip_location_mismatch");
2036
+ }
2037
+ if (cipherTextResult.risk?.score) {
2038
+ riskScore += cipherTextResult.risk.score * 0.2;
2039
+ }
2040
+ }
1899
2041
  return {
1900
2042
  score: Math.min(riskScore, 100),
1901
2043
  level: this.getRiskLevel(riskScore),
@@ -1921,7 +2063,7 @@ var ComplianceClient = class {
1921
2063
  if (score >= 40) return "medium";
1922
2064
  return "low";
1923
2065
  }
1924
- getBlockReasons(geoVerification, profile) {
2066
+ getBlockReasons(geoVerification, profile, cipherTextResult) {
1925
2067
  const reasons = [];
1926
2068
  if (geoVerification.is_blocked) {
1927
2069
  reasons.push(...geoVerification.risk_reasons);
@@ -1932,9 +2074,20 @@ var ComplianceClient = class {
1932
2074
  if (profile.has_sanctions) {
1933
2075
  reasons.push("sanctions_match");
1934
2076
  }
1935
- return reasons;
2077
+ if (cipherTextResult) {
2078
+ if (!cipherTextResult.valid) {
2079
+ reasons.push("ciphertext_validation_failed");
2080
+ }
2081
+ if (cipherTextResult.risk?.is_blocked) {
2082
+ reasons.push(...cipherTextResult.risk.block_reasons || []);
2083
+ }
2084
+ }
2085
+ if (geoVerification.gps_required && !cipherTextResult) {
2086
+ reasons.push("gps_verification_required");
2087
+ }
2088
+ return [...new Set(reasons)];
1936
2089
  }
1937
- getTransactionBlockReasons(geoVerification, transactionRisk, jurisdictionAllowed) {
2090
+ getTransactionBlockReasons(geoVerification, transactionRisk, jurisdictionAllowed, cipherTextResult) {
1938
2091
  const reasons = [];
1939
2092
  if (!geoVerification.is_compliant) {
1940
2093
  reasons.push("non_compliant_jurisdiction");
@@ -1945,7 +2098,18 @@ var ComplianceClient = class {
1945
2098
  if (!transactionRisk.allowed) {
1946
2099
  reasons.push(...transactionRisk.factors);
1947
2100
  }
1948
- return reasons;
2101
+ if (cipherTextResult) {
2102
+ if (!cipherTextResult.valid) {
2103
+ reasons.push("ciphertext_validation_failed");
2104
+ }
2105
+ if (cipherTextResult.risk?.is_blocked) {
2106
+ reasons.push(...cipherTextResult.risk.block_reasons || []);
2107
+ }
2108
+ }
2109
+ if (geoVerification.gps_required && !cipherTextResult) {
2110
+ reasons.push("gps_verification_required");
2111
+ }
2112
+ return [...new Set(reasons)];
1949
2113
  }
1950
2114
  // ============================================================================
1951
2115
  // Location Request Methods