vesant-sdk 1.7.0 → 1.7.1-dev.0520b46

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-B0qhE2kr.d.mts → client-5q4whhGu.d.mts} +2 -2
  2. package/dist/{client-DF7hlMEz.d.ts → client-BaUekQT8.d.ts} +96 -52
  3. package/dist/{client-DtH2RLuy.d.ts → client-DUHC-68_.d.ts} +2 -2
  4. package/dist/{client-DrjgZoH_.d.mts → client-XDEhh9VN.d.mts} +96 -52
  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 +218 -90
  10. package/dist/compliance/index.js.map +1 -1
  11. package/dist/compliance/index.mjs +218 -90
  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 +69 -8
  16. package/dist/decisions/index.js.map +1 -1
  17. package/dist/decisions/index.mjs +69 -8
  18. package/dist/decisions/index.mjs.map +1 -1
  19. package/dist/geolocation/index.d.mts +68 -7
  20. package/dist/geolocation/index.d.ts +68 -7
  21. package/dist/geolocation/index.js +223 -90
  22. package/dist/geolocation/index.js.map +1 -1
  23. package/dist/geolocation/index.mjs +220 -91
  24. package/dist/geolocation/index.mjs.map +1 -1
  25. package/dist/index-C3zUKydT.d.mts +264 -0
  26. package/dist/index-DSDgS09k.d.ts +264 -0
  27. package/dist/index.d.mts +27 -10
  28. package/dist/index.d.ts +27 -10
  29. package/dist/index.js +418 -126
  30. package/dist/index.js.map +1 -1
  31. package/dist/index.mjs +409 -127
  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 +102 -21
  36. package/dist/kyc/core.js.map +1 -1
  37. package/dist/kyc/core.mjs +102 -22
  38. package/dist/kyc/core.mjs.map +1 -1
  39. package/dist/kyc/index.d.mts +154 -30
  40. package/dist/kyc/index.d.ts +154 -30
  41. package/dist/kyc/index.js +102 -21
  42. package/dist/kyc/index.js.map +1 -1
  43. package/dist/kyc/index.mjs +102 -22
  44. package/dist/kyc/index.mjs.map +1 -1
  45. package/dist/react.d.mts +14 -3
  46. package/dist/react.d.ts +14 -3
  47. package/dist/react.js +317 -68
  48. package/dist/react.js.map +1 -1
  49. package/dist/react.mjs +317 -68
  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 +69 -8
  54. package/dist/risk-profile/index.js.map +1 -1
  55. package/dist/risk-profile/index.mjs +69 -8
  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 +69 -8
  60. package/dist/scores/index.js.map +1 -1
  61. package/dist/scores/index.mjs +69 -8
  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 +74 -10
  66. package/dist/tax/index.js.map +1 -1
  67. package/dist/tax/index.mjs +74 -10
  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,3 +1,16 @@
1
+ // src/core/auth.ts
2
+ var StaticApiKeyProvider = class {
3
+ constructor(apiKey) {
4
+ this.apiKey = apiKey;
5
+ }
6
+ async getCredential() {
7
+ return this.apiKey ? { scheme: "Bearer", token: this.apiKey } : null;
8
+ }
9
+ canRefresh() {
10
+ return false;
11
+ }
12
+ };
13
+
1
14
  // src/core/errors.ts
