@soliton-id/web-sdk 1.0.0 → 1.0.1

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.

Potentially problematic release.


This version of @soliton-id/web-sdk might be problematic. Click here for more details.

Files changed (3) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +107 -39
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,21 @@ All notable changes to `@soliton-id/web-sdk`. The `soliton-v1` postMessage
4
4
  protocol is frozen: changes are additive only, so older SDK versions keep
5
5
  working against the hosted flow.
6
6
 
7
+ ## 1.0.1 — 2026-08-02
8
+
9
+ Documentation only. No runtime, API, or bundle changes; `soliton-v1` is
10
+ unchanged and `1.0.0` remains fully compatible. Published because npm's
11
+ `1.0.0` README is immutable and described test keys incorrectly.
12
+
13
+ - Rewrote the test-key section: `sk_test_` credentials now produce
14
+ deterministic synthetic fixtures (`pass` / `fail` / `partial`) that never
15
+ open the camera, rather than running the same real capture pipeline as
16
+ `sk_live_`. Documented the scenario/verdict mapping and the strict
17
+ live/test read isolation.
18
+ - Documented completion webhooks as a polling alternative, and corrected the
19
+ iframe-origin, CSP, and `Permissions-Policy` guidance to describe the
20
+ iframe's direct-parent origin and nested frame chains.
21
+
7
22
  ## 1.0.0 — 2026-08-01
8
23
 
9
24
  First public release.
package/README.md CHANGED
@@ -120,29 +120,51 @@ creation and check it on every status read to make this auditable.
120
120
 
121
121
  Embedding is off by default and gated on BOTH layers:
122
122
 
123
- 1. Your API key must have the exact origins of the pages that will embed the
124
- flow registered (scheme + host + port, e.g. `https://app.example.com`).
125
- Ask us to register yours.
126
- 2. The same origins must be present in the soliton.id deploy-time frame
127
- ancestors allowlist (we handle this when we register your key).
128
-
129
- A verification link opened inside an iframe on any other origin refuses to
130
- start and reports `origin_not_allowed`.
123
+ 1. Your Soliton account must have the exact origin of each page that runs the
124
+ SDK and directly contains its Soliton iframe registered (scheme + host +
125
+ port, e.g. `https://app.example.com`). This direct-parent page does not
126
+ have to be the browser's top-level page.
127
+ 2. The direct-parent origin must also be present in the soliton.id deploy-time
128
+ `frame-ancestors` allowlist. If the SDK page is itself framed, every origin
129
+ above it in the frame chain must be present there too (we manage this
130
+ allowlist).
131
+
132
+ A verification link opened inside an iframe with any other direct-parent
133
+ origin refuses to start and reports `origin_not_allowed`.
131
134
 
132
135
  During the invite-only pilot, Soliton manually manages both layers. Send your
133
- Soliton contact every exact production, staging, and local origin before
134
- testing. Wildcards are not accepted, and adding or changing an origin can
136
+ Soliton contact every exact production and local direct-parent origin before
137
+ testing. Include a staging origin only when Soliton has supplied a working
138
+ staging flow URL. For a nested integration, also send every other ancestor
139
+ origin. Wildcards are not accepted, and adding or changing an origin can
135
140
  require a Soliton deployment.
136
141
 
142
+ Register the direct-parent page's origin, not a URL path. For example,
143
+ `https://app.example.com` and `https://app.example.com:8443` are different
144
+ origins; `/verify`, a query string, and a trailing slash are not part of the
145
+ value you send us. Redirect-domain registration and iframe-origin registration
146
+ are separate: enabling one does not enable the other.
147
+
137
148
  ## Customer security headers
138
149
 
