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
@@ -224,7 +224,7 @@ function createConsoleLogger() {
224
224
  }
225
225
 
226
226
  // src/core/version.ts
227
- var SDK_VERSION = "1.5.0";
227
+ var SDK_VERSION = "1.6.0";
228
228
 
229
229
  // src/shared/browser-utils.ts
230
230
  function generateUUID() {
@@ -512,6 +512,8 @@ var BaseClient = class {
512
512
  return new VesantError(message, "FORBIDDEN", 403);
513
513
  case 404:
514
514
  return new VesantError(message, "NOT_FOUND", 404);
515
+ case 409:
516
+ return new VesantError(message, "DUPLICATE_PROFILE", 409);
515
517
  case 429: {
516
518
  const retryAfter = data.retry_after || data.retryAfter;
517
519
  return new RateLimitError(retryAfter);
@@ -1438,17 +1440,34 @@ var ComplianceClient = class {
1438
1440
  const startTime = Date.now();
1439
1441
  this.validateRegistrationRequest(request);
1440
1442
  let geoVerification = null;
1443
+ let cipherTextResult;
1441
1444
  try {
1442
1445
  if (this.config.debug) {
1443
1446
  this.logger.debug("Starting registration verification", { customerId: request.customerId });
1444
1447
  }
1445
- geoVerification = await this.geoClient.verifyIP({
1446
- ip_address: request.ipAddress,
1447
- user_id: request.customerId,
1448
- event_type: "registration",
1449
- device_fingerprint: request.deviceFingerprint
1450
- }, requestOptions);
1451
- const blockReasons = this.evaluateRegistrationBlock(geoVerification);
1448
+ const customerData = request.cipherText ? {
1449
+ full_name: request.fullName,
1450
+ email: request.emailAddress,
1451
+ phone: request.phoneNumber,
1452
+ date_of_birth: request.dateOfBirth
1453
+ } : void 0;
1454
+ [cipherTextResult, geoVerification] = await Promise.all([
1455
+ this.executeCipherTextValidation(
1456
+ request.cipherText,
1457
+ request.customerId,
1458
+ "registration",
1459
+ request.ipAddress,
1460
+ customerData,
1461
+ requestOptions
1462
+ ),
1463
+ this.geoClient.verifyIP({
1464
+ ip_address: request.ipAddress,
1465
+ user_id: request.customerId,
1466
+ event_type: "registration",
1467
+ device_fingerprint: request.deviceFingerprint
1468
+ }, requestOptions)
1469
+ ]);
1470
+ const blockReasons = this.evaluateRegistrationBlock(geoVerification, cipherTextResult);
1452
1471
  if (blockReasons.length > 0) {
1453
1472
  if (this.config.debug) {
1454
1473
  this.logger.debug("Registration blocked at geo stage", { blockReasons });
@@ -1460,7 +1479,8 @@ var ComplianceClient = class {
1460
1479
  requiresKYC: false,
1461
1480
  requiresEDD: false,
1462
1481
  blockReasons,
1463
- processingTime: Date.now() - startTime
1482
+ processingTime: Date.now() - startTime,
1483
+ cipherTextValidation: cipherTextResult
1464
1484
  };
1465
1485
  }
1466
1486
  const profile = await this.riskClient.createProfile({
@@ -1495,7 +1515,8 @@ var ComplianceClient = class {
1495
1515
  requiresKYC,
1496
1516
  requiresEDD,
1497
1517
  blockReasons: [],
1498
- processingTime: Date.now() - startTime
1518
+ processingTime: Date.now() - startTime,
1519
+ cipherTextValidation: cipherTextResult
1499
1520
  };
1500
1521
  } catch (error) {
1501
1522
  if (this.config.debug) {
@@ -1523,7 +1544,7 @@ var ComplianceClient = class {
1523
1544
  * @param geoVerification - Geolocation verification result
1524
1545
  * @returns Array of block reasons (empty if allowed)
1525
1546
  */
1526
- evaluateRegistrationBlock(geoVerification) {
1547
+ evaluateRegistrationBlock(geoVerification, cipherTextResult) {
1527
1548
  const blockReasons = [];
1528
1549
  if (geoVerification.is_blocked) {
1529
1550
  blockReasons.push(...geoVerification.risk_reasons);
@@ -1557,6 +1578,20 @@ var ComplianceClient = class {
1557
1578
  blockReasons.push("critical_risk_level");
1558
1579
  }
1559
1580
  }
1581
+ if (cipherTextResult) {
1582
+ if (!cipherTextResult.valid) {
1583
+ blockReasons.push("ciphertext_validation_failed");
1584
+ }
1585
+ if (cipherTextResult.risk?.is_blocked) {
1586
+ blockReasons.push(...cipherTextResult.risk.block_reasons || []);
1587
+ }
1588
+ if (cipherTextResult.risk?.location_mismatch) {
1589
+ blockReasons.push("gps_ip_location_mismatch");
1590
+ }
1591
+ }
1592
+ if (geoVerification.gps_required && !cipherTextResult) {
1593
+ blockReasons.push("gps_verification_required");
1594
+ }
1560
1595
  return [...new Set(blockReasons)];
1561
1596
  }
1562
1597
  /**
@@ -1687,7 +1722,15 @@ var ComplianceClient = class {
1687
1722
  if (this.config.debug) {
1688
1723
  this.logger.debug("Starting login verification", { customerId: request.customerId });
1689
1724
  }
1690
- const [geoVerification, profileResult] = await Promise.all([
1725
+ const [cipherTextResult, geoVerification, profileResult] = await Promise.all([
1726
+ this.executeCipherTextValidation(
1727
+ request.cipherText,
1728
+ request.customerId,
1729
+ "login",
1730
+ request.ipAddress,
1731
+ void 0,
1732
+ requestOptions
1733
+ ),
1691
1734
  this.geoClient.verifyIP({
1692
1735
  ip_address: request.ipAddress,
1693
1736
  user_id: request.customerId,
@@ -1696,10 +1739,23 @@ var ComplianceClient = class {
1696
1739
  }, requestOptions),
1697
1740
  this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null)
1698
1741
  ]);
1742
+ const loginBlockReasons = this.getBlockReasons(geoVerification, profileResult || {}, cipherTextResult);
1743
+ const isBlocked = !geoVerification.is_compliant || geoVerification.is_blocked || !!cipherTextResult?.risk?.is_blocked || cipherTextResult?.valid === false || geoVerification.gps_required && !cipherTextResult;
1744
+ if (isBlocked && !profileResult) {
1745
+ return {
1746
+ allowed: false,
1747
+ geolocation: geoVerification,
1748
+ profile: null,
1749
+ requiresStepUp: false,
1750
+ blockReasons: loginBlockReasons,
1751
+ processingTime: Date.now() - startTime,
1752
+ cipherTextValidation: cipherTextResult
1753
+ };
1754
+ }
1699
1755
  let profile;
1700
1756
  if (profileResult) {
1701
1757
  profile = profileResult;
1702
- if (this.shouldUpdateProfile(profile, geoVerification.location.city)) {
1758
+ if (!isBlocked && this.shouldUpdateProfile(profile, geoVerification.location.city)) {
1703
1759
  profile = await this.riskClient.updateProfile(profile.id, {
1704
1760
  last_recorded_activity: (/* @__PURE__ */ new Date()).toISOString(),
1705
1761
  location: `${geoVerification.location.city}, ${geoVerification.location.country}`,
@@ -1712,15 +1768,15 @@ var ComplianceClient = class {
1712
1768
  }
1713
1769
  profile = await this.createProfileFromGeo(request.customerId, geoVerification);
1714
1770
  }
1715
- const isAllowed = geoVerification.is_compliant && !geoVerification.is_blocked && profile.customer_status !== "suspended";
1716
- const requiresStepUp = geoVerification.risk_level === "high" || geoVerification.risk_level === "critical";
1771
+ const requiresStepUp = geoVerification.risk_level === "high" || geoVerification.risk_level === "critical" || cipherTextResult?.risk?.location_mismatch === true;
1717
1772
  return {
1718
- allowed: isAllowed,
1773
+ allowed: !isBlocked && profile.customer_status !== "suspended",
1719
1774
  geolocation: geoVerification,
1720
1775
  profile,
1721
1776
  requiresStepUp,
1722
- blockReasons: this.getBlockReasons(geoVerification, profile),
1723
- processingTime: Date.now() - startTime
1777
+ blockReasons: isBlocked || profile.customer_status === "suspended" ? this.getBlockReasons(geoVerification, profile, cipherTextResult) : [],
1778
+ processingTime: Date.now() - startTime,
1779
+ cipherTextValidation: cipherTextResult
1724
1780
  };
1725
1781
  } catch (error) {
1726
1782
  throw new ComplianceError("Login verification failed", error instanceof Error ? error.message : void 0);
@@ -1767,27 +1823,55 @@ var ComplianceClient = class {
1767
1823
  currency: request.currency
1768
1824
  });
1769
1825
  }
1770
- const [geoVerification, profile] = await Promise.all([
1826
+ const [cipherTextResult, geoVerification, profileResult] = await Promise.all([
1827
+ this.executeCipherTextValidation(
1828
+ request.cipherText,
1829
+ request.customerId,
1830
+ "transaction",
1831
+ request.ipAddress,
1832
+ void 0,
1833
+ requestOptions
1834
+ ),
1771
1835
  this.geoClient.verifyIP({
1772
1836
  ip_address: request.ipAddress,
1773
1837
  user_id: request.customerId,
1774
1838
  event_type: "transaction",
1775
1839
  device_fingerprint: request.deviceFingerprint
1776
1840
  }, requestOptions),
1777
- this.riskClient.getProfile(request.customerId, requestOptions)
1841
+ this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null)
1778
1842
  ]);
1843
+ const geoBlocked = !geoVerification.is_compliant || geoVerification.is_blocked || !!cipherTextResult?.risk?.is_blocked || cipherTextResult?.valid === false || geoVerification.gps_required && !cipherTextResult;
1844
+ if (geoBlocked && !profileResult) {
1845
+ return {
1846
+ allowed: false,
1847
+ geolocation: geoVerification,
1848
+ profile: null,
1849
+ transactionRisk: { score: 0, level: "low", factors: [], allowed: false, requiresManualReview: false },
1850
+ requiresApproval: false,
1851
+ blockReasons: this.getTransactionBlockReasons(
1852
+ geoVerification,
1853
+ { score: 0, level: "low", factors: [], allowed: false, requiresManualReview: false },
1854
+ true,
1855
+ cipherTextResult
1856
+ ),
1857
+ processingTime: Date.now() - startTime,
1858
+ cipherTextValidation: cipherTextResult
1859
+ };
1860
+ }
1861
+ const profile = profileResult;
1779
1862
  const transactionRisk = this.calculateTransactionRisk(
1780
1863
  request.amount,
1781
1864
  request.currency,
1782
1865
  geoVerification,
1783
- profile
1866
+ profile,
1867
+ cipherTextResult
1784
1868
  );
1785
1869
  const jurisdictionAllowed = this.checkJurisdictionLimits(
1786
1870
  request.amount,
1787
1871
  request.currency,
1788
1872
  geoVerification.jurisdiction
1789
1873
  );
1790
- const isAllowed = geoVerification.is_compliant && !geoVerification.is_blocked && jurisdictionAllowed && transactionRisk.allowed;
1874
+ const isAllowed = !geoBlocked && jurisdictionAllowed && transactionRisk.allowed && profile.customer_status !== "suspended";
1791
1875
  return {
1792
1876
  allowed: isAllowed,
1793
1877
  geolocation: geoVerification,
@@ -1797,9 +1881,11 @@ var ComplianceClient = class {
1797
1881
  blockReasons: this.getTransactionBlockReasons(
1798
1882
  geoVerification,
1799
1883
  transactionRisk,
1800
- jurisdictionAllowed
1884
+ jurisdictionAllowed,
1885
+ cipherTextResult
1801
1886
  ),
1802
- processingTime: Date.now() - startTime
1887
+ processingTime: Date.now() - startTime,
1888
+ cipherTextValidation: cipherTextResult
1803
1889
  };
1804
1890
  } catch (error) {
1805
1891
  throw new ComplianceError("Transaction verification failed", error instanceof Error ? error.message : void 0);
@@ -1814,12 +1900,22 @@ var ComplianceClient = class {
1814
1900
  async verifyEvent(request, requestOptions) {
1815
1901
  const startTime = Date.now();
1816
1902
  this.validateEventRequest(request);
1817
- const geoVerification = await this.geoClient.verifyIP({
1818
- ip_address: request.ipAddress,
1819
- user_id: request.customerId,
1820
- event_type: request.eventType,
1821
- device_fingerprint: request.deviceFingerprint
1822
- }, requestOptions);
1903
+ const [cipherTextResult, geoVerification] = await Promise.all([
1904
+ this.executeCipherTextValidation(
1905
+ request.cipherText,
1906
+ request.customerId,
1907
+ request.eventType,
1908
+ request.ipAddress,
1909
+ void 0,
1910
+ requestOptions
1911
+ ),
1912
+ this.geoClient.verifyIP({
1913
+ ip_address: request.ipAddress,
1914
+ user_id: request.customerId,
1915
+ event_type: request.eventType,
1916
+ device_fingerprint: request.deviceFingerprint
1917
+ }, requestOptions)
1918
+ ]);
1823
1919
  if (this.config.autoCreateProfiles) {
1824
1920
  try {
1825
1921
  const profile = await this.riskClient.getProfile(request.customerId, requestOptions);
@@ -1832,11 +1928,26 @@ var ComplianceClient = class {
1832
1928
  }
1833
1929
  }
1834
1930
  }
1931
+ const cipherTextBlocked = cipherTextResult ? !cipherTextResult.valid || cipherTextResult.risk?.is_blocked === true : false;
1932
+ const blockReasons = [...geoVerification.risk_reasons];
1933
+ if (cipherTextResult) {
1934
+ if (!cipherTextResult.valid) {
1935
+ blockReasons.push("ciphertext_validation_failed");
1936
+ }
1937
+ if (cipherTextResult.risk?.is_blocked) {
1938
+ blockReasons.push(...cipherTextResult.risk.block_reasons || []);
1939
+ }
1940
+ }
1941
+ const gpsBlocked = geoVerification.gps_required && !cipherTextResult;
1942
+ if (gpsBlocked) {
1943
+ blockReasons.push("gps_verification_required");
1944
+ }
1835
1945
  return {
1836
- allowed: geoVerification.is_compliant && !geoVerification.is_blocked,
1946
+ allowed: geoVerification.is_compliant && !geoVerification.is_blocked && !cipherTextBlocked && !gpsBlocked,
1837
1947
  geolocation: geoVerification,
1838
- blockReasons: geoVerification.risk_reasons,
1839
- processingTime: Date.now() - startTime
1948
+ blockReasons: [...new Set(blockReasons)],
1949
+ processingTime: Date.now() - startTime,
1950
+ cipherTextValidation: cipherTextResult
1840
1951
  };
1841
1952
  }
1842
1953
  // ============================================================================
@@ -1865,7 +1976,29 @@ var ComplianceClient = class {
1865
1976
  kyc_status: "pending"
1866
1977
  });
1867
1978
  }
1868
- calculateTransactionRisk(amount, currency, geoVerification, profile) {
1979
+ /**
1980
+ * Execute cipherText validation with graceful degradation.
1981
+ * Returns undefined if cipherText is not provided or validation fails.
1982
+ */
1983
+ async executeCipherTextValidation(cipherText, userId, eventType, ipAddress, customerData, requestOptions) {
1984
+ if (!cipherText) return void 0;
1985
+ try {
1986
+ return await this.geoClient.validateCipherText(
1987
+ cipherText,
1988
+ userId,
1989
+ eventType,
1990
+ ipAddress,
1991
+ customerData,
1992
+ requestOptions
1993
+ );
1994
+ } catch (err) {
1995
+ this.logger.warn("CipherText validation failed, proceeding with IP-only", {
1996
+ error: err instanceof Error ? err.message : "Unknown error"
1997
+ });
1998
+ return void 0;
1999
+ }
2000
+ }
2001
+ calculateTransactionRisk(amount, currency, geoVerification, profile, cipherTextResult) {
1869
2002
  if (!this._currencyRatesCustomized && !this._currencyRatesWarned) {
1870
2003
  this._currencyRatesWarned = true;
1871
2004
  this.logger.warn(
@@ -1898,6 +2031,15 @@ var ComplianceClient = class {
1898
2031
  riskScore += 50;
1899
2032
  factors.push("account_suspended");
1900
2033
  }
2034
+ if (cipherTextResult) {
2035
+ if (cipherTextResult.risk?.location_mismatch) {
2036
+ riskScore += 20;
2037
+ factors.push("gps_ip_location_mismatch");
2038
+ }
2039
+ if (cipherTextResult.risk?.score) {
2040
+ riskScore += cipherTextResult.risk.score * 0.2;
2041
+ }
2042
+ }
1901
2043
  return {
1902
2044
  score: Math.min(riskScore, 100),
1903
2045
  level: this.getRiskLevel(riskScore),
@@ -1923,7 +2065,7 @@ var ComplianceClient = class {
1923
2065
  if (score >= 40) return "medium";
1924
2066
  return "low";
1925
2067
  }
1926
- getBlockReasons(geoVerification, profile) {
2068
+ getBlockReasons(geoVerification, profile, cipherTextResult) {
1927
2069
  const reasons = [];
1928
2070
  if (geoVerification.is_blocked) {
1929
2071
  reasons.push(...geoVerification.risk_reasons);
@@ -1934,9 +2076,20 @@ var ComplianceClient = class {
1934
2076
  if (profile.has_sanctions) {
1935
2077
  reasons.push("sanctions_match");
1936
2078
  }
1937
- return reasons;
2079
+ if (cipherTextResult) {
2080
+ if (!cipherTextResult.valid) {
2081
+ reasons.push("ciphertext_validation_failed");
2082
+ }
2083
+ if (cipherTextResult.risk?.is_blocked) {
2084
+ reasons.push(...cipherTextResult.risk.block_reasons || []);
2085
+ }
2086
+ }
2087
+ if (geoVerification.gps_required && !cipherTextResult) {
2088
+ reasons.push("gps_verification_required");
2089
+ }
2090
+ return [...new Set(reasons)];
1938
2091
  }
1939
- getTransactionBlockReasons(geoVerification, transactionRisk, jurisdictionAllowed) {
2092
+ getTransactionBlockReasons(geoVerification, transactionRisk, jurisdictionAllowed, cipherTextResult) {
1940
2093
  const reasons = [];
1941
2094
  if (!geoVerification.is_compliant) {
1942
2095
  reasons.push("non_compliant_jurisdiction");
@@ -1947,7 +2100,18 @@ var ComplianceClient = class {
1947
2100
  if (!transactionRisk.allowed) {
1948
2101
  reasons.push(...transactionRisk.factors);
1949
2102
  }
1950
- return reasons;
2103
+ if (cipherTextResult) {
2104
+ if (!cipherTextResult.valid) {
2105
+ reasons.push("ciphertext_validation_failed");
2106
+ }
2107
+ if (cipherTextResult.risk?.is_blocked) {
2108
+ reasons.push(...cipherTextResult.risk.block_reasons || []);
2109
+ }
2110
+ }
2111
+ if (geoVerification.gps_required && !cipherTextResult) {
2112
+ reasons.push("gps_verification_required");
2113
+ }
2114
+ return [...new Set(reasons)];
1951
2115
  }
1952
2116
  // ============================================================================
1953
2117
  // Location Request Methods