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
@@ -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) {
@@ -299,7 +312,7 @@ function createConsoleLogger() {
299
312
  }
300
313
 
301
314
  // src/core/version.ts
302
- var SDK_VERSION = "1.7.0";
315
+ var SDK_VERSION = "1.7.1";
303
316
 
304
317
  // src/shared/browser-utils.ts
305
318
  function generateUUID() {
@@ -381,6 +394,12 @@ var BaseClient = class {
381
394
  if (!config.tenantId?.trim()) {
382
395
  throw new ValidationError("tenantId is required and must be a non-empty string", ["tenantId"]);
383
396
  }
397
+ if (typeof fetch === "undefined") {
398
+ throw new VesantError(
399
+ "The Vesant SDK requires a global fetch (Node.js >= 18). Upgrade Node or provide a fetch polyfill.",
400
+ "RUNTIME_UNSUPPORTED"
401
+ );
402
+ }
384
403
  this.interceptors = config.interceptors || [];
385
404
  this.logger = config.logger || createConsoleLogger();
386
405
  let environment = config.environment;
@@ -399,11 +418,12 @@ var BaseClient = class {
399
418
  environment,
400
419
  headers: config.headers || {},
401
420
  timeout: config.timeout || 1e4,
402
- retries: config.retries || 3,
421
+ retries: config.retries ?? 3,
403
422
  debug: config.debug || false,
404
423
  interceptors: this.interceptors,
405
424
  logger: this.logger
406
425
  };
426
+ this.authProvider = config.authProvider ?? (apiKey ? new StaticApiKeyProvider(apiKey) : void 0);
407
427
  if (config.circuitBreaker) {
408
428
  this.circuitBreaker = new CircuitBreaker(config.circuitBreaker);
409
429
  }
@@ -411,6 +431,19 @@ var BaseClient = class {
411
431
  this.rateLimitTracker = new RateLimitTracker();
412
432
  }
413
433
  }
434
+ /**
435
+ * Resolve the Idempotency-Key for a request. Mutating methods (POST/PUT/PATCH)
436
+ * get the caller-supplied key or a freshly minted UUID; non-mutating methods get
437
+ * none. requestWithRetry resolves this once and injects it so every retry reuses
438
+ * one key (letting the server dedup replays); a direct request() resolves per call.
439
+ */
440
+ resolveIdempotencyKey(method, requestOptions) {
441
+ const isMutating = ["POST", "PUT", "PATCH"].includes((method || "GET").toUpperCase());
442
+ if (!isMutating) {
443
+ return void 0;
444
+ }
445
+ return requestOptions?.idempotencyKey ?? generateUUID();
446
+ }
414
447
  /**
415
448
  * Make an HTTP request with timeout and error handling
416
449
  */
@@ -436,15 +469,20 @@ var BaseClient = class {
436
469
  ...this.config.headers,
437
470
  ...options.headers || {}
438
471
  };
439
- if (this.config.apiKey) {
440
- headers["Authorization"] = `Bearer ${this.config.apiKey}`;
472
+ const credential = await this.authProvider?.getCredential({
473
+ tenantId: this.config.tenantId,
474
+ requestId
475
+ });
476
+ if (credential) {
477
+ headers["Authorization"] = `${credential.scheme ?? "Bearer"} ${credential.token}`;
441
478
  }
442
479
  if (this.config.environment === "sandbox") {
443
480
  headers["X-Sandbox"] = "true";
444
481
  }
445
482
  const method = (options.method || "GET").toUpperCase();
446
- if (["POST", "PUT", "PATCH"].includes(method)) {
447
- headers["Idempotency-Key"] = requestOptions?.idempotencyKey || generateUUID();
483
+ const idempotencyKey = this.resolveIdempotencyKey(method, requestOptions);
484
+ if (idempotencyKey) {
485
+ headers["Idempotency-Key"] = idempotencyKey;
448
486
  }
449
487
  const controller = new AbortController();
450
488
  const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
@@ -465,10 +503,28 @@ var BaseClient = class {
465
503
  if (this.config.debug) {
466
504
  this.logger.debug(`${finalOptions.method || "GET"} ${endpoint}`);
467
505
  }
468
- const response = await fetch(url, {
506
+ let response = await fetch(url, {
469
507
  ...finalOptions,
470
508
  signal: controller.signal
471
509
  });
510
+ if (response.status === 401 && this.authProvider?.canRefresh?.()) {
511
+ const refreshed = await this.authProvider.getCredential({
512
+ tenantId: this.config.tenantId,
513
+ requestId,
514
+ forceRefresh: true
515
+ });
516
+ if (refreshed) {
517
+ this.config.onCredentialRotated?.({ reason: "unauthorized" });
518
+ finalOptions = {
519
+ ...finalOptions,
520
+ headers: {
521
+ ...finalOptions.headers,
522
+ Authorization: `${refreshed.scheme ?? "Bearer"} ${refreshed.token}`
523
+ }
524
+ };
525
+ response = await fetch(url, { ...finalOptions, signal: controller.signal });
526
+ }
527
+ }
472
528
  clearTimeout(timeoutId);
473
529
  if (this.rateLimitTracker) {
474
530
  this.rateLimitTracker.updateFromHeaders(response.headers);
@@ -557,9 +613,11 @@ var BaseClient = class {
557
613
  */
558
614
  async requestWithRetry(endpoint, options = {}, serviceURL, retries = this.config.retries, requestOptions) {
559
615
  let lastError;
616
+ const idempotencyKey = this.resolveIdempotencyKey(options.method || "GET", requestOptions);
617
+ const attemptOptions = idempotencyKey ? { ...requestOptions, idempotencyKey } : requestOptions;
560
618
  for (let attempt = 0; attempt <= retries; attempt++) {
561
619
  try {
562
- return await this.request(endpoint, options, serviceURL, requestOptions);
620
+ return await this.request(endpoint, options, serviceURL, attemptOptions);
563
621
  } catch (error) {
564
622
  lastError = error instanceof Error ? error : new Error("Unknown error");
565
623
  if (requestOptions?.signal?.aborted) {
@@ -656,6 +714,9 @@ var BaseClient = class {
656
714
  if (config.interceptors) {
657
715
  this.interceptors = config.interceptors;
658
716
  }
717
+ if (config.authProvider !== void 0 || config.apiKey !== void 0) {
718
+ this.authProvider = this.config.authProvider ?? (this.config.apiKey ? new StaticApiKeyProvider(this.config.apiKey) : void 0);
719
+ }
659
720
  }
660
721
  /**
661
722
  * Get current configuration (readonly)
@@ -683,27 +744,63 @@ var BaseClient = class {
683
744
  }
684
745
  };
685
746
 
686
- // src/geolocation/ciphertext.ts
687
- var CIPHER_TEXT_EXPIRY_MINUTES = 5;
688
- async function computeHMAC(key, message) {
689
- if (typeof globalThis.crypto !== "undefined" && globalThis.crypto.subtle) {
690
- const encoder = new TextEncoder();
691
- const keyData = encoder.encode(key);
692
- const msgData = encoder.encode(message);
693
- const cryptoKey = await globalThis.crypto.subtle.importKey(
694
- "raw",
695
- keyData,
696
- { name: "HMAC", hash: "SHA-256" },
697
- false,
698
- ["sign"]
699
- );
700
- const signature = await globalThis.crypto.subtle.sign("HMAC", cryptoKey, msgData);
701
- const bytes = new Uint8Array(signature);
702
- return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
747
+ // src/geolocation/integrity.ts
748
+ var isNil = (v) => v === null || v === void 0;
749
+ function assessGpsIntegrity(input, opts = {}) {
750
+ const flags = [];
751
+ const now = opts.now ?? (() => Date.now());
752
+ const maxAgeMs = opts.maxAgeMs ?? 6e4;
753
+ const minAccuracy = opts.minAccuracyMeters ?? 1;
754
+ const { accuracy, altitude, altitudeAccuracy, heading, speed, timestamp } = input;
755
+ if (isNil(accuracy)) {
756
+ flags.push("accuracy_missing");
757
+ } else if (accuracy === 0) {
758
+ flags.push("accuracy_zero");
759
+ } else if (accuracy < minAccuracy) {
760
+ flags.push("accuracy_implausibly_small");
761
+ }
762
+ const hasMotion = !isNil(heading) || !isNil(speed);
763
+ if (hasMotion && (isNil(accuracy) || accuracy === 0)) {
764
+ flags.push("motion_without_accuracy");
765
+ }
766
+ if (!isNil(altitude) && isNil(altitudeAccuracy)) {
767
+ flags.push("altitude_without_accuracy");
768
+ }
769
+ if (timestamp !== void 0 && now() - timestamp > maxAgeMs) {
770
+ flags.push("stale_timestamp");
771
+ }
772
+ if (opts.permissionState === "denied" || opts.permissionState === "prompt") {
773
+ flags.push(`permission_${opts.permissionState}`);
774
+ }
775
+ return { suspicious: flags.length > 0, flags };
776
+ }
777
+ function gpsIntegrityInputFromPosition(position) {
778
+ const c = position.coords;
779
+ return {
780
+ latitude: c.latitude,
781
+ longitude: c.longitude,
782
+ accuracy: c.accuracy,
783
+ altitude: c.altitude,
784
+ altitudeAccuracy: c.altitudeAccuracy,
785
+ heading: c.heading,
786
+ speed: c.speed,
787
+ timestamp: position.timestamp
788
+ };
789
+ }
790
+ async function probeGeolocationPermission() {
791
+ try {
792
+ if (typeof navigator === "undefined" || !navigator.permissions?.query) {
793
+ return "unavailable";
794
+ }
795
+ const status = await navigator.permissions.query({ name: "geolocation" });
796
+ return status.state;
797
+ } catch {
798
+ return "unavailable";
703
799
  }
704
- const { createHmac } = await import('crypto');
705
- return createHmac("sha256", key).update(message).digest("hex");
706
800
  }
801
+
802
+ // src/geolocation/ciphertext.ts
803
+ var CIPHER_TEXT_EXPIRY_MINUTES = 5;
707
804
  function getWebGLInfo() {
708
805
  if (typeof document === "undefined") return null;
709
806
  try {
@@ -735,6 +832,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
735
832
  if (typeof navigator === "undefined" || !navigator.geolocation) {
736
833
  return null;
737
834
  }
835
+ const permissionState = await probeGeolocationPermission();
738
836
  return new Promise((resolve) => {
739
837
  navigator.geolocation.getCurrentPosition(
740
838
  (position) => {
@@ -751,6 +849,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
751
849
  resolve(null);
752
850
  return;
753
851
  }
852
+ const { flags } = assessGpsIntegrity(gpsIntegrityInputFromPosition(position), { permissionState });
754
853
  resolve({
755
854
  latitude,
756
855
  longitude,
@@ -759,7 +858,8 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
759
858
  altitude_accuracy: position.coords.altitudeAccuracy ?? void 0,
760
859
  heading: position.coords.heading ?? void 0,
761
860
  speed: position.coords.speed ?? void 0,
762
- timestamp: position.timestamp
861
+ timestamp: position.timestamp,
862
+ integrity_flags: flags.length ? flags : void 0
763
863
  });
764
864
  },
765
865
  () => {
@@ -826,6 +926,9 @@ async function generateCipherText(options, config) {
826
926
  );
827
927
  if (location) {
828
928
  locationData = location;
929
+ if (location.integrity_flags?.length) {
930
+ warnings.push(`GPS integrity flags (advisory): ${location.integrity_flags.join(", ")}`);
931
+ }
829
932
  } else if (gpsRequiredByConfig) {
830
933
  throw new VesantError(
831
934
  `GPS location is required for ${options.reason} by tenant configuration, but GPS was not available or permission was denied`,
@@ -855,15 +958,7 @@ async function generateCipherText(options, config) {
855
958
  };
856
959
  const encoded = encodePayload(payload);
857
960
  const timestamp = now.getTime().toString(36);
858
- let cipherText;
859
- const hmacKey = options.signingKey || options.apiKey;
860
- if (hmacKey) {
861
- const message = `02.${timestamp}.${encoded}`;
862
- const hmac = await computeHMAC(hmacKey, message);
863
- cipherText = `${message}.${hmac}`;
864
- } else {
865
- cipherText = `01.${timestamp}.${encoded}`;
866
- }
961
+ const cipherText = `01.${timestamp}.${encoded}`;
867
962
  return {
868
963
  cipherText,
869
964
  locationCaptured: !!locationData,
@@ -874,6 +969,7 @@ async function generateCipherText(options, config) {
874
969
  }
875
970
 
876
971
  // src/geolocation/client.ts
972
+ var DEFAULT_GPS_CONFIG_TTL_MS = 5 * 60 * 1e3;
877
973
  var GeolocationClient = class extends BaseClient {
878
974
  constructor(config) {
879
975
  const baseConfig = {
@@ -889,6 +985,8 @@ var GeolocationClient = class extends BaseClient {
889
985
  environment: config.environment
890
986
  };
891
987
  super(baseConfig);
988
+ this.gpsConfigCache = null;
989
+ this.gpsConfigTtlMs = config.gpsConfigTtlMs ?? DEFAULT_GPS_CONFIG_TTL_MS;
892
990
  }
893
991
  // ============================================================================
894
992
  // IP Verification & Compliance
@@ -920,8 +1018,8 @@ var GeolocationClient = class extends BaseClient {
920
1018
  * ```
921
1019
  */
922
1020
  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"]);
1021
+ if (request.ip_address !== void 0 && !request.ip_address.trim()) {
1022
+ throw new ValidationError("ip_address, when provided, must be a non-empty string", ["ip_address"]);
925
1023
  }
926
1024
  return this.requestWithRetry("/api/v1/geo/verify", {
927
1025
  method: "POST",
@@ -974,37 +1072,85 @@ var GeolocationClient = class extends BaseClient {
974
1072
  * ```
975
1073
  */
976
1074
  async getGPSConfig(requestOptions) {
977
- const config = await this.requestWithRetry("/api/v1/geo/config", void 0, void 0, void 0, requestOptions);
978
- if (config.signing_key) {
979
- this.cachedSigningKey = config.signing_key;
1075
+ const cached = this.gpsConfigCache;
1076
+ if (cached && cached.expiresAt > Date.now()) {
1077
+ return cached.value;
980
1078
  }
981
- return config;
1079
+ return this.refreshGPSConfig(requestOptions);
982
1080
  }
983
1081
  /**
984
- * Fetch the signing key from the dedicated authenticated endpoint.
1082
+ * Re-read the tenant's GPS requirement configuration, ignoring any copy held
1083
+ * from an earlier read.
985
1084
  *
986
- * Falls back to getGPSConfig() for backward compatibility with older servers
987
- * that don't expose `/api/v1/geo/signing-key`.
1085
+ * These requirements are edited in the compliance console while your
1086
+ * application is running. `getGPSConfig` reuses a fetched copy for a short
1087
+ * period so a long-lived session does not call the API on every event; call
1088
+ * this when you need a change to take effect immediately — for example right
1089
+ * after an administrator saves new settings.
988
1090
  *
989
- * @returns The signing key string, or undefined if unavailable
1091
+ * @returns The current GPS requirement config per event type
1092
+ *
1093
+ * @example
1094
+ * ```typescript
1095
+ * const config = await client.refreshGPSConfig();
1096
+ * if (config.require_gps.login) {
1097
+ * // GPS is now required for login
1098
+ * }
1099
+ * ```
1100
+ */
1101
+ async refreshGPSConfig(requestOptions) {
1102
+ const value = await this.requestWithRetry(
1103
+ "/api/v1/geo/config",
1104
+ void 0,
1105
+ void 0,
1106
+ void 0,
1107
+ requestOptions
1108
+ );
1109
+ this.gpsConfigCache = { value, expiresAt: Date.now() + this.gpsConfigTtlMs };
1110
+ return value;
1111
+ }
1112
+ /**
1113
+ * Mint a short-lived, single-use device-signals nonce.
1114
+ *
1115
+ * The nonce is bound to the tenant, user, and event type and is consumed
1116
+ * server-side during validation, so a captured device-signals envelope cannot
1117
+ * be replayed. `validateCipherText` mints and attaches one automatically; call
1118
+ * this directly only if you manage the nonce yourself.
1119
+ *
1120
+ * @param userId - User ID the nonce is bound to
1121
+ * @param eventType - Event type the nonce is bound to (login, registration, ...)
1122
+ * @returns The nonce and its expiry
1123
+ */
1124
+ async fetchSignalsNonce(userId, eventType, requestOptions) {
1125
+ if (!userId?.trim()) {
1126
+ throw new ValidationError("userId is required and must be a non-empty string", ["userId"]);
1127
+ }
1128
+ const request = { user_id: userId, event_type: eventType };
1129
+ return this.request(
1130
+ "/api/v1/geo/signals-token",
1131
+ {
1132
+ method: "POST",
1133
+ body: JSON.stringify(request)
1134
+ },
1135
+ void 0,
1136
+ requestOptions
1137
+ );
1138
+ }
1139
+ /**
1140
+ * Best-effort nonce mint for validation. Returns undefined if minting fails —
1141
+ * the server is the sole authority and blocks when a nonce is required, so this
1142
+ * never downgrades security on the client's say-so.
990
1143
  */
991
- async fetchSigningKey(requestOptions) {
1144
+ async resolveSignalsNonce(userId, eventType, requestOptions) {
992
1145
  try {
993
- const response = await this.requestWithRetry(
994
- "/api/v1/geo/signing-key",
995
- void 0,
996
- void 0,
997
- void 0,
998
- requestOptions
1146
+ const { nonce } = await this.fetchSignalsNonce(userId, eventType, requestOptions);
1147
+ return nonce;
1148
+ } catch (err) {
1149
+ this.logger.warn(
1150
+ `Failed to mint device-signals nonce; proceeding without it: ${err instanceof Error ? err.message : String(err)}`
999
1151
  );
1000
- if (response.signing_key) {
1001
- this.cachedSigningKey = response.signing_key;
1002
- return response.signing_key;
1003
- }
1004
- } catch {
1152
+ return void 0;
1005
1153
  }
1006
- const config = await this.getGPSConfig(requestOptions);
1007
- return config.signing_key;
1008
1154
  }
1009
1155
  // ============================================================================
1010
1156
  // CipherText Validation
@@ -1057,12 +1203,14 @@ var GeolocationClient = class extends BaseClient {
1057
1203
  if (!userId?.trim()) {
1058
1204
  throw new ValidationError("userId is required and must be a non-empty string", ["userId"]);
1059
1205
  }
1206
+ const nonce = await this.resolveSignalsNonce(userId, eventType, requestOptions);
1060
1207
  const request = {
1061
1208
  cipher_text: cipherText,
1062
1209
  user_id: userId,
1063
1210
  event_type: eventType,
1064
1211
  expected_ip: expectedIP,
1065
- customer_data: customerData
1212
+ customer_data: customerData,
1213
+ nonce
1066
1214
  };
1067
1215
  return this.requestWithRetry(
1068
1216
  "/api/v1/geo/validate-ciphertext",
@@ -1271,20 +1419,12 @@ var GeolocationClient = class extends BaseClient {
1271
1419
  *
1272
1420
  * @example
1273
1421
  * ```typescript
1274
- * // Using GPS (preferred)
1422
+ * // GPS (the web SDK is GPS + IP only; the server handles the IP fallback)
1275
1423
  * const result = await client.captureLocation(token, {
1276
1424
  * latitude: 37.7749,
1277
1425
  * longitude: -122.4194,
1278
1426
  * accuracy: 10
1279
1427
  * });
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
1428
  * ```
1289
1429
  */
1290
1430
  async captureLocation(token, capture, requestOptions) {
@@ -1297,34 +1437,22 @@ var GeolocationClient = class extends BaseClient {
1297
1437
  // CipherText Generation
1298
1438
  // ============================================================================
1299
1439
  /**
1300
- * Generate a signed cipherText containing device and location data.
1301
- *
1302
- * Automatically passes the client's API key for HMAC signing (v02 format).
1303
- * If no API key is configured, falls back to unsigned v01 format.
1440
+ * Generate a device-signals envelope containing device and location data,
1441
+ * validated by the server.
1304
1442
  *
1305
- * @param options - Options for cipherText generation
1443
+ * @param options - Options for envelope generation
1306
1444
  * @param gpsConfig - Optional GPS config (from getGPSConfig)
1307
- * @returns CipherText result with the signed string
1445
+ * @returns The device-signals envelope result
1308
1446
  *
1309
1447
  * @example
1310
1448
  * ```typescript
1311
1449
  * const result = await client.generateCipherText({ reason: 'login' });
1312
- * console.log(result.cipherText); // v02 signed cipherText
1450
+ * console.log(result.cipherText); // device-signals envelope
1313
1451
  * ```
1314
1452
  */
1315
1453
  async generateCipherText(options, gpsConfig) {
1316
- let signingKey = this.cachedSigningKey;
1317
- let resolvedGpsConfig = gpsConfig;
1318
- if (!signingKey) {
1319
- signingKey = await this.fetchSigningKey();
1320
- }
1321
- if (!resolvedGpsConfig) {
1322
- resolvedGpsConfig = await this.getGPSConfig();
1323
- }
1324
- return generateCipherText(
1325
- { ...options, signingKey: signingKey || void 0 },
1326
- resolvedGpsConfig
1327
- );
1454
+ const resolvedGpsConfig = gpsConfig ?? await this.getGPSConfig();
1455
+ return generateCipherText(options, resolvedGpsConfig);
1328
1456
  }
1329
1457
  // ============================================================================
1330
1458
  // Utility Methods (inherited from BaseClient: healthCheck, updateConfig, getConfig, buildQueryString)