# Web SDK 2.0 Release Notes

Every published release of the Incode Web SDK 2.x packages, newest first.

`@incodetech/core` and `@incodetech/web` are versioned in lock-step — a given release number always
refers to both packages, and they must be installed at matching versions. New integrations should
start from [Getting Started](/sdk-reference/web-sdk-2-getting-started/).

```bash
npm install @incodetech/web@latest @incodetech/core@latest
```

<Callout icon="📘" theme="info">
  ### Looking for Web SDK 1.x? Its release notes are on

  [Web SDK Release Notes](/release-notes/releases-web-sdk/). The 1.x
  (`@incodetech/welcome`) and 2.x package lines are versioned independently.
</Callout>

## 2.1.1 — 2026-07-30

### Changed

- `@incodetech/core` and `@incodetech/web` now publish ISC license metadata and a `LICENSE` file, so
  automated license scanners resolve the packages instead of rejecting them for missing license
  information. Metadata only — no API or runtime behavior changes.
- Updated the bundled on-device processing runtime.

### Fixed

- The SDK now initializes on hardened hosts and in webviews where Web Storage is unavailable —
  removed, blocked, or replaced. Values that cannot be persisted are skipped and reads fall back to
  defaults, instead of the SDK failing to start.
- Antifraud, device-integrity, and anti-injection hardening.

Install: `npm install @incodetech/web@2.1.1 @incodetech/core@2.1.1`

## 2.1.0 — 2026-07-10

### Added

- **Certificate Issuance** module (`CERTIFICATE_ISSUANCE`) — password capture, digital certificate
  issuance, and download. Available as `createCertificateIssuanceManager` from
  `@incodetech/core/certificate-issuance` and as `<incode-certificate-issuance>`. See
  [Certificate Issuance](/sdk-reference/web-sdk-2-module-certificate-issuance/).
- **Fiscal QR** module (`FISCAL_QR`) — scans a Mexican fiscal (SAT) QR code, resolves its URL, and
  submits it for verification.
- **Field Comparison** module (`FIELD_COMPARISON`) — collects a first and last name and submits them
  for backend verification.
- **INE Validation** (`INE_VALIDATION`) — the Mexican government / INE check, available through the
  same manager and component as [Government Validation](/sdk-reference/web-sdk-2-module-gov-validation-1/).
- **ML Consent** (`ML_CONSENT`) — supported in both flows and workflows through the shared mandatory<br />consent module.
- **Video Selfie** with local recording.
- **Privacy Lens** — an opt-in cosmetic avatar rendered in place of the live camera preview during
  selfie and authentication capture, with a reassurance banner above the capture frame. Detection,
  quality, liveness, and upload continue to run on the real camera frames; enable it from your
  dashboard configuration.
- `setup()` gained options for controlling third-party dependencies and self-hosting:
  - `fingerprint: false` — skips client-side device-fingerprint submission.
  - `ipLookup: false` — skips the client IP lookup.
  - `i18n` — supply your own i18n instance (`@incodetech/web`).
  - `wasm: { basePath }` — serve the on-device processing assets from your own origin. See
    [WASM Configuration](/sdk-reference/web-sdk-2-wasm/).
  - `devMode` and `wasm: { showLogs }` — development diagnostics. Do not enable in production.
- `extractIdFace: false` on `IdCaptureConfig` skips face extraction from the ID document, for flows
  that do not run a biometric comparison. See [ID Capture](/sdk-reference/web-sdk-2-module-id-capture/).
- `showFinishScreenBySessionStatus` on the workflow configuration renders a finish screen specific to
  the resolved session status. See [Workflow](/sdk-reference/web-sdk-2-module-workflow/).
- ID Capture and Face Capture emit new events:
  - `errorTriggered` for every front-end error state — capture and upload errors, expired document,
    offline or degraded network, and fatal errors — with an `{ errorName, errorCode, reason }`
    payload.
  - `background` and `foreground` when the page's visibility changes during an active session,
    carrying the current screen. A session opened in an already-hidden tab reports it on start. See
    [Event Callbacks](/sdk-reference/web-sdk-2-event-callbacks/).
- Form modules expose per-field validation. `validateField()` on the manager triggers validation for
  a single field on blur, and a `validationErrors` map on the state drives the displayed messages.
  Available on **eKYC**, **eKYB**, **Dynamic Forms**, **ID OCR**, and **CURP Validation**.
