vesant-sdk 1.7.0-dev.7d59b3e → 1.7.0-dev.8afce7f

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 (67) hide show
  1. package/dist/{client-DoMSYMMR.d.ts → client-0NOPDnT0.d.ts} +29 -26
  2. package/dist/{client-DMIRx7Tu.d.mts → client-CvWNRwwg.d.mts} +29 -26
  3. package/dist/{client-ZNdnpWe7.d.mts → client-Dps40EtF.d.mts} +2 -2
  4. package/dist/{client-C3DCmGe9.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 -21
  10. package/dist/compliance/index.js.map +1 -1
  11. package/dist/compliance/index.mjs +126 -21
  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.d.mts +7 -7
  26. package/dist/index.d.ts +7 -7
  27. package/dist/index.js +209 -36
  28. package/dist/index.js.map +1 -1
  29. package/dist/index.mjs +205 -37
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/kyc/core.d.mts +2 -2
  32. package/dist/kyc/core.d.ts +2 -2
  33. package/dist/kyc/core.js +87 -18
  34. package/dist/kyc/core.js.map +1 -1
  35. package/dist/kyc/core.mjs +87 -18
  36. package/dist/kyc/core.mjs.map +1 -1
  37. package/dist/kyc/index.d.mts +110 -13
  38. package/dist/kyc/index.d.ts +110 -13
  39. package/dist/kyc/index.js +87 -18
  40. package/dist/kyc/index.js.map +1 -1
  41. package/dist/kyc/index.mjs +87 -18
  42. package/dist/kyc/index.mjs.map +1 -1
  43. package/dist/react.d.mts +9 -3
  44. package/dist/react.d.ts +9 -3
  45. package/dist/react.js +180 -77
  46. package/dist/react.js.map +1 -1
  47. package/dist/react.mjs +180 -77
  48. package/dist/react.mjs.map +1 -1
  49. package/dist/risk-profile/index.d.mts +1 -1
  50. package/dist/risk-profile/index.d.ts +1 -1
  51. package/dist/risk-profile/index.js +61 -6
  52. package/dist/risk-profile/index.js.map +1 -1
  53. package/dist/risk-profile/index.mjs +61 -6
  54. package/dist/risk-profile/index.mjs.map +1 -1
  55. package/dist/scores/index.d.mts +1 -1
  56. package/dist/scores/index.d.ts +1 -1
  57. package/dist/scores/index.js +61 -6
  58. package/dist/scores/index.js.map +1 -1
  59. package/dist/scores/index.mjs +61 -6
  60. package/dist/scores/index.mjs.map +1 -1
  61. package/dist/tax/index.d.mts +20 -3
  62. package/dist/tax/index.d.ts +20 -3
  63. package/dist/tax/index.js +70 -9
  64. package/dist/tax/index.js.map +1 -1
  65. package/dist/tax/index.mjs +70 -9
  66. package/dist/tax/index.mjs.map +1 -1
  67. package/package.json +1 -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) {
@@ -321,6 +334,7 @@ var BaseClient = class {
321
334
  interceptors: this.interceptors,
322
335
  logger: this.logger
323
336
  };
337
+ this.authProvider = config.authProvider ?? (apiKey ? new StaticApiKeyProvider(apiKey) : void 0);
324
338
  if (config.circuitBreaker) {
325
339
  this.circuitBreaker = new CircuitBreaker(config.circuitBreaker);
326
340
  }
@@ -328,6 +342,19 @@ var BaseClient = class {
328
342
  this.rateLimitTracker = new RateLimitTracker();
329
343
  }
330
344
  }
345
+ /**
346
+ * Resolve the Idempotency-Key for a request. Mutating methods (POST/PUT/PATCH)
347
+ * get the caller-supplied key or a freshly minted UUID; non-mutating methods get
348
+ * none. requestWithRetry resolves this once and injects it so every retry reuses
349
+ * one key (letting the server dedup replays); a direct request() resolves per call.
350
+ */
351
+ resolveIdempotencyKey(method, requestOptions) {
352
+ const isMutating = ["POST", "PUT", "PATCH"].includes((method || "GET").toUpperCase());
353
+ if (!isMutating) {
354
+ return void 0;
355
+ }
356
+ return requestOptions?.idempotencyKey ?? generateUUID();
357
+ }
331
358
  /**
332
359
  * Make an HTTP request with timeout and error handling
333
360
  */
@@ -353,15 +380,20 @@ var BaseClient = class {
353
380
  ...this.config.headers,
354
381
  ...options.headers || {}
355
382
  };
