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.
- package/dist/{client-DF7hlMEz.d.ts → client-0NOPDnT0.d.ts} +16 -26
- package/dist/{client-DrjgZoH_.d.mts → client-CvWNRwwg.d.mts} +16 -26
- package/dist/{client-B0qhE2kr.d.mts → client-Dps40EtF.d.mts} +2 -2
- package/dist/{client-DtH2RLuy.d.ts → client-SMxqod4j.d.ts} +2 -2
- 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 +126 -18
- package/dist/compliance/index.js.map +1 -1
- package/dist/compliance/index.mjs +126 -18
- 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 +61 -6
- package/dist/decisions/index.js.map +1 -1
- package/dist/decisions/index.mjs +61 -6
- package/dist/decisions/index.mjs.map +1 -1
- package/dist/geolocation/index.d.mts +59 -4
- package/dist/geolocation/index.d.ts +59 -4
- package/dist/geolocation/index.js +129 -18
- package/dist/geolocation/index.js.map +1 -1
- package/dist/geolocation/index.mjs +127 -19
- package/dist/geolocation/index.mjs.map +1 -1
- package/dist/index-CPOrMRaH.d.ts +264 -0
- package/dist/index-CimDmgZb.d.mts +264 -0
- package/dist/index.d.mts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +286 -49
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +281 -50
- package/dist/index.mjs.map +1 -1
- package/dist/kyc/core.d.mts +2 -2
- package/dist/kyc/core.d.ts +2 -2
- package/dist/kyc/core.js +83 -14
- package/dist/kyc/core.js.map +1 -1
- package/dist/kyc/core.mjs +83 -14
- package/dist/kyc/core.mjs.map +1 -1
- package/dist/kyc/index.d.mts +56 -8
- package/dist/kyc/index.d.ts +56 -8
- package/dist/kyc/index.js +83 -14
- package/dist/kyc/index.js.map +1 -1
- package/dist/kyc/index.mjs +83 -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 +68 -4
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +68 -4
- 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 +61 -6
- package/dist/risk-profile/index.js.map +1 -1
- package/dist/risk-profile/index.mjs +61 -6
- 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 +61 -6
- package/dist/scores/index.js.map +1 -1
- package/dist/scores/index.mjs +61 -6
- 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 +66 -8
- package/dist/tax/index.js.map +1 -1
- package/dist/tax/index.mjs +66 -8
- 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 +1 -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) {
|
|
@@ -402,6 +415,7 @@ var BaseClient = class {
|
|
|
402
415
|
interceptors: this.interceptors,
|
|
403
416
|
logger: this.logger
|
|
404
417
|
};
|
|
418
|
+
this.authProvider = config.authProvider ?? (apiKey ? new StaticApiKeyProvider(apiKey) : void 0);
|
|
405
419
|
if (config.circuitBreaker) {
|
|
406
420
|
this.circuitBreaker = new CircuitBreaker(config.circuitBreaker);
|
|
407
421
|
}
|
|
@@ -409,6 +423,19 @@ var BaseClient = class {
|
|
|
409
423
|
this.rateLimitTracker = new RateLimitTracker();
|
|
410
424
|
}
|
|
411
425
|
}
|
|
426
|
+
/**
|
|
427
|
+
* Resolve the Idempotency-Key for a request. Mutating methods (POST/PUT/PATCH)
|
|
428
|
+
* get the caller-supplied key or a freshly minted UUID; non-mutating methods get
|
|
429
|
+
* none. requestWithRetry resolves this once and injects it so every retry reuses
|
|
430
|
+
* one key (letting the server dedup replays); a direct request() resolves per call.
|
|
431
|
+
*/
|
|
432
|
+
resolveIdempotencyKey(method, requestOptions) {
|
|
433
|
+
const isMutating = ["POST", "PUT", "PATCH"].includes((method || "GET").toUpperCase());
|
|
434
|
+
if (!isMutating) {
|
|
435
|
+
return void 0;
|
|
436
|
+
}
|
|
437
|
+
return requestOptions?.idempotencyKey ?? generateUUID();
|
|
438
|
+
}
|
|
412
439
|
/**
|
|
413
440
|
* Make an HTTP request with timeout and error handling
|
|
414
441
|
*/
|
|
@@ -434,15 +461,20 @@ var BaseClient = class {
|
|
|
434
461
|
...this.config.headers,
|
|
435
462
|
...options.headers || {}
|
|
436
463
|
};
|
|
437
|
-
|
|
438
|
-
|
|
464
|
+
const credential = await this.authProvider?.getCredential({
|
|
465
|
+
tenantId: this.config.tenantId,
|
|
466
|
+
requestId
|
|
467
|
+
});
|
|
468
|
+
if (credential) {
|
|
469
|
+
headers["Authorization"] = `${credential.scheme ?? "Bearer"} ${credential.token}`;
|
|
439
470
|
}
|
|
440
471
|
if (this.config.environment === "sandbox") {
|
|
441
472
|
headers["X-Sandbox"] = "true";
|
|
442
473
|
}
|
|
443
474
|
const method = (options.method || "GET").toUpperCase();
|
|
444
|
-
|
|
445
|
-
|
|
475
|
+
const idempotencyKey = this.resolveIdempotencyKey(method, requestOptions);
|
|
476
|
+
if (idempotencyKey) {
|
|
477
|
+
headers["Idempotency-Key"] = idempotencyKey;
|
|
446
478
|
}
|
|
447
479
|
const controller = new AbortController();
|
|
448
480
|
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
@@ -463,10 +495,28 @@ var BaseClient = class {
|
|
|
463
495
|
if (this.config.debug) {
|
|
464
496
|
this.logger.debug(`${finalOptions.method || "GET"} ${endpoint}`);
|
|
465
497
|
}
|
|
466
|
-
|
|
498
|
+
let response = await fetch(url, {
|
|
467
499
|
...finalOptions,
|
|
468
500
|
signal: controller.signal
|
|
469
501
|
});
|
|
502
|
+
if (response.status === 401 && this.authProvider?.canRefresh?.()) {
|
|
503
|
+
const refreshed = await this.authProvider.getCredential({
|
|
504
|
+
tenantId: this.config.tenantId,
|
|
505
|
+
requestId,
|
|
506
|
+
forceRefresh: true
|
|
507
|
+
});
|
|
508
|
+
if (refreshed) {
|
|
509
|
+
this.config.onCredentialRotated?.({ reason: "unauthorized" });
|
|
510
|
+
finalOptions = {
|
|
511
|
+
...finalOptions,
|
|
512
|
+
headers: {
|
|
513
|
+
...finalOptions.headers,
|
|
514
|
+
Authorization: `${refreshed.scheme ?? "Bearer"} ${refreshed.token}`
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
response = await fetch(url, { ...finalOptions, signal: controller.signal });
|
|
518
|
+
}
|
|
519
|
+
}
|
|
470
520
|
clearTimeout(timeoutId);
|
|
471
521
|
if (this.rateLimitTracker) {
|
|
472
522
|
this.rateLimitTracker.updateFromHeaders(response.headers);
|
|
@@ -555,9 +605,11 @@ var BaseClient = class {
|
|
|
555
605
|
*/
|
|
556
606
|
async requestWithRetry(endpoint, options = {}, serviceURL, retries = this.config.retries, requestOptions) {
|
|
557
607
|
let lastError;
|
|
608
|
+
const idempotencyKey = this.resolveIdempotencyKey(options.method || "GET", requestOptions);
|
|
609
|
+
const attemptOptions = idempotencyKey ? { ...requestOptions, idempotencyKey } : requestOptions;
|
|
558
610
|
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
559
611
|
try {
|
|
560
|
-
return await this.request(endpoint, options, serviceURL,
|
|
612
|
+
return await this.request(endpoint, options, serviceURL, attemptOptions);
|
|
561
613
|
} catch (error) {
|
|
562
614
|
lastError = error instanceof Error ? error : new Error("Unknown error");
|
|
563
615
|
if (requestOptions?.signal?.aborted) {
|
|
@@ -654,6 +706,9 @@ var BaseClient = class {
|
|
|
654
706
|
if (config.interceptors) {
|
|
655
707
|
this.interceptors = config.interceptors;
|
|
656
708
|
}
|
|
709
|
+
if (config.authProvider !== void 0 || config.apiKey !== void 0) {
|
|
710
|
+
this.authProvider = this.config.authProvider ?? (this.config.apiKey ? new StaticApiKeyProvider(this.config.apiKey) : void 0);
|
|
711
|
+
}
|
|
657
712
|
}
|
|
658
713
|
/**
|
|
659
714
|
* Get current configuration (readonly)
|
|
@@ -681,6 +736,61 @@ var BaseClient = class {
|
|
|
681
736
|
}
|
|
682
737
|
};
|
|
683
738
|
|
|
739
|
+
// src/geolocation/integrity.ts
|
|
740
|
+
var isNil = (v) => v === null || v === void 0;
|
|
741
|
+
function assessGpsIntegrity(input, opts = {}) {
|
|
742
|
+
const flags = [];
|
|
743
|
+
const now = opts.now ?? (() => Date.now());
|
|
744
|
+
const maxAgeMs = opts.maxAgeMs ?? 6e4;
|
|
745
|
+
const minAccuracy = opts.minAccuracyMeters ?? 1;
|
|
746
|
+
const { accuracy, altitude, altitudeAccuracy, heading, speed, timestamp } = input;
|
|
747
|
+
if (isNil(accuracy)) {
|
|
748
|
+
flags.push("accuracy_missing");
|
|
749
|
+
} else if (accuracy === 0) {
|
|
750
|
+
flags.push("accuracy_zero");
|
|
751
|
+
} else if (accuracy < minAccuracy) {
|
|
752
|
+
flags.push("accuracy_implausibly_small");
|
|
753
|
+
}
|
|
754
|
+
const hasMotion = !isNil(heading) || !isNil(speed);
|
|
755
|
+
if (hasMotion && (isNil(accuracy) || accuracy === 0)) {
|
|
756
|
+
flags.push("motion_without_accuracy");
|
|
757
|
+
}
|
|
758
|
+
if (!isNil(altitude) && isNil(altitudeAccuracy)) {
|
|
759
|
+
flags.push("altitude_without_accuracy");
|
|
760
|
+
}
|
|
761
|
+
if (timestamp !== void 0 && now() - timestamp > maxAgeMs) {
|
|
762
|
+
flags.push("stale_timestamp");
|
|
763
|
+
}
|
|
764
|
+
if (opts.permissionState === "denied" || opts.permissionState === "prompt") {
|
|
765
|
+
flags.push(`permission_${opts.permissionState}`);
|
|
766
|
+
}
|
|
767
|
+
return { suspicious: flags.length > 0, flags };
|
|
768
|
+
}
|
|
769
|
+
function gpsIntegrityInputFromPosition(position) {
|
|
770
|
+
const c = position.coords;
|
|
771
|
+
return {
|
|
772
|
+
latitude: c.latitude,
|
|
773
|
+
longitude: c.longitude,
|
|
774
|
+
accuracy: c.accuracy,
|
|
775
|
+
altitude: c.altitude,
|
|
776
|
+
altitudeAccuracy: c.altitudeAccuracy,
|
|
777
|
+
heading: c.heading,
|
|
778
|
+
speed: c.speed,
|
|
779
|
+
timestamp: position.timestamp
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
async function probeGeolocationPermission() {
|
|
783
|
+
try {
|
|
784
|
+
if (typeof navigator === "undefined" || !navigator.permissions?.query) {
|
|
785
|
+
return "unavailable";
|
|
786
|
+
}
|
|
787
|
+
const status = await navigator.permissions.query({ name: "geolocation" });
|
|
788
|
+
return status.state;
|
|
789
|
+
} catch {
|
|
790
|
+
return "unavailable";
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
|
|
684
794
|
// src/geolocation/ciphertext.ts
|
|
685
795
|
var CIPHER_TEXT_EXPIRY_MINUTES = 5;
|
|
686
796
|
async function computeHMAC(key, message) {
|
|
@@ -733,6 +843,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
|
|
|
733
843
|
if (typeof navigator === "undefined" || !navigator.geolocation) {
|
|
734
844
|
return null;
|
|
735
845
|
}
|
|
846
|
+
const permissionState = await probeGeolocationPermission();
|
|
736
847
|
return new Promise((resolve) => {
|
|
737
848
|
navigator.geolocation.getCurrentPosition(
|
|
738
849
|
(position) => {
|
|
@@ -749,6 +860,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
|
|
|
749
860
|
resolve(null);
|
|
750
861
|
return;
|
|
751
862
|
}
|
|
863
|
+
const { flags } = assessGpsIntegrity(gpsIntegrityInputFromPosition(position), { permissionState });
|
|
752
864
|
resolve({
|
|
753
865
|
latitude,
|
|
754
866
|
longitude,
|
|
@@ -757,7 +869,8 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
|
|
|
757
869
|
altitude_accuracy: position.coords.altitudeAccuracy ?? void 0,
|
|
758
870
|
heading: position.coords.heading ?? void 0,
|
|
759
871
|
speed: position.coords.speed ?? void 0,
|
|
760
|
-
timestamp: position.timestamp
|
|
872
|
+
timestamp: position.timestamp,
|
|
873
|
+
integrity_flags: flags.length ? flags : void 0
|
|
761
874
|
});
|
|
762
875
|
},
|
|
763
876
|
() => {
|
|
@@ -824,6 +937,9 @@ async function generateCipherText(options, config) {
|
|
|
824
937
|
);
|
|
825
938
|
if (location) {
|
|
826
939
|
locationData = location;
|
|
940
|
+
if (location.integrity_flags?.length) {
|
|
941
|
+
warnings.push(`GPS integrity flags (advisory): ${location.integrity_flags.join(", ")}`);
|
|
942
|
+
}
|
|
827
943
|
} else if (gpsRequiredByConfig) {
|
|
828
944
|
throw new VesantError(
|
|
829
945
|
`GPS location is required for ${options.reason} by tenant configuration, but GPS was not available or permission was denied`,
|
|
@@ -918,8 +1034,8 @@ var GeolocationClient = class extends BaseClient {
|
|
|
918
1034
|
* ```
|
|
919
1035
|
*/
|
|
920
1036
|
async verifyIP(request, requestOptions) {
|
|
921
|
-
if (!request.ip_address
|
|
922
|
-
throw new ValidationError("ip_address
|
|
1037
|
+
if (request.ip_address !== void 0 && !request.ip_address.trim()) {
|
|
1038
|
+
throw new ValidationError("ip_address, when provided, must be a non-empty string", ["ip_address"]);
|
|
923
1039
|
}
|
|
924
1040
|
return this.requestWithRetry("/api/v1/geo/verify", {
|
|
925
1041
|
method: "POST",
|
|
@@ -1269,20 +1385,12 @@ var GeolocationClient = class extends BaseClient {
|
|
|
1269
1385
|
*
|
|
1270
1386
|
* @example
|
|
1271
1387
|
* ```typescript
|
|
1272
|
-
* //
|
|
1388
|
+
* // GPS (the web SDK is GPS + IP only; the server handles the IP fallback)
|
|
1273
1389
|
* const result = await client.captureLocation(token, {
|
|
1274
1390
|
* latitude: 37.7749,
|
|
1275
1391
|
* longitude: -122.4194,
|
|
1276
1392
|
* accuracy: 10
|
|
1277
1393
|
* });
|
|
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
1394
|
* ```
|
|
1287
1395
|
*/
|
|
1288
1396
|
async captureLocation(token, capture, requestOptions) {
|