2
15
  var VesantError = class _VesantError extends Error {
3
16
  constructor(message, code, statusCode, details) {
@@ -214,7 +227,7 @@ function createConsoleLogger() {
214
227
  }
215
228
 
216
229
  // src/core/version.ts
217
- var SDK_VERSION = "1.7.0";
230
+ var SDK_VERSION = "1.7.1";
218
231
 
219
232
  // src/shared/browser-utils.ts
220
233
  function generateUUID() {
@@ -296,6 +309,12 @@ var BaseClient = class {
296
309
  if (!config.tenantId?.trim()) {
297
310
  throw new ValidationError("tenantId is required and must be a non-empty string", ["tenantId"]);
298
311
  }
312
+ if (typeof fetch === "undefined") {
313
+ throw new VesantError(
314
+ "The Vesant SDK requires a global fetch (Node.js >= 18). Upgrade Node or provide a fetch polyfill.",
315
+ "RUNTIME_UNSUPPORTED"
316
+ );
317
+ }
299
318
  this.interceptors = config.interceptors || [];
300
319
  this.logger = config.logger || createConsoleLogger();
301
320
  let environment = config.environment;
@@ -314,11 +333,12 @@ var BaseClient = class {
314
333
  environment,
315
334
  headers: config.headers || {},
316
335
  timeout: config.timeout || 1e4,
317
- retries: config.retries || 3,
336
+ retries: config.retries ?? 3,
318
337
  debug: config.debug || false,
319
338
  interceptors: this.interceptors,
320
339
  logger: this.logger
321
340
  };
341
+ this.authProvider = config.authProvider ?? (apiKey ? new StaticApiKeyProvider(apiKey) : void 0);
322
342
  if (config.circuitBreaker) {
323
343
  this.circuitBreaker = new CircuitBreaker(config.circuitBreaker);
324
344
  }
@@ -326,6 +346,19 @@ var BaseClient = class {
326
346
  this.rateLimitTracker = new RateLimitTracker();
327
347
  }
328
348
  }
349
+ /**
350
+ * Resolve the Idempotency-Key for a request. Mutating methods (POST/PUT/PATCH)
351
+ * get the caller-supplied key or a freshly minted UUID; non-mutating methods get
352
+ * none. requestWithRetry resolves this once and injects it so every retry reuses
353
+ * one key (letting the server dedup replays); a direct request() resolves per call.
354
+ */
355
+ resolveIdempotencyKey(method, requestOptions) {
356
+ const isMutating = ["POST", "PUT", "PATCH"].includes((method || "GET").toUpperCase());
357
+ if (!isMutating) {
358
+ return void 0;
359
+ }
360
+ return requestOptions?.idempotencyKey ?? generateUUID();
361
+ }
329
362
  /**
330
363
  * Make an HTTP request with timeout and error handling
331
364
  */
@@ -351,15 +384,20 @@ var BaseClient = class {
351
384
  ...this.config.headers,
352
385
  ...options.headers || {}
353
386
  };
354
- if (this.config.apiKey) {
355
- headers["Authorization"] = `Bearer ${this.config.apiKey}`;
387
+ const credential = await this.authProvider?.getCredential({
388
+ tenantId: this.config.tenantId,
389
+ requestId
390
+ });
391
+ if (credential) {
392
+ headers["Authorization"] = `${credential.scheme ?? "Bearer"} ${credential.token}`;
356
393
  }
357
394
  if (this.config.environment === "sandbox") {
358
395
  headers["X-Sandbox"] = "true";
359
396
  }
360
397
  const method = (options.method || "GET").toUpperCase();
361
- if (["POST", "PUT", "PATCH"].includes(method)) {
362
- headers["Idempotency-Key"] = requestOptions?.idempotencyKey || generateUUID();
398
+ const idempotencyKey = this.resolveIdempotencyKey(method, requestOptions);
399
+ if (idempotencyKey) {
400
+ headers["Idempotency-Key"] = idempotencyKey;
363
401
  }
364
402
  const controller = new AbortController();
365
403
  const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
@@ -380,10 +418,28 @@ var BaseClient = class {
380
418
  if (this.config.debug) {
381
419
  this.logger.debug(`${finalOptions.method || "GET"} ${endpoint}`);
382
420
  }
383
- const response = await fetch(url, {
421
+ let response = await fetch(url, {
384
422
  ...finalOptions,
385
423
  signal: controller.signal
386
424
  });
425
+ if (response.status === 401 && this.authProvider?.canRefresh?.()) {
426
+ const refreshed = await this.authProvider.getCredential({
427
+ tenantId: this.config.tenantId,
428
+ requestId,
429
+ forceRefresh: true
430
+ });
431
+ if (refreshed) {
432
+ this.config.onCredentialRotated?.({ reason: "unauthorized" });
433
+ finalOptions = {
434
+ ...finalOptions,
435
+ headers: {
436
+ ...finalOptions.headers,
437
+ Authorization: `${refreshed.scheme ?? "Bearer"} ${refreshed.token}`
438
+ }
439
+ };
440
+ response = await fetch(url, { ...finalOptions, signal: controller.signal });
441
+ }
442
+ }
387
443
  clearTimeout(timeoutId);
388
444
  if (this.rateLimitTracker) {
389
445
  this.rateLimitTracker.updateFromHeaders(response.headers);
@@ -472,9 +528,11 @@ var BaseClient = class {
472
528
  */
473
529
  async requestWithRetry(endpoint, options = {}, serviceURL, retries = this.config.retries, requestOptions) {
474
530
  let lastError;
531
+ const idempotencyKey = this.resolveIdempotencyKey(options.method || "GET", requestOptions);
532
+ const attemptOptions = idempotencyKey ? { ...requestOptions, idempotencyKey } : requestOptions;
475
533
  for (let attempt = 0; attempt <= retries; attempt++) {
476
534
  try {
477
- return await this.request(endpoint, options, serviceURL, requestOptions);
535
+ return await this.request(endpoint, options, serviceURL, attemptOptions);
478
536
  } catch (error) {
479
537
  lastError = error instanceof Error ? error : new Error("Unknown error");
480
538
  if (requestOptions?.signal?.aborted) {
@@ -571,6 +629,9 @@ var BaseClient = class {
571
629
  if (config.interceptors) {
572
630
  this.interceptors = config.interceptors;
573
631
  }
632
+ if (config.authProvider !== void 0 || config.apiKey !== void 0) {
633
+ this.authProvider = this.config.authProvider ?? (this.config.apiKey ? new StaticApiKeyProvider(this.config.apiKey) : void 0);
634
+ }
574
635
  }
575
636
  /**
576
637
  * Get current configuration (readonly)
@@ -598,27 +659,63 @@ var BaseClient = class {
598
659
  }
599
660
  };
600
661
 
601
- // src/geolocation/ciphertext.ts
602
- var CIPHER_TEXT_EXPIRY_MINUTES = 5;
603
- async function computeHMAC(key, message) {
604
- if (typeof globalThis.crypto !== "undefined" && globalThis.crypto.subtle) {
605
- const encoder = new TextEncoder();
606
- const keyData = encoder.encode(key);
607
- const msgData = encoder.encode(message);
608
- const cryptoKey = await globalThis.crypto.subtle.importKey(
609
- "raw",
610
- keyData,
611
- { name: "HMAC", hash: "SHA-256" },
612
- false,
613
- ["sign"]
614
- );
615
- const signature = await globalThis.crypto.subtle.sign("HMAC", cryptoKey, msgData);
616
- const bytes = new Uint8Array(signature);
617
- return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
662
+ // src/geolocation/integrity.ts
663
+ var isNil = (v) => v === null || v === void 0;
664
+ function assessGpsIntegrity(input, opts = {}) {
665
+ const flags = [];
666
+ const now = opts.now ?? (() => Date.now());
667
+ const maxAgeMs = opts.maxAgeMs ?? 6e4;
668
+ const minAccuracy = opts.minAccuracyMeters ?? 1;
669
+ const { accuracy, altitude, altitudeAccuracy, heading, speed, timestamp } = input;
670
+ if (isNil(accuracy)) {
671
+ flags.push("accuracy_missing");
672
+ } else if (accuracy === 0) {
673
+ flags.push("accuracy_zero");
674
+ } else if (accuracy < minAccuracy) {
675
+ flags.push("accuracy_implausibly_small");
676
+ }
677
+ const hasMotion = !isNil(heading) || !isNil(speed);
678
+ if (hasMotion && (isNil(accuracy) || accuracy === 0)) {
679
+ flags.push("motion_without_accuracy");
680
+ }
681
+ if (!isNil(altitude) && isNil(altitudeAccuracy)) {
682
+ flags.push("altitude_without_accuracy");
683
+ }
684
+ if (timestamp !== void 0 && now() - timestamp > maxAgeMs) {
685
+ flags.push("stale_timestamp");
618
686
  }
619
- const { createHmac } = await import('crypto');
620
- return createHmac("sha256", key).update(message).digest("hex");
687
+ if (opts.permissionState === "denied" || opts.permissionState === "prompt") {
688
+ flags.push(`permission_${opts.permissionState}`);
689
+ }
690
+ return { suspicious: flags.length > 0, flags };
621
691
  }
692
+ function gpsIntegrityInputFromPosition(position) {
693
+ const c = position.coords;
694
+ return {
695
+ latitude: c.latitude,
696
+ longitude: c.longitude,
697
+ accuracy: c.accuracy,
698
+ altitude: c.altitude,
699
+ altitudeAccuracy: c.altitudeAccuracy,
700
+ heading: c.heading,
701
+ speed: c.speed,
702
+ timestamp: position.timestamp
703
+ };
704
+ }
705
+ async function probeGeolocationPermission() {
706
+ try {
707
+ if (typeof navigator === "undefined" || !navigator.permissions?.query) {
708
+ return "unavailable";
709
+ }
710
+ const status = await navigator.permissions.query({ name: "geolocation" });
711
+ return status.state;
712
+ } catch {
713
+ return "unavailable";
714
+ }
715
+ }
716
+
717
+ // src/geolocation/ciphertext.ts
718
+ var CIPHER_TEXT_EXPIRY_MINUTES = 5;
622
719
  function getWebGLInfo() {
623
720
  if (typeof document === "undefined") return null;
624
721
  try {
@@ -650,6 +747,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
650
747
  if (typeof navigator === "undefined" || !navigator.geolocation) {
651
748
  return null;
652
749
  }
750
+ const permissionState = await probeGeolocationPermission();
653
751
  return new Promise((resolve) => {
654
752
  navigator.geolocation.getCurrentPosition(
655
753
  (position) => {
@@ -666,6 +764,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
666
764
  resolve(null);
667
765
  return;
668
766
  }
767
+ const { flags } = assessGpsIntegrity(gpsIntegrityInputFromPosition(position), { permissionState });
669
768
  resolve({
670
769
  latitude,
671
770
  longitude,
@@ -674,7 +773,8 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
674
773
  altitude_accuracy: position.coords.altitudeAccuracy ?? void 0,
675
774
  heading: position.coords.heading ?? void 0,
676
775
  speed: position.coords.speed ?? void 0,
677
- timestamp: position.timestamp
776
+ timestamp: position.timestamp,
777
+ integrity_flags: flags.length ? flags : void 0
678
778
  });
679
779
  },
680
780
  () => {
@@ -741,6 +841,9 @@ async function generateCipherText(options, config) {
741
841
  );
742
842
  if (location) {
743
843
  locationData = location;
844
+ if (location.integrity_flags?.length) {
845
+ warnings.push(`GPS integrity flags (advisory): ${location.integrity_flags.join(", ")}`);
846
+ }
744
847
  } else if (gpsRequiredByConfig) {
745
848
  throw new VesantError(
746
849
  `GPS location is required for ${options.reason} by tenant configuration, but GPS was not available or permission was denied`,
@@ -770,15 +873,7 @@ async function generateCipherText(options, config) {
770
873
  };
771
874
  const encoded = encodePayload(payload);
772
875
  const timestamp = now.getTime().toString(36);
773
- let cipherText;
774
- const hmacKey = options.signingKey || options.apiKey;
775
- if (hmacKey) {
776
- const message = `02.${timestamp}.${encoded}`;
777
- const hmac = await computeHMAC(hmacKey, message);
778
- cipherText = `${message}.${hmac}`;
779
- } else {
780
- cipherText = `01.${timestamp}.${encoded}`;
781
- }
876
+ const cipherText = `01.${timestamp}.${encoded}`;
782
877
  return {
783
878
  cipherText,
784
879
  locationCaptured: !!locationData,
@@ -787,6 +882,7 @@ async function generateCipherText(options, config) {
787
882
  expiresAt: expiry.toISOString()
788
883
  };
789
884
  }
885
+ var collectDeviceSignals = generateCipherText;
790
886
  function decodeCipherText(cipherText) {
791
887
  try {
792
888
  const parts = cipherText.split(".");
@@ -814,6 +910,7 @@ function isCipherTextExpired(cipherText) {
814
910
  }
815
911
 
816
912
  // src/geolocation/client.ts
913
+ var DEFAULT_GPS_CONFIG_TTL_MS = 5 * 60 * 1e3;
817
914
  var GeolocationClient = class extends BaseClient {
818
915
  constructor(config) {
819
916
  const baseConfig = {
@@ -829,6 +926,8 @@ var GeolocationClient = class extends BaseClient {
829
926
  environment: config.environment
830
927
  };
831
928
  super(baseConfig);
929
+ this.gpsConfigCache = null;
930
+ this.gpsConfigTtlMs = config.gpsConfigTtlMs ?? DEFAULT_GPS_CONFIG_TTL_MS;
832
931
  }
833
932
  // ============================================================================
834
933
  // IP Verification & Compliance
@@ -860,8 +959,8 @@ var GeolocationClient = class extends BaseClient {
860
959
  * ```
861
960
  */
862
961
  async verifyIP(request, requestOptions) {
863
- if (!request.ip_address?.trim()) {
864
- throw new ValidationError("ip_address is required and must be a non-empty string", ["ip_address"]);
962
+ if (request.ip_address !== void 0 && !request.ip_address.trim()) {
963
+ throw new ValidationError("ip_address, when provided, must be a non-empty string", ["ip_address"]);
865
964
  }
866
965
  return this.requestWithRetry("/api/v1/geo/verify", {
867
966
  method: "POST",
@@ -914,37 +1013,85 @@ var GeolocationClient = class extends BaseClient {
914
1013
  * ```
915
1014
  */
916
1015
  async getGPSConfig(requestOptions) {
917
- const config = await this.requestWithRetry("/api/v1/geo/config", void 0, void 0, void 0, requestOptions);
918
- if (config.signing_key) {
919
- this.cachedSigningKey = config.signing_key;
1016
+ const cached = this.gpsConfigCache;
1017
+ if (cached && cached.expiresAt > Date.now()) {
1018
+ return cached.value;
920
1019
  }
921
- return config;
1020
+ return this.refreshGPSConfig(requestOptions);
922
1021
  }
923
1022
  /**
924
- * Fetch the signing key from the dedicated authenticated endpoint.
1023
+ * Re-read the tenant's GPS requirement configuration, ignoring any copy held
1024
+ * from an earlier read.
925
1025
  *
926
- * Falls back to getGPSConfig() for backward compatibility with older servers
927
- * that don't expose `/api/v1/geo/signing-key`.
1026
+ * These requirements are edited in the compliance console while your
1027
+ * application is running. `getGPSConfig` reuses a fetched copy for a short
1028
+ * period so a long-lived session does not call the API on every event; call
1029
+ * this when you need a change to take effect immediately — for example right
1030
+ * after an administrator saves new settings.
928
1031
  *
929
- * @returns The signing key string, or undefined if unavailable
1032
+ * @returns The current GPS requirement config per event type
1033
+ *
1034
+ * @example
1035
+ * ```typescript
1036
+ * const config = await client.refreshGPSConfig();
1037
+ * if (config.require_gps.login) {
1038
+ * // GPS is now required for login
1039
+ * }
1040
+ * ```
1041
+ */
1042
+ async refreshGPSConfig(requestOptions) {
1043
+ const value = await this.requestWithRetry(
1044
+ "/api/v1/geo/config",
1045
+ void 0,
1046
+ void 0,
1047
+ void 0,
1048
+ requestOptions
1049
+ );
1050
+ this.gpsConfigCache = { value, expiresAt: Date.now() + this.gpsConfigTtlMs };
1051
+ return value;
1052
+ }
1053
+ /**
1054
+ * Mint a short-lived, single-use device-signals nonce.
1055
+ *
1056
+ * The nonce is bound to the tenant, user, and event type and is consumed
1057
+ * server-side during validation, so a captured device-signals envelope cannot
1058
+ * be replayed. `validateCipherText` mints and attaches one automatically; call
1059
+ * this directly only if you manage the nonce yourself.
1060
+ *
1061
+ * @param userId - User ID the nonce is bound to
1062
+ * @param eventType - Event type the nonce is bound to (login, registration, ...)
1063
+ * @returns The nonce and its expiry
1064
+ */
1065
+ async fetchSignalsNonce(userId, eventType, requestOptions) {
1066
+ if (!userId?.trim()) {
1067
+ throw new ValidationError("userId is required and must be a non-empty string", ["userId"]);
1068
+ }
1069
+ const request = { user_id: userId, event_type: eventType };
1070
+ return this.request(
1071
+ "/api/v1/geo/signals-token",
1072
+ {
1073
+ method: "POST",
1074
+ body: JSON.stringify(request)
1075
+ },
1076
+ void 0,
1077
+ requestOptions
1078
+ );
1079
+ }
1080
+ /**
1081
+ * Best-effort nonce mint for validation. Returns undefined if minting fails —
1082
+ * the server is the sole authority and blocks when a nonce is required, so this
1083
+ * never downgrades security on the client's say-so.
930
1084
  */
931
- async fetchSigningKey(requestOptions) {
1085
+ async resolveSignalsNonce(userId, eventType, requestOptions) {
932
1086
  try {
933
- const response = await this.requestWithRetry(
934
- "/api/v1/geo/signing-key",
935
- void 0,
936
- void 0,
937
- void 0,
938
- requestOptions
1087
+ const { nonce } = await this.fetchSignalsNonce(userId, eventType, requestOptions);
1088
+ return nonce;
1089
+ } catch (err) {
1090
+ this.logger.warn(
1091
+ `Failed to mint device-signals nonce; proceeding without it: ${err instanceof Error ? err.message : String(err)}`
939
1092
  );
940
- if (response.signing_key) {
941
- this.cachedSigningKey = response.signing_key;
942
- return response.signing_key;
943
- }
944
- } catch {
1093
+ return void 0;
945
1094
  }
946
- const config = await this.getGPSConfig(requestOptions);
947
- return config.signing_key;
948
1095
  }
949
1096
  // ============================================================================
950
1097
  // CipherText Validation
@@ -997,12 +1144,14 @@ var GeolocationClient = class extends BaseClient {
997
1144
  if (!userId?.trim()) {
998
1145
  throw new ValidationError("userId is required and must be a non-empty string", ["userId"]);
999
1146
  }
1147
+ const nonce = await this.resolveSignalsNonce(userId, eventType, requestOptions);
1000
1148
  const request = {
1001
1149
  cipher_text: cipherText,
1002
1150
  user_id: userId,
1003
1151
  event_type: eventType,
1004
1152
  expected_ip: expectedIP,
1005
- customer_data: customerData
1153
+ customer_data: customerData,
1154
+ nonce
1006
1155
  };
1007
1156
  return this.requestWithRetry(
1008
1157
  "/api/v1/geo/validate-ciphertext",
@@ -1211,20 +1360,12 @@ var GeolocationClient = class extends BaseClient {
1211
1360
  *
1212
1361
  * @example
1213
1362
  * ```typescript
1214
- * // Using GPS (preferred)
1363
+ * // GPS (the web SDK is GPS + IP only; the server handles the IP fallback)
1215
1364
  * const result = await client.captureLocation(token, {
1216
1365
  * latitude: 37.7749,
1217
1366
  * longitude: -122.4194,
1218
1367
  * accuracy: 10
1219
1368
  * });
1220
- *
1221
- * // Using WiFi positioning (fallback)
1222
- * const result = await client.captureLocation(token, {
1223
- * wifi_networks: [
1224
- * { macAddress: "00:11:22:33:44:55", signalStrength: -50 },
1225
- * { macAddress: "AA:BB:CC:DD:EE:FF", signalStrength: -70 }
1226
- * ]
1227
- * });
1228
1369
  * ```
1229
1370
  */
1230
1371
  async captureLocation(token, capture, requestOptions) {
@@ -1237,40 +1378,28 @@ var GeolocationClient = class extends BaseClient {
1237
1378
  // CipherText Generation
1238
1379
  // ============================================================================
1239
1380
  /**
1240
- * Generate a signed cipherText containing device and location data.
1381
+ * Generate a device-signals envelope containing device and location data,
1382
+ * validated by the server.
1241
1383
  *
1242
- * Automatically passes the client's API key for HMAC signing (v02 format).
1243
- * If no API key is configured, falls back to unsigned v01 format.
1244
- *
1245
- * @param options - Options for cipherText generation
1384
+ * @param options - Options for envelope generation
1246
1385
  * @param gpsConfig - Optional GPS config (from getGPSConfig)
1247
- * @returns CipherText result with the signed string
1386
+ * @returns The device-signals envelope result
1248
1387
  *
1249
1388
  * @example
1250
1389
  * ```typescript
1251
1390
  * const result = await client.generateCipherText({ reason: 'login' });
1252
- * console.log(result.cipherText); // v02 signed cipherText
1391
+ * console.log(result.cipherText); // device-signals envelope
1253
1392
  * ```
1254
1393
  */
1255
1394
  async generateCipherText(options, gpsConfig) {
1256
- let signingKey = this.cachedSigningKey;
1257
- let resolvedGpsConfig = gpsConfig;
1258
- if (!signingKey) {
1259
- signingKey = await this.fetchSigningKey();
1260
- }
1261
- if (!resolvedGpsConfig) {
1262
- resolvedGpsConfig = await this.getGPSConfig();
1263
- }
1264
- return generateCipherText(
1265
- { ...options, signingKey: signingKey || void 0 },
1266
- resolvedGpsConfig
1267
- );
1395
+ const resolvedGpsConfig = gpsConfig ?? await this.getGPSConfig();
1396
+ return generateCipherText(options, resolvedGpsConfig);
1268
1397
  }
1269
1398
  // ============================================================================
1270
1399
  // Utility Methods (inherited from BaseClient: healthCheck, updateConfig, getConfig, buildQueryString)
1271
1400
  // ============================================================================
1272
1401
  };
1273
1402
 
1274
- export { GeolocationClient, decodeCipherText, generateCipherText, isCipherTextExpired };
1403
+ export { GeolocationClient, assessGpsIntegrity, collectDeviceSignals, decodeCipherText, generateCipherText, gpsIntegrityInputFromPosition, isCipherTextExpired, probeGeolocationPermission };
1275
1404
  //# sourceMappingURL=index.mjs.map
1276
1405
  //# sourceMappingURL=index.mjs.map