356
- if (this.config.apiKey) {
357
- headers["Authorization"] = `Bearer ${this.config.apiKey}`;
383
+ const credential = await this.authProvider?.getCredential({
384
+ tenantId: this.config.tenantId,
385
+ requestId
386
+ });
387
+ if (credential) {
388
+ headers["Authorization"] = `${credential.scheme ?? "Bearer"} ${credential.token}`;
358
389
  }
359
390
  if (this.config.environment === "sandbox") {
360
391
  headers["X-Sandbox"] = "true";
361
392
  }
362
393
  const method = (options.method || "GET").toUpperCase();
363
- if (["POST", "PUT", "PATCH"].includes(method)) {
364
- headers["Idempotency-Key"] = requestOptions?.idempotencyKey || generateUUID();
394
+ const idempotencyKey = this.resolveIdempotencyKey(method, requestOptions);
395
+ if (idempotencyKey) {
396
+ headers["Idempotency-Key"] = idempotencyKey;
365
397
  }
366
398
  const controller = new AbortController();
367
399
  const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
@@ -382,10 +414,28 @@ var BaseClient = class {
382
414
  if (this.config.debug) {
383
415
  this.logger.debug(`${finalOptions.method || "GET"} ${endpoint}`);
384
416
  }
385
- const response = await fetch(url, {
417
+ let response = await fetch(url, {
386
418
  ...finalOptions,
387
419
  signal: controller.signal
388
420
  });
421
+ if (response.status === 401 && this.authProvider?.canRefresh?.()) {
422
+ const refreshed = await this.authProvider.getCredential({
423
+ tenantId: this.config.tenantId,
424
+ requestId,
425
+ forceRefresh: true
426
+ });
427
+ if (refreshed) {
428
+ this.config.onCredentialRotated?.({ reason: "unauthorized" });
429
+ finalOptions = {
430
+ ...finalOptions,
431
+ headers: {
432
+ ...finalOptions.headers,
433
+ Authorization: `${refreshed.scheme ?? "Bearer"} ${refreshed.token}`
434
+ }
435
+ };
436
+ response = await fetch(url, { ...finalOptions, signal: controller.signal });
437
+ }
438
+ }
389
439
  clearTimeout(timeoutId);
390
440
  if (this.rateLimitTracker) {
391
441
  this.rateLimitTracker.updateFromHeaders(response.headers);
@@ -474,9 +524,11 @@ var BaseClient = class {
474
524
  */
475
525
  async requestWithRetry(endpoint, options = {}, serviceURL, retries = this.config.retries, requestOptions) {
476
526
  let lastError;
527
+ const idempotencyKey = this.resolveIdempotencyKey(options.method || "GET", requestOptions);
528
+ const attemptOptions = idempotencyKey ? { ...requestOptions, idempotencyKey } : requestOptions;
477
529
  for (let attempt = 0; attempt <= retries; attempt++) {
478
530
  try {
479
- return await this.request(endpoint, options, serviceURL, requestOptions);
531
+ return await this.request(endpoint, options, serviceURL, attemptOptions);
480
532
  } catch (error) {
481
533
  lastError = error instanceof Error ? error : new Error("Unknown error");
482
534
  if (requestOptions?.signal?.aborted) {
@@ -573,6 +625,9 @@ var BaseClient = class {
573
625
  if (config.interceptors) {
574
626
  this.interceptors = config.interceptors;
575
627
  }
628
+ if (config.authProvider !== void 0 || config.apiKey !== void 0) {
629
+ this.authProvider = this.config.authProvider ?? (this.config.apiKey ? new StaticApiKeyProvider(this.config.apiKey) : void 0);
630
+ }
576
631
  }
577
632
  /**
578
633
  * Get current configuration (readonly)
@@ -600,6 +655,61 @@ var BaseClient = class {
600
655
  }
601
656
  };
602
657
 
658
+ // src/geolocation/integrity.ts
659
+ var isNil = (v) => v === null || v === void 0;
660
+ function assessGpsIntegrity(input, opts = {}) {
661
+ const flags = [];
662
+ const now = opts.now ?? (() => Date.now());
663
+ const maxAgeMs = opts.maxAgeMs ?? 6e4;
664
+ const minAccuracy = opts.minAccuracyMeters ?? 1;
665
+ const { accuracy, altitude, altitudeAccuracy, heading, speed, timestamp } = input;
666
+ if (isNil(accuracy)) {
667
+ flags.push("accuracy_missing");
668
+ } else if (accuracy === 0) {
669
+ flags.push("accuracy_zero");
670
+ } else if (accuracy < minAccuracy) {
671
+ flags.push("accuracy_implausibly_small");
672
+ }
673
+ const hasMotion = !isNil(heading) || !isNil(speed);
674
+ if (hasMotion && (isNil(accuracy) || accuracy === 0)) {
675
+ flags.push("motion_without_accuracy");
676
+ }
677
+ if (!isNil(altitude) && isNil(altitudeAccuracy)) {
678
+ flags.push("altitude_without_accuracy");
679
+ }
680
+ if (timestamp !== void 0 && now() - timestamp > maxAgeMs) {
681
+ flags.push("stale_timestamp");
682
+ }
683
+ if (opts.permissionState === "denied" || opts.permissionState === "prompt") {
684
+ flags.push(`permission_${opts.permissionState}`);
685
+ }
686
+ return { suspicious: flags.length > 0, flags };
687
+ }
688
+ function gpsIntegrityInputFromPosition(position) {
689
+ const c = position.coords;
690
+ return {
691
+ latitude: c.latitude,
692
+ longitude: c.longitude,
693
+ accuracy: c.accuracy,
694
+ altitude: c.altitude,
695
+ altitudeAccuracy: c.altitudeAccuracy,
696
+ heading: c.heading,
697
+ speed: c.speed,
698
+ timestamp: position.timestamp
699
+ };
700
+ }
701
+ async function probeGeolocationPermission() {
702
+ try {
703
+ if (typeof navigator === "undefined" || !navigator.permissions?.query) {
704
+ return "unavailable";
705
+ }
706
+ const status = await navigator.permissions.query({ name: "geolocation" });
707
+ return status.state;
708
+ } catch {
709
+ return "unavailable";
710
+ }
711
+ }
712
+
603
713
  // src/geolocation/ciphertext.ts
604
714
  var CIPHER_TEXT_EXPIRY_MINUTES = 5;
605
715
  async function computeHMAC(key, message) {
@@ -652,6 +762,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
652
762
  if (typeof navigator === "undefined" || !navigator.geolocation) {
653
763
  return null;
654
764
  }
765
+ const permissionState = await probeGeolocationPermission();
655
766
  return new Promise((resolve) => {
656
767
  navigator.geolocation.getCurrentPosition(
657
768
  (position) => {
@@ -668,6 +779,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
668
779
  resolve(null);
669
780
  return;
670
781
  }
782
+ const { flags } = assessGpsIntegrity(gpsIntegrityInputFromPosition(position), { permissionState });
671
783
  resolve({
672
784
  latitude,
673
785
  longitude,
@@ -676,7 +788,8 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
676
788
  altitude_accuracy: position.coords.altitudeAccuracy ?? void 0,
677
789
  heading: position.coords.heading ?? void 0,
678
790
  speed: position.coords.speed ?? void 0,
679
- timestamp: position.timestamp
791
+ timestamp: position.timestamp,
792
+ integrity_flags: flags.length ? flags : void 0
680
793
  });
681
794
  },
682
795
  () => {
@@ -743,6 +856,9 @@ async function generateCipherText(options, config) {
743
856
  );
744
857
  if (location) {
745
858
  locationData = location;
859
+ if (location.integrity_flags?.length) {
860
+ warnings.push(`GPS integrity flags (advisory): ${location.integrity_flags.join(", ")}`);
861
+ }
746
862
  } else if (gpsRequiredByConfig) {
747
863
  throw new VesantError(
748
864
  `GPS location is required for ${options.reason} by tenant configuration, but GPS was not available or permission was denied`,
@@ -862,8 +978,8 @@ var GeolocationClient = class extends BaseClient {
862
978
  * ```
863
979
  */
864
980
  async verifyIP(request, requestOptions) {
865
- if (!request.ip_address?.trim()) {
866
- throw new ValidationError("ip_address is required and must be a non-empty string", ["ip_address"]);
981
+ if (request.ip_address !== void 0 && !request.ip_address.trim()) {
982
+ throw new ValidationError("ip_address, when provided, must be a non-empty string", ["ip_address"]);
867
983
  }
868
984
  return this.requestWithRetry("/api/v1/geo/verify", {
869
985
  method: "POST",
@@ -1213,20 +1329,12 @@ var GeolocationClient = class extends BaseClient {
1213
1329
  *
1214
1330
  * @example
1215
1331
  * ```typescript
1216
- * // Using GPS (preferred)
1332
+ * // GPS (the web SDK is GPS + IP only; the server handles the IP fallback)
1217
1333
  * const result = await client.captureLocation(token, {
1218
1334
  * latitude: 37.7749,
1219
1335
  * longitude: -122.4194,
1220
1336
  * accuracy: 10
1221
1337
  * });
1222
- *
1223
- * // Using WiFi positioning (fallback)
1224
- * const result = await client.captureLocation(token, {
1225
- * wifi_networks: [
1226
- * { macAddress: "00:11:22:33:44:55", signalStrength: -50 },
1227
- * { macAddress: "AA:BB:CC:DD:EE:FF", signalStrength: -70 }
1228
- * ]
1229
- * });
1230
1338
  * ```
1231
1339
  */
1232
1340
  async captureLocation(token, capture, requestOptions) {
@@ -1274,8 +1382,11 @@ var GeolocationClient = class extends BaseClient {
1274
1382
  };
1275
1383
 
1276
1384
  exports.GeolocationClient = GeolocationClient;
1385
+ exports.assessGpsIntegrity = assessGpsIntegrity;
1277
1386
  exports.decodeCipherText = decodeCipherText;
1278
1387
  exports.generateCipherText = generateCipherText;
1388
+ exports.gpsIntegrityInputFromPosition = gpsIntegrityInputFromPosition;
1279
1389
  exports.isCipherTextExpired = isCipherTextExpired;
1390
+ exports.probeGeolocationPermission = probeGeolocationPermission;
1280
1391
  //# sourceMappingURL=index.js.map
1281
1392
  //# sourceMappingURL=index.js.map