vesant-sdk 1.7.0-dev.b2c9ecf → 1.7.0-dev.b4284ca
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-B32yBt1b.d.ts → client-0NOPDnT0.d.ts} +16 -26
- package/dist/{client-BqPVh5jH.d.mts → client-CvWNRwwg.d.mts} +16 -26
- package/dist/{client-CHPEgasE.d.mts → client-Dps40EtF.d.mts} +2 -2
- package/dist/{client-pKE_gii_.d.ts → client-SMxqod4j.d.ts} +2 -2
- package/dist/{client-6sSaxufk.d.mts → client-q9fN8Hhf.d.mts} +96 -1
- package/dist/{client-6sSaxufk.d.ts → client-q9fN8Hhf.d.ts} +96 -1
- package/dist/compliance/index.d.mts +3 -3
- package/dist/compliance/index.d.ts +3 -3
- package/dist/compliance/index.js +114 -16
- package/dist/compliance/index.js.map +1 -1
- package/dist/compliance/index.mjs +114 -16
- 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 +49 -4
- package/dist/decisions/index.js.map +1 -1
- package/dist/decisions/index.mjs +49 -4
- 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 +117 -16
- package/dist/geolocation/index.js.map +1 -1
- package/dist/geolocation/index.mjs +115 -17
- 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 +25 -8
- package/dist/index.d.ts +25 -8
- package/dist/index.js +274 -37
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +267 -38
- 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 +49 -4
- package/dist/kyc/core.js.map +1 -1
- package/dist/kyc/core.mjs +49 -4
- package/dist/kyc/core.mjs.map +1 -1
- package/dist/kyc/index.d.mts +1 -1
- package/dist/kyc/index.d.ts +1 -1
- package/dist/kyc/index.js +49 -4
- package/dist/kyc/index.js.map +1 -1
- package/dist/kyc/index.mjs +49 -4
- 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 +49 -4
- package/dist/risk-profile/index.js.map +1 -1
- package/dist/risk-profile/index.mjs +49 -4
- 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 +49 -4
- package/dist/scores/index.js.map +1 -1
- package/dist/scores/index.mjs +49 -4
- package/dist/scores/index.mjs.map +1 -1
- package/dist/tax/index.d.mts +1 -1
- package/dist/tax/index.d.ts +1 -1
- package/dist/tax/index.js +49 -4
- package/dist/tax/index.js.map +1 -1
- package/dist/tax/index.mjs +49 -4
- 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
|
@@ -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) {
|
|
@@ -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
|
|
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
|
}
|
|
@@ -364,8 +384,12 @@ var BaseClient = class {
|
|
|
364
384
|
...this.config.headers,
|
|
365
385
|
...options.headers || {}
|
|
366
386
|
};
|
|
367
|
-
|
|
368
|
-
|
|
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}`;
|
|
369
393
|
}
|
|
370
394
|
if (this.config.environment === "sandbox") {
|
|
371
395
|
headers["X-Sandbox"] = "true";
|
|
@@ -394,10 +418,28 @@ var BaseClient = class {
|
|
|
394
418
|
if (this.config.debug) {
|
|
395
419
|
this.logger.debug(`${finalOptions.method || "GET"} ${endpoint}`);
|
|
396
420
|
}
|
|
397
|
-
|
|
421
|
+
let response = await fetch(url, {
|
|
398
422
|
...finalOptions,
|
|
399
423
|
signal: controller.signal
|
|
400
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
|
+
}
|
|
401
443
|
clearTimeout(timeoutId);
|
|
402
444
|
if (this.rateLimitTracker) {
|
|
403
445
|
this.rateLimitTracker.updateFromHeaders(response.headers);
|
|
@@ -587,6 +629,9 @@ var BaseClient = class {
|
|
|
587
629
|
if (config.interceptors) {
|
|
588
630
|
this.interceptors = config.interceptors;
|
|
589
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
|
+
}
|
|
590
635
|
}
|
|
591
636
|
/**
|
|
592
637
|
* Get current configuration (readonly)
|
|
@@ -614,6 +659,61 @@ var BaseClient = class {
|
|
|
614
659
|
}
|
|
615
660
|
};
|
|
616
661
|
|
|
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");
|
|
686
|
+
}
|
|
687
|
+
if (opts.permissionState === "denied" || opts.permissionState === "prompt") {
|
|
688
|
+
flags.push(`permission_${opts.permissionState}`);
|
|
689
|
+
}
|
|
690
|
+
return { suspicious: flags.length > 0, flags };
|
|
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
|
+
|
|
617
717
|
// src/geolocation/ciphertext.ts
|
|
618
718
|
var CIPHER_TEXT_EXPIRY_MINUTES = 5;
|
|
619
719
|
async function computeHMAC(key, message) {
|
|
@@ -666,6 +766,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
|
|
|
666
766
|
if (typeof navigator === "undefined" || !navigator.geolocation) {
|
|
667
767
|
return null;
|
|
668
768
|
}
|
|
769
|
+
const permissionState = await probeGeolocationPermission();
|
|
669
770
|
return new Promise((resolve) => {
|
|
670
771
|
navigator.geolocation.getCurrentPosition(
|
|
671
772
|
(position) => {
|
|
@@ -682,6 +783,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
|
|
|
682
783
|
resolve(null);
|
|
683
784
|
return;
|
|
684
785
|
}
|
|
786
|
+
const { flags } = assessGpsIntegrity(gpsIntegrityInputFromPosition(position), { permissionState });
|
|
685
787
|
resolve({
|
|
686
788
|
latitude,
|
|
687
789
|
longitude,
|
|
@@ -690,7 +792,8 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
|
|
|
690
792
|
altitude_accuracy: position.coords.altitudeAccuracy ?? void 0,
|
|
691
793
|
heading: position.coords.heading ?? void 0,
|
|
692
794
|
speed: position.coords.speed ?? void 0,
|
|
693
|
-
timestamp: position.timestamp
|
|
795
|
+
timestamp: position.timestamp,
|
|
796
|
+
integrity_flags: flags.length ? flags : void 0
|
|
694
797
|
});
|
|
695
798
|
},
|
|
696
799
|
() => {
|
|
@@ -757,6 +860,9 @@ async function generateCipherText(options, config) {
|
|
|
757
860
|
);
|
|
758
861
|
if (location) {
|
|
759
862
|
locationData = location;
|
|
863
|
+
if (location.integrity_flags?.length) {
|
|
864
|
+
warnings.push(`GPS integrity flags (advisory): ${location.integrity_flags.join(", ")}`);
|
|
865
|
+
}
|
|
760
866
|
} else if (gpsRequiredByConfig) {
|
|
761
867
|
throw new VesantError(
|
|
762
868
|
`GPS location is required for ${options.reason} by tenant configuration, but GPS was not available or permission was denied`,
|
|
@@ -876,8 +982,8 @@ var GeolocationClient = class extends BaseClient {
|
|
|
876
982
|
* ```
|
|
877
983
|
*/
|
|
878
984
|
async verifyIP(request, requestOptions) {
|
|
879
|
-
if (!request.ip_address
|
|
880
|
-
throw new ValidationError("ip_address
|
|
985
|
+
if (request.ip_address !== void 0 && !request.ip_address.trim()) {
|
|
986
|
+
throw new ValidationError("ip_address, when provided, must be a non-empty string", ["ip_address"]);
|
|
881
987
|
}
|
|
882
988
|
return this.requestWithRetry("/api/v1/geo/verify", {
|
|
883
989
|
method: "POST",
|
|
@@ -1227,20 +1333,12 @@ var GeolocationClient = class extends BaseClient {
|
|
|
1227
1333
|
*
|
|
1228
1334
|
* @example
|
|
1229
1335
|
* ```typescript
|
|
1230
|
-
* //
|
|
1336
|
+
* // GPS (the web SDK is GPS + IP only; the server handles the IP fallback)
|
|
1231
1337
|
* const result = await client.captureLocation(token, {
|
|
1232
1338
|
* latitude: 37.7749,
|
|
1233
1339
|
* longitude: -122.4194,
|
|
1234
1340
|
* accuracy: 10
|
|
1235
1341
|
* });
|
|
1236
|
-
*
|
|
1237
|
-
* // Using WiFi positioning (fallback)
|
|
1238
|
-
* const result = await client.captureLocation(token, {
|
|
1239
|
-
* wifi_networks: [
|
|
1240
|
-
* { macAddress: "00:11:22:33:44:55", signalStrength: -50 },
|
|
1241
|
-
* { macAddress: "AA:BB:CC:DD:EE:FF", signalStrength: -70 }
|
|
1242
|
-
* ]
|
|
1243
|
-
* });
|
|
1244
1342
|
* ```
|
|
1245
1343
|
*/
|
|
1246
1344
|
async captureLocation(token, capture, requestOptions) {
|
|
@@ -1287,6 +1385,6 @@ var GeolocationClient = class extends BaseClient {
|
|
|
1287
1385
|
// ============================================================================
|
|
1288
1386
|
};
|
|
1289
1387
|
|
|
1290
|
-
export { GeolocationClient, decodeCipherText, generateCipherText, isCipherTextExpired };
|
|
1388
|
+
export { GeolocationClient, assessGpsIntegrity, decodeCipherText, generateCipherText, gpsIntegrityInputFromPosition, isCipherTextExpired, probeGeolocationPermission };
|
|
1291
1389
|
//# sourceMappingURL=index.mjs.map
|
|
1292
1390
|
//# sourceMappingURL=index.mjs.map
|