- Flow and workflow failures now carry a machine-readable `moduleErrorCode`, and Incode API error
  codes and messages are surfaced across the flow and workflow lifecycle.
- A flow's `onFinish` result includes the end-screen texts configured in your dashboard.
- **eKYC** renders phone and email fields when `riskAddons` are configured.
- **Dynamic Forms** renders `YESNO` questions as a Yes/No dropdown.
- `<incode-workflow>` supports a self-loading mode.
- **Watchlist**, **Watchlist for Business**, and Incode Watchlist nodes now resolve in workflows.
- Transactional Risk Intelligence (TRI) telemetry.

### Changed

- **Forms use optimistic validation.** The Continue button starts enabled on each screen. Submitting
  with empty required fields reports every missing field at once and disables the button until they
  are corrected; typing clears the error for that field. Format errors (phone, email, CPF, CNPJ, SSN,
  postal code) report on blur. Applies to **eKYC**, **eKYB**, **Dynamic Forms**, **ID OCR**, the
  phone and email input screens, and the OTP code screens.
- **Form state shape changed with it.** If you read form state directly:
  - `errors` is replaced by `validationErrors`, whose entries are `{ key, params? }`.
  - `submitAttempted` is removed — the state machine now writes errors for all invalid fields on
    submit, so no separate flag is needed to gate display.
  - `isValid` and `canSubmit` now mean "no validation error is currently displayed" rather than "the
    form would pass validation". Existing `disabled={!isValid}` bindings keep working under the new
    optimistic meaning.
  - `computeEkycDisplayErrors` and `computeEkybDisplayErrors` are no longer exported; errors live
    entirely on `state.validationErrors`.
- **Authentication:** `USER_IS_NOT_RECOGNIZED` is retryable up to the configured capture-attempt
  limit (default 3) and then advances the flow, matching Web SDK 1.x, instead of ending the session on
  the first failure.
- When face authentication fails with an advanceable terminal error (`NONEXISTENT_CUSTOMER`,
  `HINT_NOT_PROVIDED`), the orchestrator advances so the backend can route the customer to
  enrollment, rather than terminating.
- A desktop-to-mobile handoff that finishes on mobile now completes the journey, instead of resuming
  the desktop session at the next module.
- **Government Validation** shows a loading spinner while a check is still in progress, replacing the
  success check mark that appeared prematurely.
- Manual capture is disabled when the Selfie or Authentication module runs with on-device face result
  submission enabled.
- Analytics screen names were realigned across modules and new typed module tokens added. If you key
  logic off screen names in tracked events, re-check your mappings against
  [Dashboard Events](/sdk-reference/web-sdk-2-events/).
- Consent and mandatory-consent copy is fetched in the active SDK language instead of always in
  English.
- Core JavaScript is minified, reducing bundle size. See [Bundle Optimization](/sdk-reference/web-sdk-2-bundle-optimization/).
- Default fonts are self-hosted with the package rather than fetched from a third-party CDN. See
  [Third-Party Dependencies](/sdk-reference/web-sdk-2-third-party-dependencies/).

### Fixed

- **ID Capture:** expired-ID retry handling restored to 1.x parity; the back-of-ID prompt is skipped
  when the backend accepts a single-sided document even with `alwaysCaptureBackOfId` set; Continue
  buttons are labelled correctly on the front-ID success screen when no back scan is needed; the
  desktop preview is mirrored so on-screen movement matches the user; `previewImageUrl` is restored
  in the capture-only flow so the post-capture screen advances; the manual-capture tooltip no longer
  shifts the layout.
- **Manual ID upload:** validation errors appear beneath the slot that failed instead of once at the
  bottom; uploaded slots survive switching between the ID and Passport tabs; images are normalized to
  JPEG before size validation; the quality-rejected error is no longer shown when the attempt was
  approved.
- **Digital ID upload:** an excluded country or unaccepted document shows the failure screen instead
  of silently continuing.
- **Face Match:** server-side face processing always runs before results are read; face match is
  skipped and the flow continues when the session was captured with `extractIdFace: false`; liveness
  snackbar labels are translated.
- **Selfie:** the on-device selfie assets load reliably when a warm-up is already in flight.
- **Custom Watchlist** calls the custom watchlist endpoint. The global **Watchlist** module is
  unchanged.
- **CURP Validation:** the retry / manual-verify option is restored after a failed validation, and
  the verifying text is hidden while idle.
- **Geolocation:** an unresolvable location renders localized copy instead of a literal `"Unknown"`,
  and the desktop permission-denied screen is localized.
