verant_id_cloud_scan 1.4.4 → 1.4.5-beta.10
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/Api.js +180 -24
- package/CHANGELOG.md +198 -0
- package/CloudScan.js +260 -27
- package/FaceComparison.js +2 -4
- package/FormatUtils.js +145 -1
- package/LocalApi.js +16 -22
- package/ScannerApi.js +156 -76
- package/ScannerProfiles.js +132 -0
- package/WebSocketClient.js +281 -0
- package/index.d.ts +92 -2
- package/package.json +11 -2
package/Api.js
CHANGED
|
@@ -1,18 +1,112 @@
|
|
|
1
1
|
import { compressAndCompareImages } from "./FaceComparison.js";
|
|
2
2
|
import { formatDateToISO, DATE_FIELDS } from "./DateUtils.js";
|
|
3
3
|
import { FIELD_MAPPING, FIELD_DEFAULTS, getFieldValue } from "./FieldMapping.js";
|
|
4
|
+
import { sanitizeFieldForDmv } from "./FormatUtils.js";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Environment Detection & Management
|
|
8
|
+
*
|
|
9
|
+
* Defaults to PRODUCTION for all hosts (including localhost).
|
|
10
|
+
* Only verify-staging.verantid.com automatically uses staging.
|
|
11
|
+
* Host apps can explicitly override via setEnvironment('staging' | 'production').
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// Current environment - starts as null to trigger detection on first use
|
|
15
|
+
let currentEnvironment = null;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Detect environment based on hostname
|
|
19
|
+
* @returns {'staging' | 'production'}
|
|
20
|
+
*/
|
|
21
|
+
function detectEnvironment() {
|
|
22
|
+
// Default to production for all hosts
|
|
23
|
+
let environment = 'production';
|
|
24
|
+
|
|
25
|
+
// Only auto-switch to staging for VerantID's staging domain
|
|
26
|
+
if (typeof window !== 'undefined') {
|
|
27
|
+
const hostname = window.location.hostname;
|
|
28
|
+
|
|
29
|
+
// ONLY verify-staging.verantid.com uses staging by default
|
|
30
|
+
if (hostname === 'verify-staging.verantid.com') {
|
|
31
|
+
environment = 'staging';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// All other hostnames (localhost, customer sites, verify.verantid.com, etc.) use production
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
console.log('[CloudScan] Environment detected:', environment, 'on', typeof window !== 'undefined' ? window.location.hostname : 'server');
|
|
38
|
+
return environment;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Get current environment (detects if not already set)
|
|
43
|
+
* @returns {'staging' | 'production'}
|
|
44
|
+
*/
|
|
45
|
+
function getEnvironment() {
|
|
46
|
+
if (currentEnvironment === null) {
|
|
47
|
+
currentEnvironment = detectEnvironment();
|
|
48
|
+
}
|
|
49
|
+
return currentEnvironment;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Explicitly set the environment
|
|
54
|
+
* @param {'staging' | 'production'} environment
|
|
55
|
+
* @throws {Error} If environment is not 'staging' or 'production'
|
|
56
|
+
*/
|
|
57
|
+
export function setEnvironment(environment) {
|
|
58
|
+
if (environment !== 'staging' && environment !== 'production') {
|
|
59
|
+
throw new Error(`Invalid environment: "${environment}". Must be "staging" or "production".`);
|
|
60
|
+
}
|
|
61
|
+
currentEnvironment = environment;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get license server address based on current environment
|
|
66
|
+
* @returns {string}
|
|
67
|
+
*/
|
|
68
|
+
function getLicenseServerAddress() {
|
|
69
|
+
const env = getEnvironment();
|
|
70
|
+
return env === 'staging'
|
|
71
|
+
? "https://lic-staging.verantid.com/api/v1"
|
|
72
|
+
: "https://lic.verantid.com/api/v1";
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get DMV server address based on current environment
|
|
77
|
+
* @returns {string}
|
|
78
|
+
*/
|
|
79
|
+
function getDmvServerAddress() {
|
|
80
|
+
const env = getEnvironment();
|
|
81
|
+
return env === 'staging'
|
|
82
|
+
? "https://dmv-check-server-staging-fcaab48bec21.herokuapp.com/api/v1/dmv_check"
|
|
83
|
+
: "https://dmv.verantid.com/api/v1/dmv_check";
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Get Face Comparison server address based on current environment
|
|
88
|
+
* @returns {string}
|
|
89
|
+
*/
|
|
90
|
+
export function getFaceComparisonServerAddress() {
|
|
91
|
+
const env = getEnvironment();
|
|
92
|
+
return env === 'staging'
|
|
93
|
+
? "https://staging.face.verantid.bluerocket.us/compare_id_and_face"
|
|
94
|
+
: "https://faceid.verantid.com/compare_id_and_face";
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Get Mobile Verification server address based on current environment
|
|
99
|
+
* @returns {string}
|
|
100
|
+
*/
|
|
101
|
+
function getMobileVerificationServerAddress() {
|
|
102
|
+
const env = getEnvironment();
|
|
103
|
+
return env === 'staging'
|
|
104
|
+
? "https://staging.mdl.verantid.bluerocket.us"
|
|
105
|
+
: "https://mdl.verantid.bluerocket.us";
|
|
106
|
+
}
|
|
13
107
|
|
|
14
108
|
export const dmvCheck = async (clientId, scannerType, licenseData) => {
|
|
15
|
-
const url =
|
|
109
|
+
const url = getDmvServerAddress();
|
|
16
110
|
|
|
17
111
|
// Build the driver object dynamically.
|
|
18
112
|
const driver = {};
|
|
@@ -36,16 +130,8 @@ export const dmvCheck = async (clientId, scannerType, licenseData) => {
|
|
|
36
130
|
value = formatDateToISO(value);
|
|
37
131
|
}
|
|
38
132
|
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
-
const sexStr = String(value).trim().toUpperCase();
|
|
42
|
-
if (sexStr === 'M' || sexStr === 'MALE') {
|
|
43
|
-
value = '1';
|
|
44
|
-
} else if (sexStr === 'F' || sexStr === 'FEMALE') {
|
|
45
|
-
value = '2';
|
|
46
|
-
}
|
|
47
|
-
// If already 1 or 2, keep as is
|
|
48
|
-
}
|
|
133
|
+
// Sanitize field value for DMV/AAMVA submission
|
|
134
|
+
value = sanitizeFieldForDmv(fieldName, value);
|
|
49
135
|
|
|
50
136
|
driver[fieldName] = value;
|
|
51
137
|
});
|
|
@@ -111,7 +197,7 @@ export const dmvCheck = async (clientId, scannerType, licenseData) => {
|
|
|
111
197
|
};
|
|
112
198
|
|
|
113
199
|
export const checkDmvFeatureLicense = async (clientId) => {
|
|
114
|
-
const url =
|
|
200
|
+
const url = getLicenseServerAddress() + "/dmv_verifications/check_license";
|
|
115
201
|
const data = { client_id: clientId };
|
|
116
202
|
|
|
117
203
|
try {
|
|
@@ -145,7 +231,7 @@ export const checkDmvFeatureLicense = async (clientId) => {
|
|
|
145
231
|
};
|
|
146
232
|
|
|
147
233
|
export const checkFaceComparisonFeatureLicense = async (clientId) => {
|
|
148
|
-
const url =
|
|
234
|
+
const url = getLicenseServerAddress() + "/facial_scans/check_license";
|
|
149
235
|
const data = { client_id: clientId };
|
|
150
236
|
|
|
151
237
|
try {
|
|
@@ -179,7 +265,7 @@ export const checkFaceComparisonFeatureLicense = async (clientId) => {
|
|
|
179
265
|
}
|
|
180
266
|
|
|
181
267
|
export const checkLicense = async (clientId, macAddress) => {
|
|
182
|
-
const url =
|
|
268
|
+
const url = getLicenseServerAddress() + "/check_license";
|
|
183
269
|
const data = { client_id: clientId, mac_address: macAddress };
|
|
184
270
|
|
|
185
271
|
try {
|
|
@@ -214,7 +300,7 @@ export const checkLicense = async (clientId, macAddress) => {
|
|
|
214
300
|
* @returns {Promise<boolean>} True if autoDmv is enabled
|
|
215
301
|
*/
|
|
216
302
|
export const checkAutoDmvEnabled = async (clientId) => {
|
|
217
|
-
const url =
|
|
303
|
+
const url = getLicenseServerAddress() + "/check_feature_license";
|
|
218
304
|
const data = { client_id: clientId };
|
|
219
305
|
|
|
220
306
|
try {
|
|
@@ -239,7 +325,7 @@ export const checkAutoDmvEnabled = async (clientId) => {
|
|
|
239
325
|
}
|
|
240
326
|
};
|
|
241
327
|
export const getBarcodeLicenseKey = async () => {
|
|
242
|
-
const url =
|
|
328
|
+
const url = getLicenseServerAddress() + "/get_barcode_license_key";
|
|
243
329
|
|
|
244
330
|
try {
|
|
245
331
|
const response = await fetch(url, {
|
|
@@ -272,6 +358,9 @@ const postToScannerApi = async (
|
|
|
272
358
|
formattedAddress = `http://${scannerAddress}`;
|
|
273
359
|
}
|
|
274
360
|
|
|
361
|
+
// Remove trailing slash to prevent double slashes in URL
|
|
362
|
+
formattedAddress = formattedAddress.replace(/\/+$/, '');
|
|
363
|
+
|
|
275
364
|
let apiAddress = `${formattedAddress}/securelink`;
|
|
276
365
|
|
|
277
366
|
const controller = new AbortController();
|
|
@@ -362,3 +451,70 @@ export const checkScannerPresent = async (scannerAddress) => {
|
|
|
362
451
|
return false;
|
|
363
452
|
}
|
|
364
453
|
};
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Create a verification session for mobile ID verification
|
|
457
|
+
*
|
|
458
|
+
* POST /sessions
|
|
459
|
+
* Returns: session_id, session_url (for QR code), websocket_url (for real-time updates)
|
|
460
|
+
*
|
|
461
|
+
* @param {string} userId - User ID for the verification session
|
|
462
|
+
* @param {string} clientId - Client ID for licensing and tracking
|
|
463
|
+
* @param {string} [origin] - Holder page origin; binds the server's
|
|
464
|
+
* SessionTranscript to the wallet's view (HPKE info). Required on non-default hosts.
|
|
465
|
+
* @returns {Promise<Object>} Session data with session_id, session_url, and websocket_url
|
|
466
|
+
*/
|
|
467
|
+
export const createVerificationSession = async (userId, clientId, origin) => {
|
|
468
|
+
const url = getMobileVerificationServerAddress() + "/sessions";
|
|
469
|
+
const data = { user_id: userId, client_id: clientId };
|
|
470
|
+
if (origin) {
|
|
471
|
+
data.origin = origin;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
try {
|
|
475
|
+
const response = await fetch(url, {
|
|
476
|
+
method: "POST",
|
|
477
|
+
headers: {
|
|
478
|
+
"Content-Type": "application/json",
|
|
479
|
+
},
|
|
480
|
+
body: JSON.stringify(data),
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
if (response.ok) {
|
|
484
|
+
const responseData = await response.json();
|
|
485
|
+
return responseData;
|
|
486
|
+
} else {
|
|
487
|
+
// Read the body once as text — fetch consumes the stream on first read,
|
|
488
|
+
// so a `response.json()` then `response.text()` fallback would throw
|
|
489
|
+
// `TypeError: body stream already read` and mask the original error.
|
|
490
|
+
const errorText = await response.text();
|
|
491
|
+
let errorData = null;
|
|
492
|
+
try {
|
|
493
|
+
errorData = JSON.parse(errorText);
|
|
494
|
+
} catch {
|
|
495
|
+
// Non-JSON body (e.g. plain text 502 from API Gateway).
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
if (errorData) {
|
|
499
|
+
console.error("Verification session creation failed:", errorData);
|
|
500
|
+
return {
|
|
501
|
+
status: 'error',
|
|
502
|
+
message: errorData.message || 'Failed to create verification session',
|
|
503
|
+
error: errorData,
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
console.error("Verification session creation failed:", errorText);
|
|
507
|
+
return {
|
|
508
|
+
status: 'error',
|
|
509
|
+
message: 'Failed to create verification session',
|
|
510
|
+
raw_error: errorText,
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
} catch (error) {
|
|
514
|
+
console.error("There was a problem with the verification session request:", error);
|
|
515
|
+
return {
|
|
516
|
+
status: 'error',
|
|
517
|
+
message: error.message || 'Unable to connect to verification service.'
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
};
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.4.5-beta.10] - 2026-05-11
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- iOS HPKE decryption failure on non-default hosts (e.g. ngrok tunnels,
|
|
12
|
+
custom staging domains). `startMobileVerification()` now derives the
|
|
13
|
+
holder page origin from `mobileVerifyBaseUrl` (falling back to the
|
|
14
|
+
CSR page's `window.location.origin` for same-origin dev setups) and
|
|
15
|
+
forwards it to `POST /sessions`. The backend uses this origin to
|
|
16
|
+
build its SessionTranscript, which must match the origin the mobile
|
|
17
|
+
wallet binds to. Without it, the server fell back to a per-environment
|
|
18
|
+
default that disagreed with the wallet's view, causing
|
|
19
|
+
`"Decryption failed: Could not decrypt credential response"` (400).
|
|
20
|
+
- `WebSocketClient.connect()` no longer hangs forever when the underlying
|
|
21
|
+
socket emits `onerror` or `onclose` before `onopen`. The returned Promise
|
|
22
|
+
now rejects with a tagged error in those paths so awaiters can handle
|
|
23
|
+
connection failures instead of waiting indefinitely.
|
|
24
|
+
- `startMobileVerification()` QR code URL construction now uses `new URL()`
|
|
25
|
+
to safely combine `mobileVerifyBaseUrl` with the session id. Previously,
|
|
26
|
+
a base URL containing a query string or hash (e.g. `https://host/path?x=1`)
|
|
27
|
+
produced an invalid result like `https://host/path?x=1/{session_id}`.
|
|
28
|
+
- `createVerificationSession()` no longer throws "body stream already
|
|
29
|
+
read" when an error response is not valid JSON. The response body is
|
|
30
|
+
now read once as text, then parsed in a try/catch instead of using
|
|
31
|
+
`response.json()` followed by a `response.text()` fallback.
|
|
32
|
+
- `startMobileVerification()` no longer emits duplicate `onError`
|
|
33
|
+
callbacks when a WebSocket failure surfaces via both
|
|
34
|
+
`WebSocketClient.connect()` and the outer catch. Errors already
|
|
35
|
+
reported by a lower layer carry an `error.reported` flag, and the
|
|
36
|
+
outer catch skips re-emitting in that case.
|
|
37
|
+
- `WebSocketClient.connect()` now invokes `callbacks.onError` from the
|
|
38
|
+
close-before-open path (previously only `onerror` did). Direct
|
|
39
|
+
`connectToVerificationSession` callers receive the failure event
|
|
40
|
+
even when no preceding `onerror` fires (e.g., server closes the
|
|
41
|
+
socket immediately). The synthesized error carries `reported: true`
|
|
42
|
+
so `startMobileVerification`'s outer catch still avoids double-emit.
|
|
43
|
+
- `WebSocketClient._handleMessage()` no longer logs the raw WebSocket
|
|
44
|
+
frame to the console. Verification payloads carry PII (mDL fields,
|
|
45
|
+
portrait base64), so the raw `console.log` of `data` was dropped.
|
|
46
|
+
Per-route type logs below remain for debug visibility.
|
|
47
|
+
- `WebSocketClient.connect()` now releases its socket reference when
|
|
48
|
+
`onerror` fires before `onopen`, so callers can immediately retry
|
|
49
|
+
`connect()` without hitting "WebSocket connection already exists"
|
|
50
|
+
in implementations where `onclose` doesn't fire after `onerror`.
|
|
51
|
+
- `WebSocketClient` now transitions to the `ERROR` state (not
|
|
52
|
+
`CLOSED`) when the socket closes before opening, so
|
|
53
|
+
`status`/`onStatusChange` reflect a connection failure rather than
|
|
54
|
+
a normal disconnect. Post-open closes still transition to `CLOSED`.
|
|
55
|
+
Now driven by an explicit `hasOpened` flag (set in `onopen`) — the
|
|
56
|
+
previous version used the Promise's `settled` flag, which is also
|
|
57
|
+
set by pre-open `onerror` and would incorrectly downgrade the
|
|
58
|
+
ERROR state to CLOSED when the follow-up onclose fired.
|
|
59
|
+
- `WebSocketClient.connect()` synchronous-throw rejections now carry
|
|
60
|
+
a stable `.code` (`NO_WEBSOCKET_IMPL` when the Node fallback fails,
|
|
61
|
+
`CONNECTION_FAILED` when the `WebSocket` constructor throws). The
|
|
62
|
+
thrown/rejected error now matches the structured `onError` payload,
|
|
63
|
+
so awaiters of the Promise can branch on the failure reason without
|
|
64
|
+
relying on the `onError` callback.
|
|
65
|
+
- `WebSocketClient.disconnect()` called while the socket is still
|
|
66
|
+
CONNECTING no longer reports a spurious connection error. The
|
|
67
|
+
`onclose` triggered by the user-initiated close used to flip
|
|
68
|
+
`status` from `closed` back to `error` and emit `onError`; it now
|
|
69
|
+
detects an instance-level `_closeRequested` flag set by
|
|
70
|
+
`disconnect()` and skips both. The pending `connect()` Promise
|
|
71
|
+
rejects with `code: 'CLIENT_DISCONNECTED'` so awaiters resolve.
|
|
72
|
+
- `WebSocketClient._handleMessage()` now decodes binary WebSocket
|
|
73
|
+
frames (Node `Buffer` from the `ws` package, browser `ArrayBuffer`
|
|
74
|
+
/ `Uint8Array` when `binaryType === 'arraybuffer'`) via `TextDecoder`
|
|
75
|
+
before `JSON.parse`. Previously, anything that wasn't a string
|
|
76
|
+
passed through as-is, so `routeKey` was always undefined and every
|
|
77
|
+
frame was silently dropped as "Unknown message route."
|
|
78
|
+
- Removed informational `console.log` calls from the mobile
|
|
79
|
+
verification code path (`WebSocketClient` + `startMobileVerification`).
|
|
80
|
+
Several of them embedded the `session_id` or QR target URL, which
|
|
81
|
+
is effectively a session access token and shouldn't be sent to
|
|
82
|
+
application logs / monitoring. Diagnostic `console.warn` and
|
|
83
|
+
`console.error` calls are preserved.
|
|
84
|
+
|
|
85
|
+
### Changed
|
|
86
|
+
- `startMobileVerification()` error callbacks now emit stage-specific
|
|
87
|
+
codes — `SESSION_CREATION_FAILED`, `QR_GENERATION_FAILED`, or
|
|
88
|
+
`WEBSOCKET_CONNECTION_FAILED` — so callers can distinguish which step
|
|
89
|
+
failed. Upstream `error.code` values are preserved when present.
|
|
90
|
+
|
|
91
|
+
### Internal
|
|
92
|
+
- The internal `createVerificationSession()` API helper gained an
|
|
93
|
+
optional third `origin` parameter; `startMobileVerification()` now
|
|
94
|
+
populates it from `mobileVerifyBaseUrl` (or `window.location.origin`
|
|
95
|
+
for same-origin dev). Host apps don't need to change anything — keep
|
|
96
|
+
calling `startMobileVerification()` as before.
|
|
97
|
+
- `package.json` now declares a `"browser": { "ws": false }` field so
|
|
98
|
+
browser bundlers (Vite / Webpack / Rollup) stub out the Node-only
|
|
99
|
+
`ws` optional dependency instead of trying to bundle it. Has no
|
|
100
|
+
effect in Node — the dynamic `import('ws')` fallback still works.
|
|
101
|
+
|
|
102
|
+
## [1.4.5-beta.9] - 2026-04-21
|
|
103
|
+
|
|
104
|
+
### Added
|
|
105
|
+
- Mobile ID verification support (VNT-1409, VNT-1419, VNT-1429, VNT-1455)
|
|
106
|
+
- Added `startMobileVerification()` function to initiate mobile verification sessions
|
|
107
|
+
- Added `createVerificationSession()` API function to create verification sessions with user ID and client ID
|
|
108
|
+
- Added WebSocket client (`WebSocketClient.js`) for real-time verification updates from AWS API Gateway
|
|
109
|
+
- Added mobile verification server address configuration with environment detection
|
|
110
|
+
- QR code generation for mobile verification sessions with customizable base URLs
|
|
111
|
+
- Real-time verification callbacks: `onVerificationStarted`, `onResult`, `onStatusChange`, `onError`
|
|
112
|
+
- Session management with session ID, session URL, WebSocket URL, and QR code SVG
|
|
113
|
+
- Connection state management (CONNECTING, OPEN, CLOSED, ERROR) for WebSocket connections
|
|
114
|
+
|
|
115
|
+
### Changed
|
|
116
|
+
- Updated environment detection to support mobile verification endpoints
|
|
117
|
+
- Mobile verification uses `staging.mdl.verantid.bluerocket.us` for staging
|
|
118
|
+
- Mobile verification uses `mdl.verantid.bluerocket.us` for production
|
|
119
|
+
- Updated scanner type detection to use `scannerProfile` from scanner response in auto-DMV verification
|
|
120
|
+
- Enhanced TypeScript definitions (`index.d.ts`) to include mobile verification types and callbacks
|
|
121
|
+
|
|
122
|
+
## [1.4.5-beta.8] - 2026-04-15
|
|
123
|
+
|
|
124
|
+
### Changed
|
|
125
|
+
- Moved UV/IR image type definitions to scanner profile configuration
|
|
126
|
+
- Added `frontUvImageType`, `backUvImageType`, `frontIrImageType`, and `backIrImageType` to IDXpressPlus profile
|
|
127
|
+
- Updated image extraction logic to use profile-defined UV/IR types instead of hardcoded strings
|
|
128
|
+
- Updated TypeScript definitions (`index.d.ts`) to include UV/IR base64 fields in `scanId` return type
|
|
129
|
+
- Removed UV/IR fields from local scanner functions (`localScanId`, `localContinueScanId`) as local scanners do not support UV/IR imaging
|
|
130
|
+
|
|
131
|
+
### Fixed
|
|
132
|
+
- Eliminated redundant variable declarations in `ScannerApi.js` by declaring UV/IR variables at function scope
|
|
133
|
+
|
|
134
|
+
## [1.4.5-beta.7] - 2026-04-15
|
|
135
|
+
|
|
136
|
+
### Changed
|
|
137
|
+
- Internal refactoring and code review fixes
|
|
138
|
+
|
|
139
|
+
## [1.4.5-beta.6] - 2026-04-15
|
|
140
|
+
|
|
141
|
+
### Added
|
|
142
|
+
- UV/IR image support for IDXpressPlus scanner profile
|
|
143
|
+
- Added `licenseFrontUvBase64`, `licenseBackUvBase64`, `licenseFrontIrBase64`, and `licenseBackIrBase64` fields to scan results
|
|
144
|
+
- Scanner now captures and returns ultraviolet (UV) and infrared (IR) images alongside standard color images
|
|
145
|
+
- Image types supported: fclr (front color), rclr (rear color), fclruv (front UV), rclruv (rear UV), fgsir (front IR), rgsir (rear IR)
|
|
146
|
+
|
|
147
|
+
### Fixed
|
|
148
|
+
- Image extraction logic now captures all image types from scanner response instead of only front/back color images
|
|
149
|
+
|
|
150
|
+
### Changed
|
|
151
|
+
- Updated IDXpressPlus scanner profile to include UV/IR parameters in default settings and restore configuration
|
|
152
|
+
- Added `clrUvIrResolution`, `fclrUvEnabled`, `rclrUvEnabled`, `fgsIrEnabled`, and `rgsIrEnabled` to `restoreParamKeys`
|
|
153
|
+
- Updated `ScannerApi.js` to extract UV/IR images from GetDocument response
|
|
154
|
+
- Updated `CloudScan.js` `scanId` function to return UV/IR image data (`licenseFrontUvBase64`, `licenseBackUvBase64`, `licenseFrontIrBase64`, `licenseBackIrBase64`)
|
|
155
|
+
- Local scanner functions (`localScanId`, `localContinueScanId`) do not include UV/IR fields as local scanners (VerantId6S) do not support UV/IR imaging
|
|
156
|
+
|
|
157
|
+
## [1.4.5-beta.5] - 2026-04-14
|
|
158
|
+
|
|
159
|
+
### Changed
|
|
160
|
+
- Applied dynamic environment URLs to face comparison feature
|
|
161
|
+
|
|
162
|
+
## [1.4.5-beta.4] - 2026-04-14
|
|
163
|
+
|
|
164
|
+
### Added
|
|
165
|
+
- Error validation for invalid environment type
|
|
166
|
+
|
|
167
|
+
### Changed
|
|
168
|
+
- Updated default server URLs to production endpoints
|
|
169
|
+
|
|
170
|
+
## [1.4.5-beta.3] - 2026-04-13
|
|
171
|
+
|
|
172
|
+
### Fixed
|
|
173
|
+
- Various bug fixes and code quality improvements
|
|
174
|
+
|
|
175
|
+
## [1.4.5-beta.2] - 2026-04-12
|
|
176
|
+
|
|
177
|
+
### Added
|
|
178
|
+
- Dynamic environment detection for server URLs
|
|
179
|
+
- Support for multiple deployment environments
|
|
180
|
+
|
|
181
|
+
### Changed
|
|
182
|
+
- Server address handling now supports trailing slashes
|
|
183
|
+
- Code improvements based on Copilot suggestions
|
|
184
|
+
|
|
185
|
+
## [1.4.5-beta.1] - 2026-04-11
|
|
186
|
+
|
|
187
|
+
### Added
|
|
188
|
+
- IDXpress scanner profiles support
|
|
189
|
+
- New scanner profile configuration options
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Version Number Guide
|
|
194
|
+
|
|
195
|
+
- **Major** (1.x.x): Breaking changes
|
|
196
|
+
- **Minor** (x.4.x): New features, backwards compatible
|
|
197
|
+
- **Patch** (x.x.5): Bug fixes, backwards compatible
|
|
198
|
+
- **Beta** (x.x.x-beta.x): Pre-release versions for testing
|