vesant-sdk 1.7.0-dev.b2c9ecf → 1.7.0-dev.b4284ca

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 (75) hide show
  1. package/dist/{client-B32yBt1b.d.ts → client-0NOPDnT0.d.ts} +16 -26
  2. package/dist/{client-BqPVh5jH.d.mts → client-CvWNRwwg.d.mts} +16 -26
  3. package/dist/{client-CHPEgasE.d.mts → client-Dps40EtF.d.mts} +2 -2
  4. package/dist/{client-pKE_gii_.d.ts → client-SMxqod4j.d.ts} +2 -2
  5. package/dist/{client-6sSaxufk.d.mts → client-q9fN8Hhf.d.mts} +96 -1
  6. package/dist/{client-6sSaxufk.d.ts → client-q9fN8Hhf.d.ts} +96 -1
  7. package/dist/compliance/index.d.mts +3 -3
  8. package/dist/compliance/index.d.ts +3 -3
  9. package/dist/compliance/index.js +114 -16
  10. package/dist/compliance/index.js.map +1 -1
  11. package/dist/compliance/index.mjs +114 -16
  12. package/dist/compliance/index.mjs.map +1 -1
  13. package/dist/decisions/index.d.mts +1 -1
  14. package/dist/decisions/index.d.ts +1 -1
  15. package/dist/decisions/index.js +49 -4
  16. package/dist/decisions/index.js.map +1 -1
  17. package/dist/decisions/index.mjs +49 -4
  18. package/dist/decisions/index.mjs.map +1 -1
  19. package/dist/geolocation/index.d.mts +59 -4
  20. package/dist/geolocation/index.d.ts +59 -4
  21. package/dist/geolocation/index.js +117 -16
  22. package/dist/geolocation/index.js.map +1 -1
  23. package/dist/geolocation/index.mjs +115 -17
  24. package/dist/geolocation/index.mjs.map +1 -1
  25. package/dist/index-CPOrMRaH.d.ts +264 -0
  26. package/dist/index-CimDmgZb.d.mts +264 -0
  27. package/dist/index.d.mts +25 -8
  28. package/dist/index.d.ts +25 -8
  29. package/dist/index.js +274 -37
  30. package/dist/index.js.map +1 -1
  31. package/dist/index.mjs +267 -38
  32. package/dist/index.mjs.map +1 -1
  33. package/dist/kyc/core.d.mts +1 -1
  34. package/dist/kyc/core.d.ts +1 -1
  35. package/dist/kyc/core.js +49 -4
  36. package/dist/kyc/core.js.map +1 -1
  37. package/dist/kyc/core.mjs +49 -4
  38. package/dist/kyc/core.mjs.map +1 -1
  39. package/dist/kyc/index.d.mts +1 -1
  40. package/dist/kyc/index.d.ts +1 -1
  41. package/dist/kyc/index.js +49 -4
  42. package/dist/kyc/index.js.map +1 -1
  43. package/dist/kyc/index.mjs +49 -4
  44. package/dist/kyc/index.mjs.map +1 -1
  45. package/dist/react.d.mts +7 -3
  46. package/dist/react.d.ts +7 -3
  47. package/dist/react.js +68 -4
  48. package/dist/react.js.map +1 -1
  49. package/dist/react.mjs +68 -4
  50. package/dist/react.mjs.map +1 -1
  51. package/dist/risk-profile/index.d.mts +1 -1
  52. package/dist/risk-profile/index.d.ts +1 -1
  53. package/dist/risk-profile/index.js +49 -4
  54. package/dist/risk-profile/index.js.map +1 -1
  55. package/dist/risk-profile/index.mjs +49 -4
  56. package/dist/risk-profile/index.mjs.map +1 -1
  57. package/dist/scores/index.d.mts +1 -1
  58. package/dist/scores/index.d.ts +1 -1
  59. package/dist/scores/index.js +49 -4
  60. package/dist/scores/index.js.map +1 -1
  61. package/dist/scores/index.mjs +49 -4
  62. package/dist/scores/index.mjs.map +1 -1
  63. package/dist/tax/index.d.mts +1 -1
  64. package/dist/tax/index.d.ts +1 -1
  65. package/dist/tax/index.js +49 -4
  66. package/dist/tax/index.js.map +1 -1
  67. package/dist/tax/index.mjs +49 -4
  68. package/dist/tax/index.mjs.map +1 -1
  69. package/dist/webhooks/index.d.mts +2 -189
  70. package/dist/webhooks/index.d.ts +2 -189
  71. package/dist/webhooks/index.js +85 -21
  72. package/dist/webhooks/index.js.map +1 -1
  73. package/dist/webhooks/index.mjs +85 -22
  74. package/dist/webhooks/index.mjs.map +1 -1
  75. package/package.json +4 -1
