vesant-sdk 1.7.0-dev.fce9898 → 1.7.0-dev.fe84882
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 +133 -22
- package/dist/compliance/index.js.map +1 -1
- package/dist/compliance/index.mjs +133 -22
- 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 +68 -7
- package/dist/decisions/index.js.map +1 -1
- package/dist/decisions/index.mjs +68 -7
- 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 +136 -19
- package/dist/geolocation/index.js.map +1 -1
- package/dist/geolocation/index.mjs +134 -20
- package/dist/geolocation/index.mjs.map +1 -1
- package/dist/index-C3zUKydT.d.mts +264 -0
- package/dist/index-DSDgS09k.d.ts +264 -0
- package/dist/index.d.mts +26 -9
- package/dist/index.d.ts +26 -9
- package/dist/index.js +324 -57
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +317 -58
- 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 +94 -19
- package/dist/kyc/core.js.map +1 -1
- package/dist/kyc/core.mjs +94 -19
- package/dist/kyc/core.mjs.map +1 -1
- package/dist/kyc/index.d.mts +90 -13
- package/dist/kyc/index.d.ts +90 -13
- package/dist/kyc/index.js +94 -19
- package/dist/kyc/index.js.map +1 -1
- package/dist/kyc/index.mjs +94 -19
- 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 +68 -7
- package/dist/risk-profile/index.js.map +1 -1
- package/dist/risk-profile/index.mjs +68 -7
- 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 +68 -7
- package/dist/scores/index.js.map +1 -1
- package/dist/scores/index.mjs +68 -7
- 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 +73 -9
- package/dist/tax/index.js.map +1 -1
- package/dist/tax/index.mjs +73 -9
- 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,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) {
|
|
@@ -298,6 +311,12 @@ var BaseClient = class {
|
|
|
298
311
|
if (!config.tenantId?.trim()) {
|
|
299
312
|
throw new ValidationError("tenantId is required and must be a non-empty string", ["tenantId"]);
|
|
300
313
|
}
|
|
314
|
+
if (typeof fetch === "undefined") {
|
|
315
|
+
throw new VesantError(
|
|
316
|
+
"The Vesant SDK requires a global fetch (Node.js >= 18). Upgrade Node or provide a fetch polyfill.",
|
|
317
|
+
"RUNTIME_UNSUPPORTED"
|
|
318
|
+
);
|
|
319
|
+
}
|
|
301
320
|
this.interceptors = config.interceptors || [];
|
|
302
321
|
this.logger = config.logger || createConsoleLogger();
|
|
303
322
|
let environment = config.environment;
|
|
@@ -316,11 +335,12 @@ var BaseClient = class {
|
|
|
316
335
|
environment,
|
|
317
336
|
headers: config.headers || {},
|
|
318
337
|
timeout: config.timeout || 1e4,
|
|
319
|
-
retries: config.retries
|
|
338
|
+
retries: config.retries ?? 3,
|
|
320
339
|
debug: config.debug || false,
|
|
321
340
|
interceptors: this.interceptors,
|
|
322
341
|
logger: this.logger
|
|
323
342
|
};
|
|
343
|
+
this.authProvider = config.authProvider ?? (apiKey ? new StaticApiKeyProvider(apiKey) : void 0);
|
|
324
344
|
if (config.circuitBreaker) {
|
|
325
345
|
this.circuitBreaker = new CircuitBreaker(config.circuitBreaker);
|
|
326
346
|
}
|
|
@@ -328,6 +348,19 @@ var BaseClient = class {
|
|
|
328
348
|
this.rateLimitTracker = new RateLimitTracker();
|
|
329
349
|
}
|
|
330
350
|
}
|
|
351
|
+
/**
|
|
352
|
+
* Resolve the Idempotency-Key for a request. Mutating methods (POST/PUT/PATCH)
|
|
353
|
+
* get the caller-supplied key or a freshly minted UUID; non-mutating methods get
|
|
354
|
+
* none. requestWithRetry resolves this once and injects it so every retry reuses
|
|
355
|
+
* one key (letting the server dedup replays); a direct request() resolves per call.
|
|
356
|
+
*/
|
|
357
|
+
resolveIdempotencyKey(method, requestOptions) {
|
|
358
|
+
const isMutating = ["POST", "PUT", "PATCH"].includes((method || "GET").toUpperCase());
|
|
359
|
+
if (!isMutating) {
|
|
360
|
+
return void 0;
|
|
361
|
+
}
|
|
362
|
+
return requestOptions?.idempotencyKey ?? generateUUID();
|
|
363
|
+
}
|
|
331
364
|
/**
|
|
332
365
|
* Make an HTTP request with timeout and error handling
|
|
333
366
|
*/
|
|
@@ -353,15 +386,20 @@ var BaseClient = class {
|
|
|
353
386
|
...this.config.headers,
|
|
354
387
|
...options.headers || {}
|
|
355
388
|
};
|
|
356
|
-
|
|
357
|
-
|
|
389
|
+
const credential = await this.authProvider?.getCredential({
|
|
390
|
+
tenantId: this.config.tenantId,
|
|
391
|
+
requestId
|
|
392
|
+
});
|
|
393
|
+
if (credential) {
|
|
394
|
+
headers["Authorization"] = `${credential.scheme ?? "Bearer"} ${credential.token}`;
|
|
358
395
|
}
|
|
359
396
|
if (this.config.environment === "sandbox") {
|
|
360
397
|
headers["X-Sandbox"] = "true";
|
|
361
398
|
}
|
|
362
399
|
const method = (options.method || "GET").toUpperCase();
|
|
363
|
-
|
|
364
|
-
|
|
400
|
+
const idempotencyKey = this.resolveIdempotencyKey(method, requestOptions);
|
|
401
|
+
if (idempotencyKey) {
|
|
402
|
+
headers["Idempotency-Key"] = idempotencyKey;
|
|
365
403
|
}
|
|
366
404
|
const controller = new AbortController();
|
|
367
405
|
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
@@ -382,10 +420,28 @@ var BaseClient = class {
|
|
|
382
420
|
if (this.config.debug) {
|
|
383
421
|
this.logger.debug(`${finalOptions.method || "GET"} ${endpoint}`);
|
|
384
422
|
}
|
|
385
|
-
|
|
423
|
+
let response = await fetch(url, {
|
|
386
424
|
...finalOptions,
|
|
387
425
|
signal: controller.signal
|
|
388
426
|
});
|
|
427
|
+
if (response.status === 401 && this.authProvider?.canRefresh?.()) {
|
|
428
|
+
const refreshed = await this.authProvider.getCredential({
|
|
429
|
+
tenantId: this.config.tenantId,
|
|
430
|
+
requestId,
|
|
431
|
+
forceRefresh: true
|
|
432
|
+
});
|
|
433
|
+
if (refreshed) {
|
|
434
|
+
this.config.onCredentialRotated?.({ reason: "unauthorized" });
|
|
435
|
+
finalOptions = {
|
|
436
|
+
...finalOptions,
|
|
437
|
+
headers: {
|
|
438
|
+
...finalOptions.headers,
|
|
439
|
+
Authorization: `${refreshed.scheme ?? "Bearer"} ${refreshed.token}`
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
response = await fetch(url, { ...finalOptions, signal: controller.signal });
|
|
443
|
+
}
|
|
444
|
+
}
|
|
389
445
|
clearTimeout(timeoutId);
|
|
390
446
|
if (this.rateLimitTracker) {
|
|
391
447
|
this.rateLimitTracker.updateFromHeaders(response.headers);
|
|
@@ -474,9 +530,11 @@ var BaseClient = class {
|
|
|
474
530
|
*/
|
|
475
531
|
async requestWithRetry(endpoint, options = {}, serviceURL, retries = this.config.retries, requestOptions) {
|
|
476
532
|
let lastError;
|
|
533
|
+
const idempotencyKey = this.resolveIdempotencyKey(options.method || "GET", requestOptions);
|
|
534
|
+
const attemptOptions = idempotencyKey ? { ...requestOptions, idempotencyKey } : requestOptions;
|
|
477
535
|
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
478
536
|
try {
|
|
479
|
-
return await this.request(endpoint, options, serviceURL,
|
|
537
|
+
return await this.request(endpoint, options, serviceURL, attemptOptions);
|
|
480
538
|
} catch (error) {
|
|
481
539
|
lastError = error instanceof Error ? error : new Error("Unknown error");
|
|
482
540
|
if (requestOptions?.signal?.aborted) {
|
|
@@ -573,6 +631,9 @@ var BaseClient = class {
|
|
|
573
631
|
if (config.interceptors) {
|
|
574
632
|
this.interceptors = config.interceptors;
|
|
575
633
|
}
|
|
634
|
+
if (config.authProvider !== void 0 || config.apiKey !== void 0) {
|
|
635
|
+
this.authProvider = this.config.authProvider ?? (this.config.apiKey ? new StaticApiKeyProvider(this.config.apiKey) : void 0);
|
|
636
|
+
}
|
|
576
637
|
}
|
|
577
638
|
/**
|
|
578
639
|
* Get current configuration (readonly)
|
|
@@ -600,6 +661,61 @@ var BaseClient = class {
|
|
|
600
661
|
}
|
|
601
662
|
};
|
|
602
663
|
|
|
664
|
+
// src/geolocation/integrity.ts
|
|
665
|
+
var isNil = (v) => v === null || v === void 0;
|
|
666
|
+
function assessGpsIntegrity(input, opts = {}) {
|
|
667
|
+
const flags = [];
|
|
668
|
+
const now = opts.now ?? (() => Date.now());
|
|
669
|
+
const maxAgeMs = opts.maxAgeMs ?? 6e4;
|
|
670
|
+
const minAccuracy = opts.minAccuracyMeters ?? 1;
|
|
671
|
+
const { accuracy, altitude, altitudeAccuracy, heading, speed, timestamp } = input;
|
|
672
|
+
if (isNil(accuracy)) {
|
|
673
|
+
flags.push("accuracy_missing");
|
|
674
|
+
} else if (accuracy === 0) {
|
|
675
|
+
flags.push("accuracy_zero");
|
|
676
|
+
} else if (accuracy < minAccuracy) {
|
|
677
|
+
flags.push("accuracy_implausibly_small");
|
|
678
|
+
}
|
|
679
|
+
const hasMotion = !isNil(heading) || !isNil(speed);
|
|
680
|
+
if (hasMotion && (isNil(accuracy) || accuracy === 0)) {
|
|
681
|
+
flags.push("motion_without_accuracy");
|
|
682
|
+
}
|
|
683
|
+
if (!isNil(altitude) && isNil(altitudeAccuracy)) {
|
|
684
|
+
flags.push("altitude_without_accuracy");
|
|
685
|
+
}
|
|
686
|
+
if (timestamp !== void 0 && now() - timestamp > maxAgeMs) {
|
|
687
|
+
flags.push("stale_timestamp");
|
|
688
|
+
}
|
|
689
|
+
if (opts.permissionState === "denied" || opts.permissionState === "prompt") {
|
|
690
|
+
flags.push(`permission_${opts.permissionState}`);
|
|
691
|
+
}
|
|
692
|
+
return { suspicious: flags.length > 0, flags };
|
|
693
|
+
}
|
|
694
|
+
function gpsIntegrityInputFromPosition(position) {
|
|
695
|
+
const c = position.coords;
|
|
696
|
+
return {
|
|
697
|
+
latitude: c.latitude,
|
|
698
|
+
longitude: c.longitude,
|
|
699
|
+
accuracy: c.accuracy,
|
|
700
|
+
altitude: c.altitude,
|
|
701
|
+
altitudeAccuracy: c.altitudeAccuracy,
|
|
702
|
+
heading: c.heading,
|
|
703
|
+
speed: c.speed,
|
|
704
|
+
timestamp: position.timestamp
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
async function probeGeolocationPermission() {
|
|
708
|
+
try {
|
|
709
|
+
if (typeof navigator === "undefined" || !navigator.permissions?.query) {
|
|
710
|
+
return "unavailable";
|
|
711
|
+
}
|
|
712
|
+
const status = await navigator.permissions.query({ name: "geolocation" });
|
|
713
|
+
return status.state;
|
|
714
|
+
} catch {
|
|
715
|
+
return "unavailable";
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
603
719
|
// src/geolocation/ciphertext.ts
|
|
604
720
|
var CIPHER_TEXT_EXPIRY_MINUTES = 5;
|
|
605
721
|
async function computeHMAC(key, message) {
|
|
@@ -652,6 +768,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
|
|
|
652
768
|
if (typeof navigator === "undefined" || !navigator.geolocation) {
|
|
653
769
|
return null;
|
|
654
770
|
}
|
|
771
|
+
const permissionState = await probeGeolocationPermission();
|
|
655
772
|
return new Promise((resolve) => {
|
|
656
773
|
navigator.geolocation.getCurrentPosition(
|
|
657
774
|
(position) => {
|
|
@@ -668,6 +785,7 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
|
|
|
668
785
|
resolve(null);
|
|
669
786
|
return;
|
|
670
787
|
}
|
|
788
|
+
const { flags } = assessGpsIntegrity(gpsIntegrityInputFromPosition(position), { permissionState });
|
|
671
789
|
resolve({
|
|
672
790
|
latitude,
|
|
673
791
|
longitude,
|
|
@@ -676,7 +794,8 @@ async function requestGPSLocation(timeout = 1e4, highAccuracy = true) {
|
|
|
676
794
|
altitude_accuracy: position.coords.altitudeAccuracy ?? void 0,
|
|
677
795
|
heading: position.coords.heading ?? void 0,
|
|
678
796
|
speed: position.coords.speed ?? void 0,
|
|
679
|
-
timestamp: position.timestamp
|
|
797
|
+
timestamp: position.timestamp,
|
|
798
|
+
integrity_flags: flags.length ? flags : void 0
|
|
680
799
|
});
|
|
681
800
|
},
|
|
682
801
|
() => {
|
|
@@ -743,6 +862,9 @@ async function generateCipherText(options, config) {
|
|
|
743
862
|
);
|
|
744
863
|
if (location) {
|
|
745
864
|
locationData = location;
|
|
865
|
+
if (location.integrity_flags?.length) {
|
|
866
|
+
warnings.push(`GPS integrity flags (advisory): ${location.integrity_flags.join(", ")}`);
|
|
867
|
+
}
|
|
746
868
|
} else if (gpsRequiredByConfig) {
|
|
747
869
|
throw new VesantError(
|
|
748
870
|
`GPS location is required for ${options.reason} by tenant configuration, but GPS was not available or permission was denied`,
|
|
@@ -862,8 +984,8 @@ var GeolocationClient = class extends BaseClient {
|
|
|
862
984
|
* ```
|
|
863
985
|
*/
|
|
864
986
|
async verifyIP(request, requestOptions) {
|
|
865
|
-
if (!request.ip_address
|
|
866
|
-
throw new ValidationError("ip_address
|
|
987
|
+
if (request.ip_address !== void 0 && !request.ip_address.trim()) {
|
|
988
|
+
throw new ValidationError("ip_address, when provided, must be a non-empty string", ["ip_address"]);
|
|
867
989
|
}
|
|
868
990
|
return this.requestWithRetry("/api/v1/geo/verify", {
|
|
869
991
|
method: "POST",
|
|
@@ -1213,20 +1335,12 @@ var GeolocationClient = class extends BaseClient {
|
|
|
1213
1335
|
*
|
|
1214
1336
|
* @example
|
|
1215
1337
|
* ```typescript
|
|
1216
|
-
* //
|
|
1338
|
+
* // GPS (the web SDK is GPS + IP only; the server handles the IP fallback)
|
|
1217
1339
|
* const result = await client.captureLocation(token, {
|
|
1218
1340
|
* latitude: 37.7749,
|
|
1219
1341
|
* longitude: -122.4194,
|
|
1220
1342
|
* accuracy: 10
|
|
1221
1343
|
* });
|
|
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
1344
|
* ```
|
|
1231
1345
|
*/
|
|
1232
1346
|
async captureLocation(token, capture, requestOptions) {
|
|
@@ -1274,8 +1388,11 @@ var GeolocationClient = class extends BaseClient {
|
|
|
1274
1388
|
};
|
|
1275
1389
|
|
|
1276
1390
|
exports.GeolocationClient = GeolocationClient;
|
|
1391
|
+
exports.assessGpsIntegrity = assessGpsIntegrity;
|
|
1277
1392
|
exports.decodeCipherText = decodeCipherText;
|
|
1278
1393
|
exports.generateCipherText = generateCipherText;
|
|
1394
|
+
exports.gpsIntegrityInputFromPosition = gpsIntegrityInputFromPosition;
|
|
1279
1395
|
exports.isCipherTextExpired = isCipherTextExpired;
|
|
1396
|
+
exports.probeGeolocationPermission = probeGeolocationPermission;
|
|
1280
1397
|
//# sourceMappingURL=index.js.map
|
|
1281
1398
|
//# sourceMappingURL=index.js.map
|