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,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) {
|
|
@@ -319,6 +332,7 @@ var BaseClient = class {
|
|
|
319
332
|
interceptors: this.interceptors,
|
|
320
333
|
logger: this.logger
|
|
321
334
|
};
|
|
335
|
+
this.authProvider = config.authProvider ?? (apiKey ? new StaticApiKeyProvider(apiKey) : void 0);
|
|
322
336
|
if (config.circuitBreaker) {
|
|
323
337
|
this.circuitBreaker = new CircuitBreaker(config.circuitBreaker);
|
|
324
338
|
}
|
|
@@ -326,6 +340,19 @@ var BaseClient = class {
|
|
|
326
340
|
this.rateLimitTracker = new RateLimitTracker();
|
|
327
341
|
}
|
|
328
342
|
}
|
|
343
|
+
/**
|
|
344
|
+
* Resolve the Idempotency-Key for a request. Mutating methods (POST/PUT/PATCH)
|
|
345
|
+
* get the caller-supplied key or a freshly minted UUID; non-mutating methods get
|
|
346
|
+
* none. requestWithRetry resolves this once and injects it so every retry reuses
|
|
347
|
+
* one key (letting the server dedup replays); a direct request() resolves per call.
|
|
348
|
+
*/
|
|
349
|
+
resolveIdempotencyKey(method, requestOptions) {
|
|
350
|
+
const isMutating = ["POST", "PUT", "PATCH"].includes((method || "GET").toUpperCase());
|
|
351
|
+
if (!isMutating) {
|
|
352
|
+
return void 0;
|
|
353
|
+
}
|
|
354
|
+
return requestOptions?.idempotencyKey ?? generateUUID();
|
|
355
|
+
}
|
|
329
356
|
/**
|
|
330
357
|
* Make an HTTP request with timeout and error handling
|
|
331
358
|
*/
|
|
@@ -351,15 +378,20 @@ var BaseClient = class {
|
|
|
351
378
|
...this.config.headers,
|
|
352
379
|
...options.headers || {}
|
|
353
380
|
};
|
|
354
|
-
|
|
355
|
-
|
|
381
|
+
const credential = await this.authProvider?.getCredential({
|
|
382
|
+
tenantId: this.config.tenantId,
|
|
383
|
+
requestId
|
|
384
|
+
});
|
|
385
|
+
if (credential) {
|
|
386
|
+
headers["Authorization"] = `${credential.scheme ?? "Bearer"} ${credential.token}`;
|
|
356
387
|
}
|
|
357
388
|
if (this.config.environment === "sandbox") {
|
|
358
389
|
headers["X-Sandbox"] = "true";
|
|
359
390
|
}
|
|
360
391
|
const method = (options.method || "GET").toUpperCase();
|
|
361
|
-
|
|
362
|
-
|
|
392
|
+
const idempotencyKey = this.resolveIdempotencyKey(method, requestOptions);
|
|
393
|
+
if (idempotencyKey) {
|
|
394
|
+
headers["Idempotency-Key"] = idempotencyKey;
|
|
363
395
|
}
|
|
364
396
|
const controller = new AbortController();
|
|
365
397
|
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
@@ -380,10 +412,28 @@ var BaseClient = class {
|
|
|
380
412
|
if (this.config.debug) {
|
|
381
413
|
this.logger.debug(`${finalOptions.method || "GET"} ${endpoint}`);
|
|
382
414
|
}
|
|
383
|
-
|
|
415
|
+
let response = await fetch(url, {
|
|
384
416
|
...finalOptions,
|
|
385
417
|
signal: controller.signal
|
|
386
418
|
});
|
|
419
|
+
if (response.status === 401 && this.authProvider?.canRefresh?.()) {
|
|
420
|
+
const refreshed = await this.authProvider.getCredential({
|
|
421
|
+
tenantId: this.config.tenantId,
|
|
422
|
+
requestId,
|
|
423
|
+
forceRefresh: true
|
|
424
|
+
});
|
|
425
|
+
if (refreshed) {
|
|
426
|
+
this.config.onCredentialRotated?.({ reason: "unauthorized" });
|
|
427
|
+
finalOptions = {
|
|
428
|
+
...finalOptions,
|
|
429
|
+
headers: {
|
|
430
|
+
...finalOptions.headers,
|
|
431
|
+
Authorization: `${refreshed.scheme ?? "Bearer"} ${refreshed.token}`
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
response = await fetch(url, { ...finalOptions, signal: controller.signal });
|
|
435
|
+
}
|
|
436
|
+
}
|
|
387
437
|
clearTimeout(timeoutId);
|
|
388
438
|
if (this.rateLimitTracker) {
|
|
389
439
|
this.rateLimitTracker.updateFromHeaders(response.headers);
|
|
@@ -472,9 +522,11 @@ var BaseClient = class {
|
|
|
472
522
|
*/
|
|
473
523
|
async requestWithRetry(endpoint, options = {}, serviceURL, retries = this.config.retries, requestOptions) {
|
|
474
524
|
let lastError;
|
|
525
|
+
const idempotencyKey = this.resolveIdempotencyKey(options.method || "GET", requestOptions);
|
|
526
|
+
const attemptOptions = idempotencyKey ? { ...requestOptions, idempotencyKey } : requestOptions;
|
|
475
527
|
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
476
528
|
try {
|
|
477
|
-
return await this.request(endpoint, options, serviceURL,
|
|
529
|
+
return await this.request(endpoint, options, serviceURL, attemptOptions);
|
|
478
530
|
} catch (error) {
|
|
479
531
|
lastError = error instanceof Error ? error : new Error("Unknown error");
|
|
480
532
|
if (requestOptions?.signal?.aborted) {
|
|
@@ -571,6 +623,9 @@ var BaseClient = class {
|
|
|
571
623
|
if (config.interceptors) {
|
|
572
624
|
this.interceptors = config.interceptors;
|
|
573
625
|
}
|
|
626
|
+
if (config.authProvider !== void 0 || config.apiKey !== void 0) {
|
|
627
|
+
this.authProvider = this.config.authProvider ?? (this.config.apiKey ? new StaticApiKeyProvider(this.config.apiKey) : void 0);
|
|
628
|
+
}
|
|
574
629
|
}
|
|
575
630
|
/**
|
|
576
631
|
* Get current configuration (readonly)
|
|
@@ -598,6 +653,61 @@ var BaseClient = class {
|
|
|
598
653
|
}
|
|
599
654
|
};
|
|
600
655
|
|
|
656
|
+
// src/geolocation/integrity.ts
|
|
657
|
+
var isNil = (v) => v === null || v === void 0;
|
|
658
|
+
function assessGpsIntegrity(input, opts = {}) {
|
|
659
|
+
const flags = [];
|
|
660
|
+
const now = opts.now ?? (() => Date.now());
|
|
661
|
+
const maxAgeMs = opts.maxAgeMs ?? 6e4;
|
|
662
|
+
const minAccuracy = opts.minAccuracyMeters ?? 1;
|
|
663
|
+
const { accuracy, altitude, altitudeAccuracy, heading, speed, timestamp } = input;
|
|
664
|
+
if (isNil(accuracy)) {
|
|
665
|
+
flags.push("accuracy_missing");
|
|
666
|
+
} else if (accuracy === 0) {
|
|
667
|
+
flags.push("accuracy_zero");
|
|
668
|
+
} else if (accuracy < minAccuracy) {
|
|
669
|
+
flags.push("accuracy_implausibly_small");
|
|
670
|
+
}
|
|
671
|
+
const hasMotion = !isNil(heading) || !isNil(speed);
|
|
672
|
+
if (hasMotion && (isNil(accuracy) || accuracy === 0)) {
|
|
673
|
+
flags.push("motion_without_accuracy");
|
|
674
|
+
}
|
|
675
|
+
if (!isNil(altitude) && isNil(altitudeAccuracy)) {
|
|
676
|
+
flags.push("altitude_without_accuracy");
|
|
677
|
+
}
|
|
678
|
+
if (timestamp !== void 0 && now() - timestamp > maxAgeMs) {
|
|
679
|
+
flags.push("stale_timestamp");
|
|
680
|
+
}
|
|
681
|
+
if (opts.permissionState === "denied" || opts.permissionState === "prompt") {
|
|
682
|
+
flags.push(`permission_${opts.permissionState}`);
|
|
683
|
+
}
|
|
684
|
+
return { suspicious: flags.length > 0, flags };
|
|
685
|
+
}
|
|
686
|
+
function gpsIntegrityInputFromPosition(position) {
|
|
687
|
+
const c = position.coords;
|
|
688
|
+
return {
|
|
689
|
+
latitude: c.latitude,
|
|
690
|
+
longitude: c.longitude,
|
|
691
|
+
accuracy: c.accuracy,
|
|
692
|
+
altitude: c.altitude,
|
|
693
|
+
altitudeAccuracy: c.altitudeAccuracy,
|
|
694
|
+
heading: c.heading,
|
|
695
|
+
speed: c.speed,
|
|
696
|
+
timestamp: position.timestamp
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
async function probeGeolocationPermission() {
|
|
700
|
+
try {
|
|
701
|
+
if (typeof navigator === "undefined" || !navigator.permissions?.query) {
|
|
702
|
+
return "unavailable";
|
|
703
|
+
}
|
|
704
|
+
const status = await navigator.permissions.query({ name: "geolocation" });
|
|
705
|
+
return status.state;
|
|
706
|
+
} catch {
|
|
707
|
+
return "unavailable";
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
|
|
601
711
|
// src/geolocation/ciphertext.ts
|
|
602
712
|
var CIPHER_TEXT_EXPIRY_MINUTES = 5;
|
|
603
713
|
async function computeHMAC(key, message) {
|
|
@@ -650,6 +760,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
|
|
|
650
760
|
if (typeof navigator === "undefined" || !navigator.geolocation) {
|
|
651
761
|
return null;
|
|
652
762
|
}
|
|
763
|
+
const permissionState = await probeGeolocationPermission();
|
|
653
764
|
return new Promise((resolve) => {
|
|
654
765
|
navigator.geolocation.getCurrentPosition(
|
|
655
766
|
(position) => {
|
|
@@ -666,6 +777,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
|
|
|
666
777
|
resolve(null);
|
|
667
778
|
return;
|
|
668
779
|
}
|
|
780
|
+
const { flags } = assessGpsIntegrity(gpsIntegrityInputFromPosition(position), { permissionState });
|
|
669
781
|
resolve({
|
|
670
782
|
latitude,
|
|
671
783
|
longitude,
|
|
@@ -674,7 +786,8 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
|
|
|
674
786
|
altitude_accuracy: position.coords.altitudeAccuracy ?? void 0,
|
|
675
787
|
heading: position.coords.heading ?? void 0,
|
|
676
788
|
speed: position.coords.speed ?? void 0,
|
|
677
|
-
timestamp: position.timestamp
|
|
789
|
+
timestamp: position.timestamp,
|
|
790
|
+
integrity_flags: flags.length ? flags : void 0
|
|
678
791
|
});
|
|
679
792
|
},
|
|
680
793
|
() => {
|
|
@@ -741,6 +854,9 @@ async function generateCipherText(options, config) {
|
|
|
741
854
|
);
|
|
742
855
|
if (location) {
|
|
743
856
|
locationData = location;
|
|
857
|
+
if (location.integrity_flags?.length) {
|
|
858
|
+
warnings.push(`GPS integrity flags (advisory): ${location.integrity_flags.join(", ")}`);
|
|
859
|
+
}
|
|
744
860
|
} else if (gpsRequiredByConfig) {
|
|
745
861
|
throw new VesantError(
|
|
746
862
|
`GPS location is required for ${options.reason} by tenant configuration, but GPS was not available or permission was denied`,
|
|
@@ -860,8 +976,8 @@ var GeolocationClient = class extends BaseClient {
|
|
|
860
976
|
* ```
|
|
861
977
|
*/
|
|
862
978
|
async verifyIP(request, requestOptions) {
|
|
863
|
-
if (!request.ip_address
|
|
864
|
-
throw new ValidationError("ip_address
|
|
979
|
+
if (request.ip_address !== void 0 && !request.ip_address.trim()) {
|
|
980
|
+
throw new ValidationError("ip_address, when provided, must be a non-empty string", ["ip_address"]);
|
|
865
981
|
}
|
|
866
982
|
return this.requestWithRetry("/api/v1/geo/verify", {
|
|
867
983
|
method: "POST",
|
|
@@ -1211,20 +1327,12 @@ var GeolocationClient = class extends BaseClient {
|
|
|
1211
1327
|
*
|
|
1212
1328
|
* @example
|
|
1213
1329
|
* ```typescript
|
|
1214
|
-
* //
|
|
1330
|
+
* // GPS (the web SDK is GPS + IP only; the server handles the IP fallback)
|
|
1215
1331
|
* const result = await client.captureLocation(token, {
|
|
1216
1332
|
* latitude: 37.7749,
|
|
1217
1333
|
* longitude: -122.4194,
|
|
1218
1334
|
* accuracy: 10
|
|
1219
1335
|
* });
|
|
1220
|
-
*
|
|
1221
|
-
* // Using WiFi positioning (fallback)
|
|
1222
|
-
* const result = await client.captureLocation(token, {
|
|
1223
|
-
* wifi_networks: [
|
|
1224
|
-
* { macAddress: "00:11:22:33:44:55", signalStrength: -50 },
|
|
1225
|
-
* { macAddress: "AA:BB:CC:DD:EE:FF", signalStrength: -70 }
|
|
1226
|
-
* ]
|
|
1227
|
-
* });
|
|
1228
1336
|
* ```
|
|
1229
1337
|
*/
|
|
1230
1338
|
async captureLocation(token, capture, requestOptions) {
|
|
@@ -1271,6 +1379,6 @@ var GeolocationClient = class extends BaseClient {
|
|
|
1271
1379
|
// ============================================================================
|
|
1272
1380
|
};
|
|
1273
1381
|
|
|
1274
|
-
export { GeolocationClient, decodeCipherText, generateCipherText, isCipherTextExpired };
|
|
1382
|
+
export { GeolocationClient, assessGpsIntegrity, decodeCipherText, generateCipherText, gpsIntegrityInputFromPosition, isCipherTextExpired, probeGeolocationPermission };
|
|
1275
1383
|
//# sourceMappingURL=index.mjs.map
|
|
1276
1384
|
//# sourceMappingURL=index.mjs.map
|