139
- If your embedding page sends restrictive response headers, merge these
140
- sources into its existing policies (do not replace the rest of your policy
141
- with this example):
150
+ Content Security Policy (CSP) is the browser response header that controls
151
+ which sources a page may load. If the page that runs the SDK sends restrictive
152
+ security headers, merge the Soliton sources into its existing policies; do not
153
+ replace the rest of your policy with these minimal examples.
154
+
155
+ When you bundle the npm package:
156
+
157
+ ```text
158
+ Content-Security-Policy: frame-src https://soliton.id
159
+ Permissions-Policy: camera=(self "https://soliton.id"), microphone=(self "https://soliton.id")
160
+ ```
161
+
162
+ When you load the classic CDN script or hosted ESM build, the remote script
163
+ also needs to be allowed:
142
164
 
143
165
  ```text
144
- Content-Security-Policy: frame-src https://soliton.id https://staging.soliton.id; script-src https://soliton.id https://staging.soliton.id
145
- Permissions-Policy: camera=(self "https://soliton.id" "https://staging.soliton.id"), microphone=(self "https://soliton.id" "https://staging.soliton.id")
166
+ Content-Security-Policy: frame-src https://soliton.id; script-src https://soliton.id
167
+ Permissions-Policy: camera=(self "https://soliton.id"), microphone=(self "https://soliton.id")
146
168
  ```
147
169
 
148
170
  - `frame-src` must include the Soliton origin you use because the capture flow