@@ -1,5 +1,18 @@
1
1
  'use strict';
2
2
 
3
+ // src/core/auth.ts
4
+ var StaticApiKeyProvider = class {
5
+ constructor(apiKey) {
6
+ this.apiKey = apiKey;
7
+ }
8
+ async getCredential() {
9
+ return this.apiKey ? { scheme: "Bearer", token: this.apiKey } : null;
10
+ }
11
+ canRefresh() {
12
+ return false;
13
+ }
14
+ };
15
+
3
16
  // src/core/errors.ts
4
17
  var VesantError = class _VesantError extends Error {
5
18
  constructor(message, code, statusCode, details) {
@@ -298,6 +311,12 @@ var BaseClient = class {
298
311
  if (!config.tenantId?.trim()) {
299
312
  throw new ValidationError("tenantId is required and must be a non-empty string", ["tenantId"]);
300
313
  }
314
+ if (typeof fetch === "undefined") {
315
+ throw new VesantError(
316
+ "The Vesant SDK requires a global fetch (Node.js >= 18). Upgrade Node or provide a fetch polyfill.",
317
+ "RUNTIME_UNSUPPORTED"
318
+ );
319
+ }
301
320
  this.interceptors = config.interceptors || [];
302
321
  this.logger = config.logger || createConsoleLogger();
303
322
  let environment = config.environment;
@@ -316,11 +335,12 @@ var BaseClient = class {
316
335
  environment,
317
336
  headers: config.headers || {},
318
337
  timeout: config.timeout || 1e4,
319
- retries: config.retries || 3,
338
+ retries: config.retries ?? 3,
320
339
  debug: config.debug || false,
321
340
  interceptors: this.interceptors,
322
341
  logger: this.logger
323
342
  };
343
+ this.authProvider = config.authProvider ?? (apiKey ? new StaticApiKeyProvider(apiKey) : void 0);
324
344
  if (config.circuitBreaker) {
325
345
  this.circuitBreaker = new CircuitBreaker(config.circuitBreaker);
326
346
  }
@@ -366,8 +386,12 @@ var BaseClient = class {
366
386
  ...this.config.headers,
367
387
  ...options.headers || {}
368
388
  };
369
- if (this.config.apiKey) {
370
- headers["Authorization"] = `Bearer ${this.config.apiKey}`;
389
+ const credential = await this.authProvider?.getCredential({
390
+ tenantId: this.config.tenantId,
391
+ requestId
392
+ });
393
+ if (credential) {
394
+ headers["Authorization"] = `${credential.scheme ?? "Bearer"} ${credential.token}`;
371
395
  }
372
396
  if (this.config.environment === "sandbox") {
373
397
  headers["X-Sandbox"] = "true";
@@ -396,10 +420,28 @@ var BaseClient = class {
396
420
  if (this.config.debug) {
397
421
  this.logger.debug(`${finalOptions.method || "GET"} ${endpoint}`);
398
422
  }
399
- const response = await fetch(url, {
423
+ let response = await fetch(url, {
400
424
  ...finalOptions,
401
425
  signal: controller.signal
402
426
  });
427
+ if (response.status === 401 && this.authProvider?.canRefresh?.()) {
428
+ const refreshed = await this.authProvider.getCredential({
429
+ tenantId: this.config.tenantId,
430
+ requestId,
431
+ forceRefresh: true
432
+ });
433
+ if (refreshed) {
434
+ this.config.onCredentialRotated?.({ reason: "unauthorized" });
435
+ finalOptions = {
436
+ ...finalOptions,
437
+ headers: {
438
+ ...finalOptions.headers,
439
+ Authorization: `${refreshed.scheme ?? "Bearer"} ${refreshed.token}`
440
+ }
441
+ };
442
+ response = await fetch(url, { ...finalOptions, signal: controller.signal });
443
+ }
444
+ }
403
445
  clearTimeout(timeoutId);
404
446
  if (this.rateLimitTracker) {
405
447
  this.rateLimitTracker.updateFromHeaders(response.headers);
@@ -589,6 +631,9 @@ var BaseClient = class {
589
631
  if (config.interceptors) {
590
632
  this.interceptors = config.interceptors;
591
633
  }
634
+ if (config.authProvider !== void 0 || config.apiKey !== void 0) {
635
+ this.authProvider = this.config.authProvider ?? (this.config.apiKey ? new StaticApiKeyProvider(this.config.apiKey) : void 0);
636
+ }
592
637
  }
593
638
  /**
594
639
  * Get current configuration (readonly)
@@ -616,6 +661,61 @@ var BaseClient = class {
616
661
  }
617
662
  };
618
663
 
664
+ // src/geolocation/integrity.ts
665
+ var isNil = (v) => v === null || v === void 0;
666
+ function assessGpsIntegrity(input, opts = {}) {
667
+ const flags = [];
668
+ const now = opts.now ?? (() => Date.now());
669
+ const maxAgeMs = opts.maxAgeMs ?? 6e4;
670
+ const minAccuracy = opts.minAccuracyMeters ?? 1;
671
+ const { accuracy, altitude, altitudeAccuracy, heading, speed, timestamp } = input;
672
+ if (isNil(accuracy)) {
673
+ flags.push("accuracy_missing");
674
+ } else if (accuracy === 0) {
675
+ flags.push("accuracy_zero");
676
+ } else if (accuracy < minAccuracy) {
677
+ flags.push("accuracy_implausibly_small");
678
+ }
679
+ const hasMotion = !isNil(heading) || !isNil(speed);
680
+ if (hasMotion && (isNil(accuracy) || accuracy === 0)) {
681
+ flags.push("motion_without_accuracy");
682
+ }
683
+ if (!isNil(altitude) && isNil(altitudeAccuracy)) {
684
+ flags.push("altitude_without_accuracy");
685
+ }
686
+ if (timestamp !== void 0 && now() - timestamp > maxAgeMs) {
687
+ flags.push("stale_timestamp");
688
+ }
689
+ if (opts.permissionState === "denied" || opts.permissionState === "prompt") {
690
+ flags.push(`permission_${opts.permissionState}`);
691
+ }
692
+ return { suspicious: flags.length > 0, flags };
693
+ }
694
+ function gpsIntegrityInputFromPosition(position) {
695
+ const c = position.coords;
696
+ return {
697
+ latitude: c.latitude,
698
+ longitude: c.longitude,
699
+ accuracy: c.accuracy,
700
+ altitude: c.altitude,
701
+ altitudeAccuracy: c.altitudeAccuracy,
702
+ heading: c.heading,
703
+ speed: c.speed,
704
+ timestamp: position.timestamp
705
+ };
706
+ }
707
+ async function probeGeolocationPermission() {
708
+ try {
709
+ if (typeof navigator === "undefined" || !navigator.permissions?.query) {
710
+ return "unavailable";
711
+ }
712
+ const status = await navigator.permissions.query({ name: "geolocation" });
713
+ return status.state;
714
+ } catch {
715
+ return "unavailable";
716
+ }
717
+ }
718
+
619
719
  // src/geolocation/ciphertext.ts
620
720
  var CIPHER_TEXT_EXPIRY_MINUTES = 5;
621
721
  async function computeHMAC(key, message) {
@@ -668,6 +768,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
668
768
  if (typeof navigator === "undefined" || !navigator.geolocation) {
669
769
  return null;
670
770
  }
771
+ const permissionState = await probeGeolocationPermission();
671
772
  return new Promise((resolve) => {
672
773
  navigator.geolocation.getCurrentPosition(
673
774
  (position) => {
@@ -684,6 +785,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
684
785
  resolve(null);
685
786
  return;
686
787
  }
788
+ const { flags } = assessGpsIntegrity(gpsIntegrityInputFromPosition(position), { permissionState });
687
789
  resolve({
688
790
  latitude,
689
791
  longitude,
@@ -692,7 +794,8 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
692
794
  altitude_accuracy: position.coords.altitudeAccuracy ?? void 0,
693
795
  heading: position.coords.heading ?? void 0,
694
796
  speed: position.coords.speed ?? void 0,
695
- timestamp: position.timestamp
797
+ timestamp: position.timestamp,
798
+ integrity_flags: flags.length ? flags : void 0
696
799
  });
697
800
  },
698
801
  () => {
@@ -759,6 +862,9 @@ async function generateCipherText(options, config) {
759
862
  );
760
863
  if (location) {
761
864
  locationData = location;
865
+ if (location.integrity_flags?.length) {
866
+ warnings.push(`GPS integrity flags (advisory): ${location.integrity_flags.join(", ")}`);
867
+ }
762
868
  } else if (gpsRequiredByConfig) {
763
869
  throw new VesantError(
764
870
  `GPS location is required for ${options.reason} by tenant configuration, but GPS was not available or permission was denied`,
@@ -878,8 +984,8 @@ var GeolocationClient = class extends BaseClient {
878
984
  * ```
879
985
  */
880
986
  async verifyIP(request, requestOptions) {
881
- if (!request.ip_address?.trim()) {
882
- throw new ValidationError("ip_address is required and must be a non-empty string", ["ip_address"]);
987
+ if (request.ip_address !== void 0 && !request.ip_address.trim()) {
988
+ throw new ValidationError("ip_address, when provided, must be a non-empty string", ["ip_address"]);
883
989
  }
884
990
  return this.requestWithRetry("/api/v1/geo/verify", {
885
991
  method: "POST",
@@ -1229,20 +1335,12 @@ var GeolocationClient = class extends BaseClient {
1229
1335
  *
1230
1336
  * @example
1231
1337
  * ```typescript
1232
- * // Using GPS (preferred)
1338
+ * // GPS (the web SDK is GPS + IP only; the server handles the IP fallback)
1233
1339
  * const result = await client.captureLocation(token, {
1234
1340
  * latitude: 37.7749,
1235
1341
  * longitude: -122.4194,
1236
1342
  * accuracy: 10
1237
1343
  * });
1238
- *
1239
- * // Using WiFi positioning (fallback)
1240
- * const result = await client.captureLocation(token, {
1241
- * wifi_networks: [
1242
- * { macAddress: "00:11:22:33:44:55", signalStrength: -50 },
1243
- * { macAddress: "AA:BB:CC:DD:EE:FF", signalStrength: -70 }
1244
- * ]
1245
- * });
1246
1344
  * ```
1247
1345
  */
1248
1346
  async captureLocation(token, capture, requestOptions) {
@@ -1290,8 +1388,11 @@ var GeolocationClient = class extends BaseClient {
1290
1388
  };
1291
1389
 
1292
1390
  exports.GeolocationClient = GeolocationClient;
1391
+ exports.assessGpsIntegrity = assessGpsIntegrity;
1293
1392
  exports.decodeCipherText = decodeCipherText;
1294
1393
  exports.generateCipherText = generateCipherText;
1394
+ exports.gpsIntegrityInputFromPosition = gpsIntegrityInputFromPosition;
1295
1395
  exports.isCipherTextExpired = isCipherTextExpired;
1396
+ exports.probeGeolocationPermission = probeGeolocationPermission;
1296
1397
  //# sourceMappingURL=index.js.map
1297
1398
  //# sourceMappingURL=index.js.map