vesant-sdk 1.7.0-dev.7d59b3e → 1.7.0-dev.80b25e7
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-DoMSYMMR.d.ts → client-0NOPDnT0.d.ts} +29 -26
- package/dist/{client-DMIRx7Tu.d.mts → client-CvWNRwwg.d.mts} +29 -26
- package/dist/{client-ZNdnpWe7.d.mts → client-Dps40EtF.d.mts} +2 -2
- package/dist/{client-C3DCmGe9.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 -21
- package/dist/compliance/index.js.map +1 -1
- package/dist/compliance/index.mjs +126 -21
- 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.d.mts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +209 -36
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +205 -37
- 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 +87 -18
- package/dist/kyc/core.js.map +1 -1
- package/dist/kyc/core.mjs +87 -18
- package/dist/kyc/core.mjs.map +1 -1
- package/dist/kyc/index.d.mts +110 -13
- package/dist/kyc/index.d.ts +110 -13
- package/dist/kyc/index.js +87 -18
- package/dist/kyc/index.js.map +1 -1
- package/dist/kyc/index.mjs +87 -18
- package/dist/kyc/index.mjs.map +1 -1
- package/dist/react.d.mts +9 -3
- package/dist/react.d.ts +9 -3
- package/dist/react.js +180 -77
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +180 -77
- 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 +20 -3
- package/dist/tax/index.d.ts +20 -3
- package/dist/tax/index.js +70 -9
- package/dist/tax/index.js.map +1 -1
- package/dist/tax/index.mjs +70 -9
- package/dist/tax/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
// src/core/auth.ts
|
|
4
|
+
var StaticApiKeyProvider = class {
|
|
5
|
+
constructor(apiKey) {
|
|
6
|
+
this.apiKey = apiKey;
|
|
7
|
+
}
|
|
8
|
+
async getCredential() {
|
|
9
|
+
return this.apiKey ? { scheme: "Bearer", token: this.apiKey } : null;
|
|
10
|
+
}
|
|
11
|
+
canRefresh() {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
3
16
|
// src/core/errors.ts
|
|
4
17
|
var VesantError = class _VesantError extends Error {
|
|
5
18
|
constructor(message, code, statusCode, details) {
|
|
@@ -321,6 +334,7 @@ var BaseClient = class {
|
|
|
321
334
|
interceptors: this.interceptors,
|
|
322
335
|
logger: this.logger
|
|
323
336
|
};
|
|
337
|
+
this.authProvider = config.authProvider ?? (apiKey ? new StaticApiKeyProvider(apiKey) : void 0);
|
|
324
338
|
if (config.circuitBreaker) {
|
|
325
339
|
this.circuitBreaker = new CircuitBreaker(config.circuitBreaker);
|
|
326
340
|
}
|
|
@@ -328,6 +342,19 @@ var BaseClient = class {
|
|
|
328
342
|
this.rateLimitTracker = new RateLimitTracker();
|
|
329
343
|
}
|
|
330
344
|
}
|
|
345
|
+
/**
|
|
346
|
+
* Resolve the Idempotency-Key for a request. Mutating methods (POST/PUT/PATCH)
|
|
347
|
+
* get the caller-supplied key or a freshly minted UUID; non-mutating methods get
|
|
348
|
+
* none. requestWithRetry resolves this once and injects it so every retry reuses
|
|
349
|
+
* one key (letting the server dedup replays); a direct request() resolves per call.
|
|
350
|
+
*/
|
|
351
|
+
resolveIdempotencyKey(method, requestOptions) {
|
|
352
|
+
const isMutating = ["POST", "PUT", "PATCH"].includes((method || "GET").toUpperCase());
|
|
353
|
+
if (!isMutating) {
|
|
354
|
+
return void 0;
|
|
355
|
+
}
|
|
356
|
+
return requestOptions?.idempotencyKey ?? generateUUID();
|
|
357
|
+
}
|
|
331
358
|
/**
|
|
332
359
|
* Make an HTTP request with timeout and error handling
|
|
333
360
|
*/
|
|
@@ -353,15 +380,20 @@ var BaseClient = class {
|
|
|
353
380
|
...this.config.headers,
|
|
354
381
|
...options.headers || {}
|
|
355
382
|
};
|
|
356
|
-
|
|
357
|
-
|
|
383
|
+
const credential = await this.authProvider?.getCredential({
|
|
384
|
+
tenantId: this.config.tenantId,
|
|
385
|
+
requestId
|
|
386
|
+
});
|
|
387
|
+
if (credential) {
|
|
388
|
+
headers["Authorization"] = `${credential.scheme ?? "Bearer"} ${credential.token}`;
|
|
358
389
|
}
|
|
359
390
|
if (this.config.environment === "sandbox") {
|
|
360
391
|
headers["X-Sandbox"] = "true";
|
|
361
392
|
}
|
|
362
393
|
const method = (options.method || "GET").toUpperCase();
|
|
363
|
-
|
|
364
|
-
|
|
394
|
+
const idempotencyKey = this.resolveIdempotencyKey(method, requestOptions);
|
|
395
|
+
if (idempotencyKey) {
|
|
396
|
+
headers["Idempotency-Key"] = idempotencyKey;
|
|
365
397
|
}
|
|
366
398
|
const controller = new AbortController();
|
|
367
399
|
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
@@ -382,10 +414,28 @@ var BaseClient = class {
|
|
|
382
414
|
if (this.config.debug) {
|
|
383
415
|
this.logger.debug(`${finalOptions.method || "GET"} ${endpoint}`);
|
|
384
416
|
}
|
|
385
|
-
|
|
417
|
+
let response = await fetch(url, {
|
|
386
418
|
...finalOptions,
|
|
387
419
|
signal: controller.signal
|
|
388
420
|
});
|
|
421
|
+
if (response.status === 401 && this.authProvider?.canRefresh?.()) {
|
|
422
|
+
const refreshed = await this.authProvider.getCredential({
|
|
423
|
+
tenantId: this.config.tenantId,
|
|
424
|
+
requestId,
|
|
425
|
+
forceRefresh: true
|
|
426
|
+
});
|
|
427
|
+
if (refreshed) {
|
|
428
|
+
this.config.onCredentialRotated?.({ reason: "unauthorized" });
|
|
429
|
+
finalOptions = {
|
|
430
|
+
...finalOptions,
|
|
431
|
+
headers: {
|
|
432
|
+
...finalOptions.headers,
|
|
433
|
+
Authorization: `${refreshed.scheme ?? "Bearer"} ${refreshed.token}`
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
response = await fetch(url, { ...finalOptions, signal: controller.signal });
|
|
437
|
+
}
|
|
438
|
+
}
|
|
389
439
|
clearTimeout(timeoutId);
|
|
390
440
|
if (this.rateLimitTracker) {
|
|
391
441
|
this.rateLimitTracker.updateFromHeaders(response.headers);
|
|
@@ -474,9 +524,11 @@ var BaseClient = class {
|
|
|
474
524
|
*/
|
|
475
525
|
async requestWithRetry(endpoint, options = {}, serviceURL, retries = this.config.retries, requestOptions) {
|
|
476
526
|
let lastError;
|
|
527
|
+
const idempotencyKey = this.resolveIdempotencyKey(options.method || "GET", requestOptions);
|
|
528
|
+
const attemptOptions = idempotencyKey ? { ...requestOptions, idempotencyKey } : requestOptions;
|
|
477
529
|
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
478
530
|
try {
|
|
479
|
-
return await this.request(endpoint, options, serviceURL,
|
|
531
|
+
return await this.request(endpoint, options, serviceURL, attemptOptions);
|
|
480
532
|
} catch (error) {
|
|
481
533
|
lastError = error instanceof Error ? error : new Error("Unknown error");
|
|
482
534
|
if (requestOptions?.signal?.aborted) {
|
|
@@ -573,6 +625,9 @@ var BaseClient = class {
|
|
|
573
625
|
if (config.interceptors) {
|
|
574
626
|
this.interceptors = config.interceptors;
|
|
575
627
|
}
|
|
628
|
+
if (config.authProvider !== void 0 || config.apiKey !== void 0) {
|
|
629
|
+
this.authProvider = this.config.authProvider ?? (this.config.apiKey ? new StaticApiKeyProvider(this.config.apiKey) : void 0);
|
|
630
|
+
}
|
|
576
631
|
}
|
|
577
632
|
/**
|
|
578
633
|
* Get current configuration (readonly)
|
|
@@ -600,6 +655,61 @@ var BaseClient = class {
|
|
|
600
655
|
}
|
|
601
656
|
};
|
|
602
657
|
|
|
658
|
+
// src/geolocation/integrity.ts
|
|
659
|
+
var isNil = (v) => v === null || v === void 0;
|
|
660
|
+
function assessGpsIntegrity(input, opts = {}) {
|
|
661
|
+
const flags = [];
|
|
662
|
+
const now = opts.now ?? (() => Date.now());
|
|
663
|
+
const maxAgeMs = opts.maxAgeMs ?? 6e4;
|
|
664
|
+
const minAccuracy = opts.minAccuracyMeters ?? 1;
|
|
665
|
+
const { accuracy, altitude, altitudeAccuracy, heading, speed, timestamp } = input;
|
|
666
|
+
if (isNil(accuracy)) {
|
|
667
|
+
flags.push("accuracy_missing");
|
|
668
|
+
} else if (accuracy === 0) {
|
|
669
|
+
flags.push("accuracy_zero");
|
|
670
|
+
} else if (accuracy < minAccuracy) {
|
|
671
|
+
flags.push("accuracy_implausibly_small");
|
|
672
|
+
}
|
|
673
|
+
const hasMotion = !isNil(heading) || !isNil(speed);
|
|
674
|
+
if (hasMotion && (isNil(accuracy) || accuracy === 0)) {
|
|
675
|
+
flags.push("motion_without_accuracy");
|
|
676
|
+
}
|
|
677
|
+
if (!isNil(altitude) && isNil(altitudeAccuracy)) {
|
|
678
|
+
flags.push("altitude_without_accuracy");
|
|
679
|
+
}
|
|
680
|
+
if (timestamp !== void 0 && now() - timestamp > maxAgeMs) {
|
|
681
|
+
flags.push("stale_timestamp");
|
|
682
|
+
}
|
|
683
|
+
if (opts.permissionState === "denied" || opts.permissionState === "prompt") {
|
|
684
|
+
flags.push(`permission_${opts.permissionState}`);
|
|
685
|
+
}
|
|
686
|
+
return { suspicious: flags.length > 0, flags };
|
|
687
|
+
}
|
|
688
|
+
function gpsIntegrityInputFromPosition(position) {
|
|
689
|
+
const c = position.coords;
|
|
690
|
+
return {
|
|
691
|
+
latitude: c.latitude,
|
|
692
|
+
longitude: c.longitude,
|
|
693
|
+
accuracy: c.accuracy,
|
|
694
|
+
altitude: c.altitude,
|
|
695
|
+
altitudeAccuracy: c.altitudeAccuracy,
|
|
696
|
+
heading: c.heading,
|
|
697
|
+
speed: c.speed,
|
|
698
|
+
timestamp: position.timestamp
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
async function probeGeolocationPermission() {
|
|
702
|
+
try {
|
|
703
|
+
if (typeof navigator === "undefined" || !navigator.permissions?.query) {
|
|
704
|
+
return "unavailable";
|
|
705
|
+
}
|
|
706
|
+
const status = await navigator.permissions.query({ name: "geolocation" });
|
|
707
|
+
return status.state;
|
|
708
|
+
} catch {
|
|
709
|
+
return "unavailable";
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
|
|
603
713
|
// src/geolocation/ciphertext.ts
|
|
604
714
|
var CIPHER_TEXT_EXPIRY_MINUTES = 5;
|
|
605
715
|
async function computeHMAC(key, message) {
|
|
@@ -652,6 +762,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
|
|
|
652
762
|
if (typeof navigator === "undefined" || !navigator.geolocation) {
|
|
653
763
|
return null;
|
|
654
764
|
}
|
|
765
|
+
const permissionState = await probeGeolocationPermission();
|
|
655
766
|
return new Promise((resolve) => {
|
|
656
767
|
navigator.geolocation.getCurrentPosition(
|
|
657
768
|
(position) => {
|
|
@@ -668,6 +779,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
|
|
|
668
779
|
resolve(null);
|
|
669
780
|
return;
|
|
670
781
|
}
|
|
782
|
+
const { flags } = assessGpsIntegrity(gpsIntegrityInputFromPosition(position), { permissionState });
|
|
671
783
|
resolve({
|
|
672
784
|
latitude,
|
|
673
785
|
longitude,
|
|
@@ -676,7 +788,8 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
|
|
|
676
788
|
altitude_accuracy: position.coords.altitudeAccuracy ?? void 0,
|
|
677
789
|
heading: position.coords.heading ?? void 0,
|
|
678
790
|
speed: position.coords.speed ?? void 0,
|
|
679
|
-
timestamp: position.timestamp
|
|
791
|
+
timestamp: position.timestamp,
|
|
792
|
+
integrity_flags: flags.length ? flags : void 0
|
|
680
793
|
});
|
|
681
794
|
},
|
|
682
795
|
() => {
|
|
@@ -743,6 +856,9 @@ async function generateCipherText(options, config) {
|
|
|
743
856
|
);
|
|
744
857
|
if (location) {
|
|
745
858
|
locationData = location;
|
|
859
|
+
if (location.integrity_flags?.length) {
|
|
860
|
+
warnings.push(`GPS integrity flags (advisory): ${location.integrity_flags.join(", ")}`);
|
|
861
|
+
}
|
|
746
862
|
} else if (gpsRequiredByConfig) {
|
|
747
863
|
throw new VesantError(
|
|
748
864
|
`GPS location is required for ${options.reason} by tenant configuration, but GPS was not available or permission was denied`,
|
|
@@ -862,8 +978,8 @@ var GeolocationClient = class extends BaseClient {
|
|
|
862
978
|
* ```
|
|
863
979
|
*/
|
|
864
980
|
async verifyIP(request, requestOptions) {
|
|
865
|
-
if (!request.ip_address
|
|
866
|
-
throw new ValidationError("ip_address
|
|
981
|
+
if (request.ip_address !== void 0 && !request.ip_address.trim()) {
|
|
982
|
+
throw new ValidationError("ip_address, when provided, must be a non-empty string", ["ip_address"]);
|
|
867
983
|
}
|
|
868
984
|
return this.requestWithRetry("/api/v1/geo/verify", {
|
|
869
985
|
method: "POST",
|
|
@@ -1213,20 +1329,12 @@ var GeolocationClient = class extends BaseClient {
|
|
|
1213
1329
|
*
|
|
1214
1330
|
* @example
|
|
1215
1331
|
* ```typescript
|
|
1216
|
-
* //
|
|
1332
|
+
* // GPS (the web SDK is GPS + IP only; the server handles the IP fallback)
|
|
1217
1333
|
* const result = await client.captureLocation(token, {
|
|
1218
1334
|
* latitude: 37.7749,
|
|
1219
1335
|
* longitude: -122.4194,
|
|
1220
1336
|
* accuracy: 10
|
|
1221
1337
|
* });
|
|
1222
|
-
*
|
|
1223
|
-
* // Using WiFi positioning (fallback)
|
|
1224
|
-
* const result = await client.captureLocation(token, {
|
|
1225
|
-
* wifi_networks: [
|
|
1226
|
-
* { macAddress: "00:11:22:33:44:55", signalStrength: -50 },
|
|
1227
|
-
* { macAddress: "AA:BB:CC:DD:EE:FF", signalStrength: -70 }
|
|
1228
|
-
* ]
|
|
1229
|
-
* });
|
|
1230
1338
|
* ```
|
|
1231
1339
|
*/
|
|
1232
1340
|
async captureLocation(token, capture, requestOptions) {
|
|
@@ -1274,8 +1382,11 @@ var GeolocationClient = class extends BaseClient {
|
|
|
1274
1382
|
};
|
|
1275
1383
|
|
|
1276
1384
|
exports.GeolocationClient = GeolocationClient;
|
|
1385
|
+
exports.assessGpsIntegrity = assessGpsIntegrity;
|
|
1277
1386
|
exports.decodeCipherText = decodeCipherText;
|
|
1278
1387
|
exports.generateCipherText = generateCipherText;
|
|
1388
|
+
exports.gpsIntegrityInputFromPosition = gpsIntegrityInputFromPosition;
|
|
1279
1389
|
exports.isCipherTextExpired = isCipherTextExpired;
|
|
1390
|
+
exports.probeGeolocationPermission = probeGeolocationPermission;
|
|
1280
1391
|
//# sourceMappingURL=index.js.map
|
|
1281
1392
|
//# sourceMappingURL=index.js.map
|