@@ -150,31 +172,77 @@ Permissions-Policy: camera=(self "https://soliton.id" "https://staging.soliton.i
150
172
  - `script-src` must include the Soliton origin you use only for the classic
151
173
  script or hosted ESM distribution. It is not needed when your application
152
174
  bundles the npm package.
153
- - If your top-level `Permissions-Policy` explicitly restricts camera or
154
- microphone, delegate both features to the production and/or staging Soliton
155
- origin you use. The SDK already sets the matching
156
- `allow="camera; microphone"` attribute on its iframe.
157
-
158
- For local development, add the exact localhost origin (including its port) to
159
- the corresponding directives as well.
160
-
161
- ## Pilot test keys
175
+ - If any document above the Soliton iframe explicitly restricts camera or
176
+ microphone with `Permissions-Policy`, every level in a nested frame chain
177
+ must allow and delegate both features through each intervening iframe; an
178
+ upstream denial cannot be overridden lower in the chain. The SDK already
179
+ sets the matching `allow="camera; microphone"` attribute on the iframe it
180
+ creates.
181
+
182
+ These examples use production. Add a staging origin to these directives only
183
+ when Soliton has supplied its exact, working staging URL; include both origins
184
+ only if the same page can open both environments.
185
+
186
+ For local customer-page testing, send us the exact origin, including its port
187
+ (for example `http://localhost:3000`), for registration. It does not belong in
188
+ `frame-src` or `script-src` while the iframe and hosted SDK still load from
189
+ soliton.id. Do not add Soliton to your page's `frame-ancestors`: that directive
190
+ controls who may frame your page, while `frame-src` controls what your page may
191
+ frame.
192
+
193
+ ## Test mode
194
+
195
+ `sk_test_` credentials produce deterministic synthetic fixtures, so you can
196
+ build and regression-test the embed without capturing a person. Your server
197
+ names the outcome when it creates the verification:
198
+
199
+ ```jsonc
200
+ // POST /api/v1/verifications with an sk_test_ key
201
+ { "client_reference_id": "user-8412", "test_fixture_scenario": "partial" }
202
+ ```
162
203
 
163
- `sk_test_` identifies a pilot credential; it is not an isolated or simulated
164
- sandbox. Test keys use the same hosted capture, biometric processing, and data
165
- handling as live keys. The prefix does not create synthetic results or trigger
166
- automatic deletion. Use only informed, consenting pilot participants, give
167
- them your applicable privacy notice, and follow your Soliton pilot terms.
204
+ | `test_fixture_scenario` | `verified` | `partial_verification` |
205
+ | ----------------------- | ---------- | ---------------------- |
206
+ | `pass` | `true` | `false` |
207
+ | `partial` | `true` | `true` |
208
+ | `fail` | `false` | `false` |
209
+
210
+ The resulting URL opens in the overlay exactly like a real one and fires
211
+ `onComplete` the same way, but never requests camera permission and never
212
+ records anything. The hosted page marks itself as synthetic on screen. This is
213
+ the practical way to exercise your `partial` branch, which is awkward to
214
+ trigger with a real capture.
215
+
216
+ Test mode does not exercise liveness, anti-spoof, or anti-deepfake logic, and
217
+ simulates no errors or timeouts — only the three terminal verdicts. Verify the
218
+ production path with an `sk_live_` key.
219
+
220
+ The two modes are strictly isolated: a live key cannot create or read a
221
+ fixture, and a test key cannot read a real verification, even within one
222
+ account. Every status read and webhook carries `result_source`
223
+ (`biometric` or `synthetic_test_fixture`) — assert it is `biometric` anywhere
224
+ a real verdict matters.
225
+
226
+ ## Completion webhooks
227
+
228
+ Instead of polling, your server can receive a signed `verification.completed`
229
+ POST the moment a verification reaches its final verdict. Like `onComplete`, it
230
+ is a "check now" signal rather than the verdict itself — fetch the verification
231
+ server-to-server before acting on it. Verify the `X-Soliton-Signature` HMAC,
232
+ deduplicate on `X-Soliton-Event-Id`, and respond `2xx` within 5 seconds. Full
233
+ setup, the signature recipe, and retry semantics are in the
234
+ [integration guide](https://soliton.id/docs/integration).
168
235
 
169
236
  ## How it works
170
237
 
171
- `open()` accepts hosted URLs only from `https://soliton.id` or
172
- `https://staging.soliton.id` (plus HTTP localhost/127.0.0.1 development URLs),
173
- requires a `/v/{token}` path, and preserves query parameters. It renders a
174
- full-viewport overlay with an iframe pointing at that validated origin and
175
- listens for the hosted page's lifecycle messages. Every message is checked
176
- three ways (origin, source window, protocol marker) before it reaches your
177
- callbacks, and unknown message types are ignored, so wrapper versions stay
178
- compatible as the hosted flow evolves. Redirect-style integration (no SDK,
179
- we redirect the user back to you) remains fully supported; the same
180
- verification URL works in both modes.
238
+ `open()` accepts hosted URLs from `https://soliton.id`. When Soliton has
239
+ supplied a working staging flow URL, it also accepts
240
+ `https://staging.soliton.id`; HTTP localhost/127.0.0.1 URLs are accepted for
241
+ development. Every URL must use a `/v/{token}` path; query parameters are
242
+ preserved. The SDK renders a full-viewport overlay with an iframe pointing at
243
+ that validated origin and listens for the hosted page's lifecycle messages.
244
+ Every message is checked three ways (origin, source window, protocol marker)
245
+ before it reaches your callbacks, and unknown message types are ignored, so
246
+ wrapper versions stay compatible as the hosted flow evolves. Redirect-style
247
+ integration (no SDK, we redirect the user back to you) remains fully
248
+ supported; the same verification URL works in both modes.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "//": "Publishable manifest for the npm Web SDK. No devDependencies and no own node_modules by design: every build runs from the next-app root with its existing toolchain (npm run build:sdk), so the lockfile never grows for packaging. dist/ is rebuilt automatically by the prepack hook and is not committed.",
3
3
  "name": "@soliton-id/web-sdk",
4
- "version": "1.0.0",
4
+ "version": "1.0.1",
5
5
  "description": "Soliton identity verification for the browser: opens the hosted verification flow in a full-viewport overlay iframe on your page and reports lifecycle events. Verdicts and portraits are fetched by your backend, never exposed in the browser.",
6
6
  "license": "MIT",
7
7
  "author": "Soliton",