vesant-sdk 1.7.0-dev.c2e85f3 → 1.7.0-dev.c349626

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-DF7hlMEz.d.ts → client-0NOPDnT0.d.ts} +16 -26
  2. package/dist/{client-DrjgZoH_.d.mts → client-CvWNRwwg.d.mts} +16 -26
  3. package/dist/{client-B0qhE2kr.d.mts → client-Dps40EtF.d.mts} +2 -2
  4. package/dist/{client-DtH2RLuy.d.ts → client-SMxqod4j.d.ts} +2 -2
  5. package/dist/{client-BolQlL5e.d.mts → client-q9fN8Hhf.d.mts} +103 -1
  6. package/dist/{client-BolQlL5e.d.ts → client-q9fN8Hhf.d.ts} +103 -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 +126 -18
  10. package/dist/compliance/index.js.map +1 -1
  11. package/dist/compliance/index.mjs +126 -18
  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 +61 -6
  16. package/dist/decisions/index.js.map +1 -1
  17. package/dist/decisions/index.mjs +61 -6
  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 +129 -18
  22. package/dist/geolocation/index.js.map +1 -1
  23. package/dist/geolocation/index.mjs +127 -19
  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 +7 -7
  28. package/dist/index.d.ts +7 -7
  29. package/dist/index.js +286 -49
  30. package/dist/index.js.map +1 -1
  31. package/dist/index.mjs +281 -50
  32. package/dist/index.mjs.map +1 -1
  33. package/dist/kyc/core.d.mts +2 -2
  34. package/dist/kyc/core.d.ts +2 -2
  35. package/dist/kyc/core.js +83 -14
  36. package/dist/kyc/core.js.map +1 -1
  37. package/dist/kyc/core.mjs +83 -14
  38. package/dist/kyc/core.mjs.map +1 -1
  39. package/dist/kyc/index.d.mts +56 -8
  40. package/dist/kyc/index.d.ts +56 -8
  41. package/dist/kyc/index.js +83 -14
  42. package/dist/kyc/index.js.map +1 -1
  43. package/dist/kyc/index.mjs +83 -14
  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 +61 -6
  54. package/dist/risk-profile/index.js.map +1 -1
  55. package/dist/risk-profile/index.mjs +61 -6
  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 +61 -6
  60. package/dist/scores/index.js.map +1 -1
  61. package/dist/scores/index.mjs +61 -6
  62. package/dist/scores/index.mjs.map +1 -1
  63. package/dist/tax/index.d.mts +2 -2
  64. package/dist/tax/index.d.ts +2 -2
  65. package/dist/tax/index.js +66 -8
  66. package/dist/tax/index.js.map +1 -1
  67. package/dist/tax/index.mjs +66 -8
  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 +1 -1
@@ -75,6 +75,19 @@ var sdkReasons = {
75
75
  })
76
76
  };
77
77
 
78
+ // src/core/auth.ts
79
+ var StaticApiKeyProvider = class {
80
+ constructor(apiKey) {
81
+ this.apiKey = apiKey;
82
+ }
83
+ async getCredential() {
84
+ return this.apiKey ? { scheme: "Bearer", token: this.apiKey } : null;
85
+ }
86
+ canRefresh() {
87
+ return false;
88
+ }
89
+ };
90
+
78
91
  // src/core/errors.ts
