vesant-sdk 1.7.0 → 1.7.1-dev.301c6df
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.
- package/dist/{client-DtH2RLuy.d.ts → client-B3DCAHlg.d.ts} +2 -2
- package/dist/{client-DrjgZoH_.d.mts → client-BwXMQA2a.d.mts} +64 -42
- package/dist/{client-B0qhE2kr.d.mts → client-D23KhWeh.d.mts} +2 -2
- package/dist/{client-DF7hlMEz.d.ts → client-fy3trF2K.d.ts} +64 -42
- package/dist/{client-BolQlL5e.d.mts → client-q9fN8Hhf.d.mts} +103 -1
- package/dist/{client-BolQlL5e.d.ts → client-q9fN8Hhf.d.ts} +103 -1
- package/dist/compliance/index.d.mts +3 -3
- package/dist/compliance/index.d.ts +3 -3
- package/dist/compliance/index.js +181 -91
- package/dist/compliance/index.js.map +1 -1
- package/dist/compliance/index.mjs +181 -91
- package/dist/compliance/index.mjs.map +1 -1
- package/dist/decisions/index.d.mts +1 -1
- package/dist/decisions/index.d.ts +1 -1
- package/dist/decisions/index.js +69 -8
- package/dist/decisions/index.js.map +1 -1
- package/dist/decisions/index.mjs +69 -8
- package/dist/decisions/index.mjs.map +1 -1
- package/dist/geolocation/index.d.mts +68 -7
- package/dist/geolocation/index.d.ts +68 -7
- package/dist/geolocation/index.js +186 -91
- package/dist/geolocation/index.js.map +1 -1
- package/dist/geolocation/index.mjs +183 -92
- package/dist/geolocation/index.mjs.map +1 -1
- package/dist/index-C3zUKydT.d.mts +264 -0
- package/dist/index-DSDgS09k.d.ts +264 -0
- package/dist/index.d.mts +26 -9
- package/dist/index.d.ts +26 -9
- package/dist/index.js +354 -120
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +346 -121
- package/dist/index.mjs.map +1 -1
- package/dist/kyc/core.d.mts +1 -1
- package/dist/kyc/core.d.ts +1 -1
- package/dist/kyc/core.js +75 -14
- package/dist/kyc/core.js.map +1 -1
- package/dist/kyc/core.mjs +75 -14
- package/dist/kyc/core.mjs.map +1 -1
- package/dist/kyc/index.d.mts +4 -4
- package/dist/kyc/index.d.ts +4 -4
- package/dist/kyc/index.js +75 -14
- package/dist/kyc/index.js.map +1 -1
- package/dist/kyc/index.mjs +75 -14
- package/dist/kyc/index.mjs.map +1 -1
- package/dist/react.d.mts +7 -3
- package/dist/react.d.ts +7 -3
- package/dist/react.js +70 -33
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +70 -33
- package/dist/react.mjs.map +1 -1
- package/dist/risk-profile/index.d.mts +1 -1
- package/dist/risk-profile/index.d.ts +1 -1
- package/dist/risk-profile/index.js +69 -8
- package/dist/risk-profile/index.js.map +1 -1
- package/dist/risk-profile/index.mjs +69 -8
- package/dist/risk-profile/index.mjs.map +1 -1
- package/dist/scores/index.d.mts +1 -1
- package/dist/scores/index.d.ts +1 -1
- package/dist/scores/index.js +69 -8
- package/dist/scores/index.js.map +1 -1
- package/dist/scores/index.mjs +69 -8
- package/dist/scores/index.mjs.map +1 -1
- package/dist/tax/index.d.mts +2 -2
- package/dist/tax/index.d.ts +2 -2
- package/dist/tax/index.js +74 -10
- package/dist/tax/index.js.map +1 -1
- package/dist/tax/index.mjs +74 -10
- package/dist/tax/index.mjs.map +1 -1
- package/dist/webhooks/index.d.mts +2 -189
- package/dist/webhooks/index.d.ts +2 -189
- package/dist/webhooks/index.js +85 -21
- package/dist/webhooks/index.js.map +1 -1
- package/dist/webhooks/index.mjs +85 -22
- package/dist/webhooks/index.mjs.map +1 -1
- package/package.json +4 -1
|
@@ -73,6 +73,19 @@ var sdkReasons = {
|
|
|
73
73
|
})
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
+
// src/core/auth.ts
|
|
77
|
+
var StaticApiKeyProvider = class {
|
|
78
|
+
constructor(apiKey) {
|
|
79
|
+
this.apiKey = apiKey;
|
|
80
|
+
}
|
|
81
|
+
async getCredential() {
|
|
82
|
+
return this.apiKey ? { scheme: "Bearer", token: this.apiKey } : null;
|
|
83
|
+
}
|
|
84
|
+
canRefresh() {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
76
89
|
// src/core/errors.ts
|
|
77
90
|
var VesantError = class _VesantError extends Error {
|
|
78
91
|
constructor(message, code, statusCode, details) {
|
|
@@ -297,7 +310,7 @@ function createConsoleLogger() {
|
|
|
297
310
|
}
|
|
298
311
|
|
|
299
312
|
// src/core/version.ts
|
|
300
|
-
var SDK_VERSION = "1.7.
|
|
313
|
+
var SDK_VERSION = "1.7.1";
|
|
301
314
|
|
|
302
315
|
// src/shared/browser-utils.ts
|
|
303
316
|
function generateUUID() {
|
|
@@ -379,6 +392,12 @@ var BaseClient = class {
|
|
|
379
392
|
if (!config.tenantId?.trim()) {
|
|
380
393
|
throw new ValidationError("tenantId is required and must be a non-empty string", ["tenantId"]);
|
|
381
394
|
}
|
|
395
|
+
if (typeof fetch === "undefined") {
|
|
396
|
+
throw new VesantError(
|
|
397
|
+
"The Vesant SDK requires a global fetch (Node.js >= 18). Upgrade Node or provide a fetch polyfill.",
|
|
398
|
+
"RUNTIME_UNSUPPORTED"
|
|
399
|
+
);
|
|
400
|
+
}
|
|
382
401
|
this.interceptors = config.interceptors || [];
|
|
383
402
|
this.logger = config.logger || createConsoleLogger();
|
|
384
403
|
let environment = config.environment;
|
|
@@ -397,11 +416,12 @@ var BaseClient = class {
|
|
|
397
416
|
environment,
|
|
398
417
|
headers: config.headers || {},
|
|
399
418
|
timeout: config.timeout || 1e4,
|
|
400
|
-
retries: config.retries
|
|
419
|
+
retries: config.retries ?? 3,
|
|
401
420
|
debug: config.debug || false,
|
|
402
421
|
interceptors: this.interceptors,
|
|
403
422
|
logger: this.logger
|
|
404
423
|
};
|
|
424
|
+
this.authProvider = config.authProvider ?? (apiKey ? new StaticApiKeyProvider(apiKey) : void 0);
|
|
405
425
|
if (config.circuitBreaker) {
|
|
406
426
|
this.circuitBreaker = new CircuitBreaker(config.circuitBreaker);
|
|
407
427
|
}
|
|
@@ -409,6 +429,19 @@ var BaseClient = class {
|
|
|
409
429
|
this.rateLimitTracker = new RateLimitTracker();
|
|
410
430
|
}
|
|
411
431
|
}
|
|
432
|
+
/**
|
|
433
|
+
* Resolve the Idempotency-Key for a request. Mutating methods (POST/PUT/PATCH)
|
|
434
|
+
* get the caller-supplied key or a freshly minted UUID; non-mutating methods get
|
|
435
|
+
* none. requestWithRetry resolves this once and injects it so every retry reuses
|
|
436
|
+
* one key (letting the server dedup replays); a direct request() resolves per call.
|
|
437
|
+
*/
|
|
438
|
+
resolveIdempotencyKey(method, requestOptions) {
|
|
439
|
+
const isMutating = ["POST", "PUT", "PATCH"].includes((method || "GET").toUpperCase());
|
|
440
|
+
if (!isMutating) {
|
|
441
|
+
return void 0;
|
|
442
|
+
}
|
|
443
|
+
return requestOptions?.idempotencyKey ?? generateUUID();
|
|
444
|
+
}
|
|
412
445
|
/**
|
|
413
446
|
* Make an HTTP request with timeout and error handling
|
|
414
447
|
*/
|
|
@@ -434,15 +467,20 @@ var BaseClient = class {
|
|
|
434
467
|
...this.config.headers,
|
|
435
468
|
...options.headers || {}
|
|
436
469
|
};
|
|
437
|
-
|
|
438
|
-
|
|
470
|
+
const credential = await this.authProvider?.getCredential({
|
|
471
|
+
tenantId: this.config.tenantId,
|
|
472
|
+
requestId
|
|
473
|
+
});
|
|
474
|
+
if (credential) {
|
|
475
|
+
headers["Authorization"] = `${credential.scheme ?? "Bearer"} ${credential.token}`;
|
|
439
476
|
}
|
|
440
477
|
if (this.config.environment === "sandbox") {
|
|
441
478
|
headers["X-Sandbox"] = "true";
|
|
442
479
|
}
|
|
443
480
|
const method = (options.method || "GET").toUpperCase();
|
|
444
|
-
|
|
445
|
-
|
|
481
|
+
const idempotencyKey = this.resolveIdempotencyKey(method, requestOptions);
|
|
482
|
+
if (idempotencyKey) {
|
|
483
|
+
headers["Idempotency-Key"] = idempotencyKey;
|
|
446
484
|
}
|
|
447
485
|
const controller = new AbortController();
|
|
448
486
|
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
@@ -463,10 +501,28 @@ var BaseClient = class {
|
|
|
463
501
|
if (this.config.debug) {
|
|
464
502
|
this.logger.debug(`${finalOptions.method || "GET"} ${endpoint}`);
|
|
465
503
|
}
|
|
466
|
-
|
|
504
|
+
let response = await fetch(url, {
|
|
467
505
|
...finalOptions,
|
|
468
506
|
signal: controller.signal
|
|
469
507
|
});
|
|
508
|
+
if (response.status === 401 && this.authProvider?.canRefresh?.()) {
|
|
509
|
+
const refreshed = await this.authProvider.getCredential({
|
|
510
|
+
tenantId: this.config.tenantId,
|
|
511
|
+
requestId,
|
|
512
|
+
forceRefresh: true
|
|
513
|
+
});
|
|
514
|
+
if (refreshed) {
|
|
515
|
+
this.config.onCredentialRotated?.({ reason: "unauthorized" });
|
|
516
|
+
finalOptions = {
|
|
517
|
+
...finalOptions,
|
|
518
|
+
headers: {
|
|
519
|
+
...finalOptions.headers,
|
|
520
|
+
Authorization: `${refreshed.scheme ?? "Bearer"} ${refreshed.token}`
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
response = await fetch(url, { ...finalOptions, signal: controller.signal });
|
|
524
|
+
}
|
|
525
|
+
}
|
|
470
526
|
clearTimeout(timeoutId);
|
|
471
527
|
if (this.rateLimitTracker) {
|
|
472
528
|
this.rateLimitTracker.updateFromHeaders(response.headers);
|
|
@@ -555,9 +611,11 @@ var BaseClient = class {
|
|
|
555
611
|
*/
|
|
556
612
|
async requestWithRetry(endpoint, options = {}, serviceURL, retries = this.config.retries, requestOptions) {
|
|
557
613
|
let lastError;
|
|
614
|
+
const idempotencyKey = this.resolveIdempotencyKey(options.method || "GET", requestOptions);
|
|
615
|
+
const attemptOptions = idempotencyKey ? { ...requestOptions, idempotencyKey } : requestOptions;
|
|
558
616
|
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
559
617
|
try {
|
|
560
|
-
return await this.request(endpoint, options, serviceURL,
|
|
618
|
+
return await this.request(endpoint, options, serviceURL, attemptOptions);
|
|
561
619
|
} catch (error) {
|
|
562
620
|
lastError = error instanceof Error ? error : new Error("Unknown error");
|
|
563
621
|
if (requestOptions?.signal?.aborted) {
|
|
@@ -654,6 +712,9 @@ var BaseClient = class {
|
|
|
654
712
|
if (config.interceptors) {
|
|
655
713
|
this.interceptors = config.interceptors;
|
|
656
714
|
}
|
|
715
|
+
if (config.authProvider !== void 0 || config.apiKey !== void 0) {
|
|
716
|
+
this.authProvider = this.config.authProvider ?? (this.config.apiKey ? new StaticApiKeyProvider(this.config.apiKey) : void 0);
|
|
717
|
+
}
|
|
657
718
|
}
|
|
658
719
|
/**
|
|
659
720
|
* Get current configuration (readonly)
|
|
@@ -681,27 +742,63 @@ var BaseClient = class {
|
|
|
681
742
|
}
|
|
682
743
|
};
|
|
683
744
|
|
|
684
|
-
// src/geolocation/
|
|
685
|
-
var
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
);
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
745
|
+
// src/geolocation/integrity.ts
|
|
746
|
+
var isNil = (v) => v === null || v === void 0;
|
|
747
|
+
function assessGpsIntegrity(input, opts = {}) {
|
|
748
|
+
const flags = [];
|
|
749
|
+
const now = opts.now ?? (() => Date.now());
|
|
750
|
+
const maxAgeMs = opts.maxAgeMs ?? 6e4;
|
|
751
|
+
const minAccuracy = opts.minAccuracyMeters ?? 1;
|
|
752
|
+
const { accuracy, altitude, altitudeAccuracy, heading, speed, timestamp } = input;
|
|
753
|
+
if (isNil(accuracy)) {
|
|
754
|
+
flags.push("accuracy_missing");
|
|
755
|
+
} else if (accuracy === 0) {
|
|
756
|
+
flags.push("accuracy_zero");
|
|
757
|
+
} else if (accuracy < minAccuracy) {
|
|
758
|
+
flags.push("accuracy_implausibly_small");
|
|
759
|
+
}
|
|
760
|
+
const hasMotion = !isNil(heading) || !isNil(speed);
|
|
761
|
+
if (hasMotion && (isNil(accuracy) || accuracy === 0)) {
|
|
762
|
+
flags.push("motion_without_accuracy");
|
|
763
|
+
}
|
|
764
|
+
if (!isNil(altitude) && isNil(altitudeAccuracy)) {
|
|
765
|
+
flags.push("altitude_without_accuracy");
|
|
766
|
+
}
|
|
767
|
+
if (timestamp !== void 0 && now() - timestamp > maxAgeMs) {
|
|
768
|
+
flags.push("stale_timestamp");
|
|
769
|
+
}
|
|
770
|
+
if (opts.permissionState === "denied" || opts.permissionState === "prompt") {
|
|
771
|
+
flags.push(`permission_${opts.permissionState}`);
|
|
772
|
+
}
|
|
773
|
+
return { suspicious: flags.length > 0, flags };
|
|
774
|
+
}
|
|
775
|
+
function gpsIntegrityInputFromPosition(position) {
|
|
776
|
+
const c = position.coords;
|
|
777
|
+
return {
|
|
778
|
+
latitude: c.latitude,
|
|
779
|
+
longitude: c.longitude,
|
|
780
|
+
accuracy: c.accuracy,
|
|
781
|
+
altitude: c.altitude,
|
|
782
|
+
altitudeAccuracy: c.altitudeAccuracy,
|
|
783
|
+
heading: c.heading,
|
|
784
|
+
speed: c.speed,
|
|
785
|
+
timestamp: position.timestamp
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
async function probeGeolocationPermission() {
|
|
789
|
+
try {
|
|
790
|
+
if (typeof navigator === "undefined" || !navigator.permissions?.query) {
|
|
791
|
+
return "unavailable";
|
|
792
|
+
}
|
|
793
|
+
const status = await navigator.permissions.query({ name: "geolocation" });
|
|
794
|
+
return status.state;
|
|
795
|
+
} catch {
|
|
796
|
+
return "unavailable";
|
|
701
797
|
}
|
|
702
|
-
const { createHmac } = await import('crypto');
|
|
703
|
-
return createHmac("sha256", key).update(message).digest("hex");
|
|
704
798
|
}
|
|
799
|
+
|
|
800
|
+
// src/geolocation/ciphertext.ts
|
|
801
|
+
var CIPHER_TEXT_EXPIRY_MINUTES = 5;
|
|
705
802
|
function getWebGLInfo() {
|
|
706
803
|
if (typeof document === "undefined") return null;
|
|
707
804
|
try {
|
|
@@ -733,6 +830,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
|
|
|
733
830
|
if (typeof navigator === "undefined" || !navigator.geolocation) {
|
|
734
831
|
return null;
|
|
735
832
|
}
|
|
833
|
+
const permissionState = await probeGeolocationPermission();
|
|
736
834
|
return new Promise((resolve) => {
|
|
737
835
|
navigator.geolocation.getCurrentPosition(
|
|
738
836
|
(position) => {
|
|
@@ -749,6 +847,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
|
|
|
749
847
|
resolve(null);
|
|
750
848
|
return;
|
|
751
849
|
}
|
|
850
|
+
const { flags } = assessGpsIntegrity(gpsIntegrityInputFromPosition(position), { permissionState });
|
|
752
851
|
resolve({
|
|
753
852
|
latitude,
|
|
754
853
|
longitude,
|
|
@@ -757,7 +856,8 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
|
|
|
757
856
|
altitude_accuracy: position.coords.altitudeAccuracy ?? void 0,
|
|
758
857
|
heading: position.coords.heading ?? void 0,
|
|
759
858
|
speed: position.coords.speed ?? void 0,
|
|
760
|
-
timestamp: position.timestamp
|
|
859
|
+
timestamp: position.timestamp,
|
|
860
|
+
integrity_flags: flags.length ? flags : void 0
|
|
761
861
|
});
|
|
762
862
|
},
|
|
763
863
|
() => {
|
|
@@ -824,6 +924,9 @@ async function generateCipherText(options, config) {
|
|
|
824
924
|
);
|
|
825
925
|
if (location) {
|
|
826
926
|
locationData = location;
|
|
927
|
+
if (location.integrity_flags?.length) {
|
|
928
|
+
warnings.push(`GPS integrity flags (advisory): ${location.integrity_flags.join(", ")}`);
|
|
929
|
+
}
|
|
827
930
|
} else if (gpsRequiredByConfig) {
|
|
828
931
|
throw new VesantError(
|
|
829
932
|
`GPS location is required for ${options.reason} by tenant configuration, but GPS was not available or permission was denied`,
|
|
@@ -853,15 +956,7 @@ async function generateCipherText(options, config) {
|
|
|
853
956
|
};
|
|
854
957
|
const encoded = encodePayload(payload);
|
|
855
958
|
const timestamp = now.getTime().toString(36);
|
|
856
|
-
|
|
857
|
-
const hmacKey = options.signingKey || options.apiKey;
|
|
858
|
-
if (hmacKey) {
|
|
859
|
-
const message = `02.${timestamp}.${encoded}`;
|
|
860
|
-
const hmac = await computeHMAC(hmacKey, message);
|
|
861
|
-
cipherText = `${message}.${hmac}`;
|
|
862
|
-
} else {
|
|
863
|
-
cipherText = `01.${timestamp}.${encoded}`;
|
|
864
|
-
}
|
|
959
|
+
const cipherText = `01.${timestamp}.${encoded}`;
|
|
865
960
|
return {
|
|
866
961
|
cipherText,
|
|
867
962
|
locationCaptured: !!locationData,
|
|
@@ -918,8 +1013,8 @@ var GeolocationClient = class extends BaseClient {
|
|
|
918
1013
|
* ```
|
|
919
1014
|
*/
|
|
920
1015
|
async verifyIP(request, requestOptions) {
|
|
921
|
-
if (!request.ip_address
|
|
922
|
-
throw new ValidationError("ip_address
|
|
1016
|
+
if (request.ip_address !== void 0 && !request.ip_address.trim()) {
|
|
1017
|
+
throw new ValidationError("ip_address, when provided, must be a non-empty string", ["ip_address"]);
|
|
923
1018
|
}
|
|
924
1019
|
return this.requestWithRetry("/api/v1/geo/verify", {
|
|
925
1020
|
method: "POST",
|
|
@@ -972,37 +1067,50 @@ var GeolocationClient = class extends BaseClient {
|
|
|
972
1067
|
* ```
|
|
973
1068
|
*/
|
|
974
1069
|
async getGPSConfig(requestOptions) {
|
|
975
|
-
|
|
976
|
-
if (config.signing_key) {
|
|
977
|
-
this.cachedSigningKey = config.signing_key;
|
|
978
|
-
}
|
|
979
|
-
return config;
|
|
1070
|
+
return this.requestWithRetry("/api/v1/geo/config", void 0, void 0, void 0, requestOptions);
|
|
980
1071
|
}
|
|
981
1072
|
/**
|
|
982
|
-
*
|
|
1073
|
+
* Mint a short-lived, single-use device-signals nonce.
|
|
983
1074
|
*
|
|
984
|
-
*
|
|
985
|
-
*
|
|
1075
|
+
* The nonce is bound to the tenant, user, and event type and is consumed
|
|
1076
|
+
* server-side during validation, so a captured device-signals envelope cannot
|
|
1077
|
+
* be replayed. `validateCipherText` mints and attaches one automatically; call
|
|
1078
|
+
* this directly only if you manage the nonce yourself.
|
|
986
1079
|
*
|
|
987
|
-
* @
|
|
1080
|
+
* @param userId - User ID the nonce is bound to
|
|
1081
|
+
* @param eventType - Event type the nonce is bound to (login, registration, ...)
|
|
1082
|
+
* @returns The nonce and its expiry
|
|
988
1083
|
*/
|
|
989
|
-
async
|
|
1084
|
+
async fetchSignalsNonce(userId, eventType, requestOptions) {
|
|
1085
|
+
if (!userId?.trim()) {
|
|
1086
|
+
throw new ValidationError("userId is required and must be a non-empty string", ["userId"]);
|
|
1087
|
+
}
|
|
1088
|
+
const request = { user_id: userId, event_type: eventType };
|
|
1089
|
+
return this.request(
|
|
1090
|
+
"/api/v1/geo/signals-token",
|
|
1091
|
+
{
|
|
1092
|
+
method: "POST",
|
|
1093
|
+
body: JSON.stringify(request)
|
|
1094
|
+
},
|
|
1095
|
+
void 0,
|
|
1096
|
+
requestOptions
|
|
1097
|
+
);
|
|
1098
|
+
}
|
|
1099
|
+
/**
|
|
1100
|
+
* Best-effort nonce mint for validation. Returns undefined if minting fails —
|
|
1101
|
+
* the server is the sole authority and blocks when a nonce is required, so this
|
|
1102
|
+
* never downgrades security on the client's say-so.
|
|
1103
|
+
*/
|
|
1104
|
+
async resolveSignalsNonce(userId, eventType, requestOptions) {
|
|
990
1105
|
try {
|
|
991
|
-
const
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
requestOptions
|
|
1106
|
+
const { nonce } = await this.fetchSignalsNonce(userId, eventType, requestOptions);
|
|
1107
|
+
return nonce;
|
|
1108
|
+
} catch (err) {
|
|
1109
|
+
this.logger.warn(
|
|
1110
|
+
`Failed to mint device-signals nonce; proceeding without it: ${err instanceof Error ? err.message : String(err)}`
|
|
997
1111
|
);
|
|
998
|
-
|
|
999
|
-
this.cachedSigningKey = response.signing_key;
|
|
1000
|
-
return response.signing_key;
|
|
1001
|
-
}
|
|
1002
|
-
} catch {
|
|
1112
|
+
return void 0;
|
|
1003
1113
|
}
|
|
1004
|
-
const config = await this.getGPSConfig(requestOptions);
|
|
1005
|
-
return config.signing_key;
|
|
1006
1114
|
}
|
|
1007
1115
|
// ============================================================================
|
|
1008
1116
|
// CipherText Validation
|
|
@@ -1055,12 +1163,14 @@ var GeolocationClient = class extends BaseClient {
|
|
|
1055
1163
|
if (!userId?.trim()) {
|
|
1056
1164
|
throw new ValidationError("userId is required and must be a non-empty string", ["userId"]);
|
|
1057
1165
|
}
|
|
1166
|
+
const nonce = await this.resolveSignalsNonce(userId, eventType, requestOptions);
|
|
1058
1167
|
const request = {
|
|
1059
1168
|
cipher_text: cipherText,
|
|
1060
1169
|
user_id: userId,
|
|
1061
1170
|
event_type: eventType,
|
|
1062
1171
|
expected_ip: expectedIP,
|
|
1063
|
-
customer_data: customerData
|
|
1172
|
+
customer_data: customerData,
|
|
1173
|
+
nonce
|
|
1064
1174
|
};
|
|
1065
1175
|
return this.requestWithRetry(
|
|
1066
1176
|
"/api/v1/geo/validate-ciphertext",
|
|
@@ -1269,20 +1379,12 @@ var GeolocationClient = class extends BaseClient {
|
|
|
1269
1379
|
*
|
|
1270
1380
|
* @example
|
|
1271
1381
|
* ```typescript
|
|
1272
|
-
* //
|
|
1382
|
+
* // GPS (the web SDK is GPS + IP only; the server handles the IP fallback)
|
|
1273
1383
|
* const result = await client.captureLocation(token, {
|
|
1274
1384
|
* latitude: 37.7749,
|
|
1275
1385
|
* longitude: -122.4194,
|
|
1276
1386
|
* accuracy: 10
|
|
1277
1387
|
* });
|
|
1278
|
-
*
|
|
1279
|
-
* // Using WiFi positioning (fallback)
|
|
1280
|
-
* const result = await client.captureLocation(token, {
|
|
1281
|
-
* wifi_networks: [
|
|
1282
|
-
* { macAddress: "00:11:22:33:44:55", signalStrength: -50 },
|
|
1283
|
-
* { macAddress: "AA:BB:CC:DD:EE:FF", signalStrength: -70 }
|
|
1284
|
-
* ]
|
|
1285
|
-
* });
|
|
1286
1388
|
* ```
|
|
1287
1389
|
*/
|
|
1288
1390
|
async captureLocation(token, capture, requestOptions) {
|
|
@@ -1295,34 +1397,22 @@ var GeolocationClient = class extends BaseClient {
|
|
|
1295
1397
|
// CipherText Generation
|
|
1296
1398
|
// ============================================================================
|
|
1297
1399
|
/**
|
|
1298
|
-
* Generate a
|
|
1400
|
+
* Generate a device-signals envelope containing device and location data,
|
|
1401
|
+
* validated by the server.
|
|
1299
1402
|
*
|
|
1300
|
-
*
|
|
1301
|
-
* If no API key is configured, falls back to unsigned v01 format.
|
|
1302
|
-
*
|
|
1303
|
-
* @param options - Options for cipherText generation
|
|
1403
|
+
* @param options - Options for envelope generation
|
|
1304
1404
|
* @param gpsConfig - Optional GPS config (from getGPSConfig)
|
|
1305
|
-
* @returns
|
|
1405
|
+
* @returns The device-signals envelope result
|
|
1306
1406
|
*
|
|
1307
1407
|
* @example
|
|
1308
1408
|
* ```typescript
|
|
1309
1409
|
* const result = await client.generateCipherText({ reason: 'login' });
|
|
1310
|
-
* console.log(result.cipherText); //
|
|
1410
|
+
* console.log(result.cipherText); // device-signals envelope
|
|
1311
1411
|
* ```
|
|
1312
1412
|
*/
|
|
1313
1413
|
async generateCipherText(options, gpsConfig) {
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
if (!signingKey) {
|
|
1317
|
-
signingKey = await this.fetchSigningKey();
|
|
1318
|
-
}
|
|
1319
|
-
if (!resolvedGpsConfig) {
|
|
1320
|
-
resolvedGpsConfig = await this.getGPSConfig();
|
|
1321
|
-
}
|
|
1322
|
-
return generateCipherText(
|
|
1323
|
-
{ ...options, signingKey: signingKey || void 0 },
|
|
1324
|
-
resolvedGpsConfig
|
|
1325
|
-
);
|
|
1414
|
+
const resolvedGpsConfig = gpsConfig ?? await this.getGPSConfig();
|
|
1415
|
+
return generateCipherText(options, resolvedGpsConfig);
|
|
1326
1416
|
}
|
|
1327
1417
|
// ============================================================================
|
|
1328
1418
|
// Utility Methods (inherited from BaseClient: healthCheck, updateConfig, getConfig, buildQueryString)
|