- **Electronic Signature:** a session never associates more than one document; a signing error shows
  for three seconds and then finishes; error states route correctly by backend error type; a
  successful `signQes` response is treated as success; the signature canvas border renders on
  iOS 14.
- **Field Comparison** submits names in the shape the dashboard expects, so they appear on the
  session.
- **Document Capture** follows the camera-permission instructions before opening the camera, and PDFs
  render in an in-page viewer instead of a native embed that showed an OS-level "Open" button on iOS
  Safari and mobile Chromium.
- **Workflow and Flow:** `DYNAMIC_FORMS` is registered and the flow advances when face-auth attempts
  are exhausted; the finish-status call is no longer issued on the desktop when the handoff completed
  on mobile; the active workflow node is used when fetching finish status, so hosts receive the
  completion redirect.
- **Redirect to Mobile:** "Change phone number" works after an SMS resend hits the limit; a transient
  error no longer flashes on desktop right after the module loads.
- The finish-process screen shown while the session result resolves no longer renders a title-less
  spinner.
- Camera tracks are stopped explicitly at module transitions, and the rear camera is selected for
  back-camera capture on desktop and tablet devices.
- Language selection from the home-screen settings modal survives a page reload.
- A `TypeError` no longer appears in the console immediately after a flow completes.
- Standalone `@incodetech/web` imports for `redirect-to-mobile`, `cpf-ocr`, `document-capture`, and
  `field-comparison` resolve correctly. See [Individual Modules](/sdk-reference/web-sdk-2-individual-modules/).
- Street-level address selections are validated in **eKYC** and **eKYB** — choosing a city-level
  autocomplete result now reports that a street-level address is required.
- Accessibility (WCAG 2.2 AA) fixes across capture, forms, and shared components: error messages are
  programmatically associated with their fields; processing and transition screens announce once
  instead of exposing fragmented text; dropdowns announce as select-only comboboxes with their
  required and invalid state; buttons keep an accessible name while loading; modals move initial focus
  to the dialog heading; scroll containers are keyboard-operable; placeholder text meets contrast
  minimums; and the camera-permission "requesting" screen no longer announces behind the native OS
  prompt.

Install: `npm install @incodetech/web@2.1.0 @incodetech/core@2.1.0`

## 2.0.1 — 2026-05-18

### Fixed

- Republished the 2.0.0 artifacts with their build output. Version 2.0.0 shipped without it and is
  deprecated on npm — install `2.0.1` or newer.
- **Digital ID upload:** an excluded country or unaccepted document now shows the failure screen
  instead of silently continuing the flow; `captureAttempts` is honored exactly, rather than allowing
  one extra attempt; the terminal "no more attempts" screen is rendered and waits for the customer
  before returning to the document chooser; and the analyzing screen's status announcement is no
  longer visible on screen.

Install: `npm install @incodetech/web@2.0.1 @incodetech/core@2.0.1`

## 2.0.0 — 2026-05-15

Initial general availability of Web SDK 2.0 — a ground-up rewrite distributed as the
`@incodetech/core` and `@incodetech/web` npm packages, replacing the 1.x
`@incodetech/welcome` script bundle.

### Added

- Three integration paths from one package set: the `<incode-flow>` drop-in component, an
  orchestrator driving individual module web components, and headless managers for fully custom UI.
  See [Getting Started](/sdk-reference/web-sdk-2-getting-started/) and [Module Patterns](/sdk-reference/web-sdk-2-module-patterns/).
- Every consumer-facing module ships as a standard Web Component with its own CSS entry point, so it
  works in any framework. See [Web Components](/sdk-reference/web-sdk-2-web-components/) and
  [Framework Integration](/sdk-reference/web-sdk-2-framework-integration/).
- Design-token theming, asset overrides, and internationalization. See
  [Theming & Styling](/sdk-reference/web-sdk-2-theming/), [Asset Overrides](/sdk-reference/web-sdk-2-asset-overrides/), and
  [Internationalization](/sdk-reference/web-sdk-2-i18n/).
- Full TypeScript types across the public API, and per-module entry points for bundle splitting. See
  [TypeScript Types](/sdk-reference/web-sdk-2-typescript-types/) and [Bundle Optimization](/sdk-reference/web-sdk-2-bundle-optimization/).

<Callout icon="❗️" theme="error">
  ### Do not install 2.0.0. It was published without its build output and is deprecated on npm. Use

  `2.0.1` or newer.
</Callout>
