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