79
92
  var VesantError = class _VesantError extends Error {
80
93
  constructor(message, code, statusCode, details) {
@@ -404,6 +417,7 @@ var BaseClient = class {
404
417
  interceptors: this.interceptors,
405
418
  logger: this.logger
406
419
  };
420
+ this.authProvider = config.authProvider ?? (apiKey ? new StaticApiKeyProvider(apiKey) : void 0);
407
421
  if (config.circuitBreaker) {
408
422
  this.circuitBreaker = new CircuitBreaker(config.circuitBreaker);
409
423
  }
@@ -411,6 +425,19 @@ var BaseClient = class {
411
425
  this.rateLimitTracker = new RateLimitTracker();
412
426
  }
413
427
  }
428
+ /**
429
+ * Resolve the Idempotency-Key for a request. Mutating methods (POST/PUT/PATCH)
430
+ * get the caller-supplied key or a freshly minted UUID; non-mutating methods get
431
+ * none. requestWithRetry resolves this once and injects it so every retry reuses
432
+ * one key (letting the server dedup replays); a direct request() resolves per call.
433
+ */
434
+ resolveIdempotencyKey(method, requestOptions) {
435
+ const isMutating = ["POST", "PUT", "PATCH"].includes((method || "GET").toUpperCase());
436
+ if (!isMutating) {
437
+ return void 0;
438
+ }
439
+ return requestOptions?.idempotencyKey ?? generateUUID();
440
+ }
414
441
  /**
415
442
  * Make an HTTP request with timeout and error handling
416
443
  */
@@ -436,15 +463,20 @@ var BaseClient = class {
436
463
  ...this.config.headers,
437
464
  ...options.headers || {}
438
465
  };
439
- if (this.config.apiKey) {
440
- headers["Authorization"] = `Bearer ${this.config.apiKey}`;
466
+ const credential = await this.authProvider?.getCredential({
467
+ tenantId: this.config.tenantId,
468
+ requestId
469
+ });
470
+ if (credential) {
471
+ headers["Authorization"] = `${credential.scheme ?? "Bearer"} ${credential.token}`;
441
472
  }
442
473
  if (this.config.environment === "sandbox") {
443
474
  headers["X-Sandbox"] = "true";
444
475
  }
445
476
  const method = (options.method || "GET").toUpperCase();
446
- if (["POST", "PUT", "PATCH"].includes(method)) {
447
- headers["Idempotency-Key"] = requestOptions?.idempotencyKey || generateUUID();
477
+ const idempotencyKey = this.resolveIdempotencyKey(method, requestOptions);
478
+ if (idempotencyKey) {
479
+ headers["Idempotency-Key"] = idempotencyKey;
448
480
  }
449
481
  const controller = new AbortController();
450
482
  const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
@@ -465,10 +497,28 @@ var BaseClient = class {
465
497
  if (this.config.debug) {
466
498
  this.logger.debug(`${finalOptions.method || "GET"} ${endpoint}`);
467
499
  }
468
- const response = await fetch(url, {
500
+ let response = await fetch(url, {
469
501
  ...finalOptions,
470
502
  signal: controller.signal
471
503
  });
504
+ if (response.status === 401 && this.authProvider?.canRefresh?.()) {
505
+ const refreshed = await this.authProvider.getCredential({
506
+ tenantId: this.config.tenantId,
507
+ requestId,
508
+ forceRefresh: true
509
+ });
510
+ if (refreshed) {
511
+ this.config.onCredentialRotated?.({ reason: "unauthorized" });
512
+ finalOptions = {
513
+ ...finalOptions,
514
+ headers: {
515
+ ...finalOptions.headers,
516
+ Authorization: `${refreshed.scheme ?? "Bearer"} ${refreshed.token}`
517
+ }
518
+ };
519
+ response = await fetch(url, { ...finalOptions, signal: controller.signal });
520
+ }
521
+ }
472
522
  clearTimeout(timeoutId);
473
523
  if (this.rateLimitTracker) {
474
524
  this.rateLimitTracker.updateFromHeaders(response.headers);
@@ -557,9 +607,11 @@ var BaseClient = class {
557
607
  */
558
608
  async requestWithRetry(endpoint, options = {}, serviceURL, retries = this.config.retries, requestOptions) {
559
609
  let lastError;
610
+ const idempotencyKey = this.resolveIdempotencyKey(options.method || "GET", requestOptions);
611
+ const attemptOptions = idempotencyKey ? { ...requestOptions, idempotencyKey } : requestOptions;
560
612
  for (let attempt = 0; attempt <= retries; attempt++) {
561
613
  try {
562
- return await this.request(endpoint, options, serviceURL, requestOptions);
614
+ return await this.request(endpoint, options, serviceURL, attemptOptions);
563
615
  } catch (error) {
564
616
  lastError = error instanceof Error ? error : new Error("Unknown error");
565
617
  if (requestOptions?.signal?.aborted) {
@@ -656,6 +708,9 @@ var BaseClient = class {
656
708
  if (config.interceptors) {
657
709
  this.interceptors = config.interceptors;
658
710
  }
711
+ if (config.authProvider !== void 0 || config.apiKey !== void 0) {
712
+ this.authProvider = this.config.authProvider ?? (this.config.apiKey ? new StaticApiKeyProvider(this.config.apiKey) : void 0);
713
+ }
659
714
  }
660
715
  /**
661
716
  * Get current configuration (readonly)
@@ -683,6 +738,61 @@ var BaseClient = class {
683
738
  }
684
739
  };
685
740
 
741
+ // src/geolocation/integrity.ts
742
+ var isNil = (v) => v === null || v === void 0;
743
+ function assessGpsIntegrity(input, opts = {}) {
744
+ const flags = [];
745
+ const now = opts.now ?? (() => Date.now());
746
+ const maxAgeMs = opts.maxAgeMs ?? 6e4;
747
+ const minAccuracy = opts.minAccuracyMeters ?? 1;
748
+ const { accuracy, altitude, altitudeAccuracy, heading, speed, timestamp } = input;
749
+ if (isNil(accuracy)) {
750
+ flags.push("accuracy_missing");
751
+ } else if (accuracy === 0) {
752
+ flags.push("accuracy_zero");
753
+ } else if (accuracy < minAccuracy) {
754
+ flags.push("accuracy_implausibly_small");
755
+ }
756
+ const hasMotion = !isNil(heading) || !isNil(speed);
757
+ if (hasMotion && (isNil(accuracy) || accuracy === 0)) {
758
+ flags.push("motion_without_accuracy");
759
+ }
760
+ if (!isNil(altitude) && isNil(altitudeAccuracy)) {
761
+ flags.push("altitude_without_accuracy");
762
+ }
763
+ if (timestamp !== void 0 && now() - timestamp > maxAgeMs) {
764
+ flags.push("stale_timestamp");
765
+ }
766
+ if (opts.permissionState === "denied" || opts.permissionState === "prompt") {
767
+ flags.push(`permission_${opts.permissionState}`);
768
+ }
769
+ return { suspicious: flags.length > 0, flags };
770
+ }
771
+ function gpsIntegrityInputFromPosition(position) {
772
+ const c = position.coords;
773
+ return {
774
+ latitude: c.latitude,
775
+ longitude: c.longitude,
776
+ accuracy: c.accuracy,
777
+ altitude: c.altitude,
778
+ altitudeAccuracy: c.altitudeAccuracy,
779
+ heading: c.heading,
780
+ speed: c.speed,
781
+ timestamp: position.timestamp
782
+ };
783
+ }
784
+ async function probeGeolocationPermission() {
785
+ try {
786
+ if (typeof navigator === "undefined" || !navigator.permissions?.query) {
787
+ return "unavailable";
788
+ }
789
+ const status = await navigator.permissions.query({ name: "geolocation" });
790
+ return status.state;
791
+ } catch {
792
+ return "unavailable";
793
+ }
794
+ }
795
+
686
796
  // src/geolocation/ciphertext.ts
687
797
  var CIPHER_TEXT_EXPIRY_MINUTES = 5;
688
798
  async function computeHMAC(key, message) {
@@ -735,6 +845,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
735
845
  if (typeof navigator === "undefined" || !navigator.geolocation) {
736
846
  return null;
737
847
  }
848
+ const permissionState = await probeGeolocationPermission();
738
849
  return new Promise((resolve) => {
739
850
  navigator.geolocation.getCurrentPosition(
740
851
  (position) => {
@@ -751,6 +862,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
751
862
  resolve(null);
752
863
  return;
753
864
  }
865
+ const { flags } = assessGpsIntegrity(gpsIntegrityInputFromPosition(position), { permissionState });
754
866
  resolve({
755
867
  latitude,
756
868
  longitude,
@@ -759,7 +871,8 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
759
871
  altitude_accuracy: position.coords.altitudeAccuracy ?? void 0,
760
872
  heading: position.coords.heading ?? void 0,
761
873
  speed: position.coords.speed ?? void 0,
762
- timestamp: position.timestamp
874
+ timestamp: position.timestamp,
875
+ integrity_flags: flags.length ? flags : void 0
763
876
  });
764
877
  },
765
878
  () => {
@@ -826,6 +939,9 @@ async function generateCipherText(options, config) {
826
939
  );
827
940
  if (location) {
828
941
  locationData = location;
942
+ if (location.integrity_flags?.length) {
943
+ warnings.push(`GPS integrity flags (advisory): ${location.integrity_flags.join(", ")}`);
944
+ }
829
945
  } else if (gpsRequiredByConfig) {
830
946
  throw new VesantError(
831
947
  `GPS location is required for ${options.reason} by tenant configuration, but GPS was not available or permission was denied`,
@@ -920,8 +1036,8 @@ var GeolocationClient = class extends BaseClient {
920
1036
  * ```
921
1037
  */
922
1038
  async verifyIP(request, requestOptions) {
923
- if (!request.ip_address?.trim()) {
924
- throw new ValidationError("ip_address is required and must be a non-empty string", ["ip_address"]);
1039
+ if (request.ip_address !== void 0 && !request.ip_address.trim()) {
1040
+ throw new ValidationError("ip_address, when provided, must be a non-empty string", ["ip_address"]);
925
1041
  }
926
1042
  return this.requestWithRetry("/api/v1/geo/verify", {
927
1043
  method: "POST",
@@ -1271,20 +1387,12 @@ var GeolocationClient = class extends BaseClient {
1271
1387
  *
1272
1388
  * @example
1273
1389
  * ```typescript
1274
- * // Using GPS (preferred)
1390
+ * // GPS (the web SDK is GPS + IP only; the server handles the IP fallback)
1275
1391
  * const result = await client.captureLocation(token, {
1276
1392
  * latitude: 37.7749,
1277
1393
  * longitude: -122.4194,
1278
1394
  * accuracy: 10
1279
1395
  * });
1280
- *
1281
- * // Using WiFi positioning (fallback)
1282
- * const result = await client.captureLocation(token, {
1283
- * wifi_networks: [
1284
- * { macAddress: "00:11:22:33:44:55", signalStrength: -50 },
1285
- * { macAddress: "AA:BB:CC:DD:EE:FF", signalStrength: -70 }
1286
- * ]
1287
- * });
1288
1396
  * ```
1289
1397
  */
1290
1398
  async captureLocation(token, capture, requestOptions) {