@sekyro/node 0.1.0-rc.4 → 0.1.0-rc.5
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/CHANGELOG.md +16 -0
- package/README.md +112 -27
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +382 -146
- package/dist/index.d.ts +382 -146
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/sbom.cdx.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -101,6 +101,12 @@ type SekyroEnvironment = "sandbox" | "live";
|
|
|
101
101
|
interface SessionStep {
|
|
102
102
|
checkType: CheckType;
|
|
103
103
|
state: CheckState;
|
|
104
|
+
/** Sekyro flows: the flow node this check belongs to (e.g. `n_live`). */
|
|
105
|
+
nodeId?: string;
|
|
106
|
+
/** Sekyro flows: the service of that node. */
|
|
107
|
+
service?: ServiceId;
|
|
108
|
+
/** Sekyro flows: the check failed and the flow's fallback took over. */
|
|
109
|
+
handled?: true;
|
|
104
110
|
/** Machine-readable failure/review reason, when the check has one. */
|
|
105
111
|
reason?: string;
|
|
106
112
|
/** Calibrated model score in [0, 1] for scored checks (liveness, face match). */
|
|
@@ -200,7 +206,8 @@ interface SessionSubjectInput {
|
|
|
200
206
|
* again with liveness + face match only, against the reference photo stored
|
|
201
207
|
* on the subject. Name exactly one target. Errors at create:
|
|
202
208
|
* `404 subject_not_found`, `409 subject_revoked`, `409 subject_no_reference`,
|
|
203
|
-
* `409 subject_stale` (older than the
|
|
209
|
+
* `409 subject_stale` (older than the flow's `returning.maxAgeMonths`),
|
|
210
|
+
* `409 reuse_disabled` (the flow turns returning-user sessions off) and
|
|
204
211
|
* `400` / `409 reuse_target_ambiguous`.
|
|
205
212
|
*/
|
|
206
213
|
reuse?: SubjectReuseTarget;
|
|
@@ -226,42 +233,52 @@ type SubjectReuseTarget = {
|
|
|
226
233
|
/** A document type the backend reads (kyc-docs-v2 vocabulary; `carte_identite` = identity card of any issuer). @public */
|
|
227
234
|
type ProfileDocumentType = "carte_identite" | "passport" | "residence_permit";
|
|
228
235
|
/**
|
|
229
|
-
* The
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
* Used through {@link EkycProfileOverride}.
|
|
236
|
+
* The services a Sekyro flow is built from. A session's steps
|
|
237
|
+
* ({@link SessionStep.service}) and {@link FlowOverrides.services} use these
|
|
238
|
+
* ids; one service may run several checks (e.g. `liveness` with an ICAO
|
|
239
|
+
* portrait).
|
|
234
240
|
* @public
|
|
235
241
|
*/
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
*/
|
|
251
|
-
channels?: Array<"whatsapp" | "sms">;
|
|
252
|
-
/**
|
|
253
|
-
* Which countries codes may be sent to: the profile's allowed
|
|
254
|
-
* `locations` (default), `any`, or a list of ISO 3166-1 alpha-2 codes.
|
|
255
|
-
* Invalid values answer `400 phone_destinations_invalid`.
|
|
256
|
-
*/
|
|
257
|
-
destinations?: "locations" | "any" | {
|
|
258
|
-
countries: string[];
|
|
242
|
+
type ServiceId = "device_network" | "phone_otp" | "email_otp" | "national_eid" | "document" | "nfc" | "population_registry" | "supplied_identity" | "summary_confirm" | "liveness" | "face_match" | "aml_screening" | "face_dedup";
|
|
243
|
+
/**
|
|
244
|
+
* The general settings of a flow that a session may override (the flow's
|
|
245
|
+
* `link`, `language` and override policy are not overridable). Country codes
|
|
246
|
+
* are ISO 3166-1 alpha-2 (`MR`). Used through {@link FlowOverrides.settings}.
|
|
247
|
+
* @public
|
|
248
|
+
*/
|
|
249
|
+
interface FlowOverridableSettings {
|
|
250
|
+
/** Who may be verified. */
|
|
251
|
+
eligibility: {
|
|
252
|
+
/** Accepted nationalities: `'*'` or a list, optionally per IP location. */
|
|
253
|
+
nationalities: {
|
|
254
|
+
default: "*" | string[];
|
|
255
|
+
byLocation?: Record<string, "*" | string[]>;
|
|
259
256
|
};
|
|
257
|
+
/** Minimum age in years (1–120), or `null` for none. */
|
|
258
|
+
minAge: number | null;
|
|
260
259
|
};
|
|
261
|
-
/**
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
260
|
+
/** Automatic decisions instead of human review (`retryConfidentRejects` lets confident rejects retry). */
|
|
261
|
+
decisions?: {
|
|
262
|
+
mode: "automatic" | "review";
|
|
263
|
+
retryConfidentRejects: boolean;
|
|
264
|
+
};
|
|
265
|
+
/** Data consistency across sources. */
|
|
266
|
+
fraud: {
|
|
267
|
+
/** Comparison of your `subject` data with the reference identity. */
|
|
268
|
+
nameMatch?: {
|
|
269
|
+
level: "strict" | "standard" | "lenient";
|
|
270
|
+
onMismatch: "fail" | "signal";
|
|
271
|
+
};
|
|
272
|
+
};
|
|
273
|
+
/** Returning-user sessions (`subject.reuse`). */
|
|
274
|
+
returning: {
|
|
275
|
+
/** `false`: returning-user sessions are refused (`409 reuse_disabled`). */
|
|
276
|
+
enabled: boolean;
|
|
277
|
+
/** Maximum age in months (1–120) of the subject's last verification; `null` = no limit. */
|
|
278
|
+
maxAgeMonths: number | null;
|
|
279
|
+
};
|
|
280
|
+
/** Identity-document rules. */
|
|
281
|
+
documents: {
|
|
265
282
|
/** Accepted document types: `'*'` (all) or a list, optionally per issuing country. */
|
|
266
283
|
accepted: {
|
|
267
284
|
default: "*" | ProfileDocumentType[];
|
|
@@ -273,98 +290,123 @@ interface EkycProfileSettings {
|
|
|
273
290
|
};
|
|
274
291
|
authenticity: "standard" | "off";
|
|
275
292
|
};
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Document substitution: the portrait a `document` or `nfc` step produces is
|
|
296
|
+
* compared with the registry portrait (or the chip with the printed photo).
|
|
297
|
+
* `signal` records a risk signal on a clear mismatch, `review` also sends the
|
|
298
|
+
* session to review, `off` compares nothing. `failBelow` is the mismatch bound
|
|
299
|
+
* in (0, 1), absent = the platform bound.
|
|
300
|
+
* @public
|
|
301
|
+
*/
|
|
302
|
+
interface DocumentSubstitutionSettings {
|
|
303
|
+
mode: "off" | "signal" | "review";
|
|
304
|
+
failBelow?: number;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* The per-service settings a session may override, by {@link ServiceId}.
|
|
308
|
+
* `attempts` limits are per step (absent = the platform default).
|
|
309
|
+
* @public
|
|
310
|
+
*/
|
|
311
|
+
interface FlowServiceSettings {
|
|
312
|
+
/** Device & Network Intelligence: IP location, anonymizers, cooldown, device and capture postures. */
|
|
313
|
+
device_network: {
|
|
314
|
+
/** Where the end user may be (IP location). */
|
|
315
|
+
locations: {
|
|
316
|
+
mode: "all";
|
|
317
|
+
} | {
|
|
318
|
+
mode: "only" | "all_except";
|
|
319
|
+
countries: string[];
|
|
320
|
+
};
|
|
321
|
+
/** VPN / proxy / Tor. */
|
|
322
|
+
anonymizers: "allow" | "block";
|
|
323
|
+
/** Device cooldown after repeated rejections (at most 5 tiers; `[]` = off). */
|
|
324
|
+
cooldown?: {
|
|
325
|
+
tiers: Array<{
|
|
326
|
+
rejectedSessions: number;
|
|
327
|
+
windowHours: number;
|
|
328
|
+
waitMinutes: number;
|
|
329
|
+
}>;
|
|
330
|
+
};
|
|
331
|
+
/** Device tamper and velocity actions. */
|
|
332
|
+
device?: {
|
|
333
|
+
tamper: "block" | "signal";
|
|
334
|
+
velocity: {
|
|
335
|
+
maxIdentitiesPerDevice: number;
|
|
336
|
+
windowDays: number;
|
|
337
|
+
action: "signal" | "block";
|
|
338
|
+
};
|
|
339
|
+
};
|
|
340
|
+
attestation?: "off" | "signal" | "enforce";
|
|
341
|
+
captureIntegrity?: "off" | "signal" | "enforce";
|
|
283
342
|
};
|
|
284
|
-
|
|
285
|
-
|
|
343
|
+
phone_otp: {
|
|
344
|
+
/** Where the number comes from: your `subject.phone` / `input.phone`, the person, or either. */
|
|
345
|
+
numberSource: "prefilled" | "user_entered" | "prefilled_or_entered";
|
|
346
|
+
/** Narrow the channels the person may choose from (absent = every channel the org has on). */
|
|
347
|
+
channels?: Array<"whatsapp" | "sms">;
|
|
348
|
+
/** Which countries codes may be sent to (absent = the flow's allowed `locations`). */
|
|
349
|
+
destinations?: "locations" | "any" | {
|
|
350
|
+
countries: string[];
|
|
351
|
+
};
|
|
352
|
+
attempts?: number;
|
|
286
353
|
};
|
|
287
|
-
|
|
288
|
-
|
|
354
|
+
email_otp: {
|
|
355
|
+
/** Where the address comes from: your `input.email`, the person, or either. */
|
|
356
|
+
emailSource: "prefilled" | "user_entered" | "prefilled_or_entered";
|
|
357
|
+
/** Disposable (temporary) addresses: allowed, flagged as a risk signal (default), or refused. */
|
|
358
|
+
disposable?: "allow" | "signal" | "block";
|
|
359
|
+
attempts?: number;
|
|
289
360
|
};
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
361
|
+
national_eid: {
|
|
362
|
+
/**
|
|
363
|
+
* `'org'` (every national eID the org can use, resolved at session create)
|
|
364
|
+
* or provider ids (`{country}.{provider}`, e.g. `MR.houwiyeti`).
|
|
365
|
+
*/
|
|
366
|
+
providers: "org" | string[];
|
|
367
|
+
/** The eID portrait is the face-match reference. */
|
|
368
|
+
portraitReference: boolean;
|
|
294
369
|
};
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
email?: number;
|
|
300
|
-
document: number;
|
|
301
|
-
registry: number;
|
|
302
|
-
liveness: number;
|
|
303
|
-
faceMatch: number;
|
|
370
|
+
document: {
|
|
371
|
+
attempts?: number;
|
|
372
|
+
/** Compare the document photo with the registry photo (absent = the platform default). */
|
|
373
|
+
documentSubstitution?: DocumentSubstitutionSettings;
|
|
304
374
|
};
|
|
305
|
-
/**
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
countries: string[];
|
|
375
|
+
/** The chip read (its MRZ source is derived from the flow and is not overridable). */
|
|
376
|
+
nfc: {
|
|
377
|
+
maxAttempts?: number;
|
|
378
|
+
/** Compare the chip photo with the registry photo (absent = the platform default). */
|
|
379
|
+
documentSubstitution?: DocumentSubstitutionSettings;
|
|
311
380
|
};
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
381
|
+
population_registry: {
|
|
382
|
+
/** `'org'` (every registry the org can use, resolved at session create) or registry ids. */
|
|
383
|
+
sources: "org" | Array<"MR.anrpts">;
|
|
384
|
+
nniSource: "auto" | "typed" | "bound_only";
|
|
385
|
+
onUncovered: "skip";
|
|
386
|
+
attempts?: number;
|
|
317
387
|
};
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
mode: "automatic" | "review";
|
|
323
|
-
retryConfidentRejects: boolean;
|
|
388
|
+
supplied_identity: Record<string, never>;
|
|
389
|
+
summary_confirm: {
|
|
390
|
+
/** Offer « Reprendre » (re-open the identity source). */
|
|
391
|
+
retake: boolean;
|
|
324
392
|
};
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
windowHours: number;
|
|
330
|
-
waitMinutes: number;
|
|
331
|
-
}>;
|
|
393
|
+
liveness: {
|
|
394
|
+
/** `off`, selfie ICAO `alert` / `reject`, or `id_document` (ID-photo portrait, always rejects). */
|
|
395
|
+
icao: "off" | "alert" | "reject" | "id_document";
|
|
396
|
+
attempts?: number;
|
|
332
397
|
};
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
velocity: {
|
|
337
|
-
maxIdentitiesPerDevice: number;
|
|
338
|
-
windowDays: number;
|
|
339
|
-
action: "signal" | "block";
|
|
340
|
-
};
|
|
398
|
+
face_match: {
|
|
399
|
+
reference: "auto" | "document" | "registry";
|
|
400
|
+
attempts?: number;
|
|
341
401
|
};
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
* `400 portrait_icao_policy_id_document`. Absent = a verification selfie, no ICAO check.
|
|
350
|
-
*/
|
|
351
|
-
portrait?: {
|
|
352
|
-
purpose?: "verification" | "id_document";
|
|
353
|
-
icao?: {
|
|
354
|
-
policy: "alert" | "reject";
|
|
355
|
-
};
|
|
402
|
+
aml_screening: {
|
|
403
|
+
lists: Array<"sanctions" | "pep" | "adverse_media">;
|
|
404
|
+
onHit: "review" | "fail";
|
|
405
|
+
};
|
|
406
|
+
face_dedup: {
|
|
407
|
+
scope: "app" | "org";
|
|
408
|
+
onDuplicate: "review" | "fail";
|
|
356
409
|
};
|
|
357
|
-
}
|
|
358
|
-
/**
|
|
359
|
-
* The email OTP step of a profile. When the email check is not available on
|
|
360
|
-
* the platform yet, saving it answers `400 email_otp_not_available`.
|
|
361
|
-
* @public
|
|
362
|
-
*/
|
|
363
|
-
interface ProfileEmail {
|
|
364
|
-
/** Where the address comes from: your `input.email`, the person, or either. */
|
|
365
|
-
emailSource: "prefilled" | "user_entered" | "prefilled_or_entered";
|
|
366
|
-
/** Disposable (temporary) addresses: allowed, flagged as a risk signal (default), or refused. */
|
|
367
|
-
disposable?: "allow" | "signal" | "block";
|
|
368
410
|
}
|
|
369
411
|
/**
|
|
370
412
|
* `T` with every property optional, recursively. Arrays are replaced as a
|
|
@@ -375,37 +417,86 @@ type DeepPartial<T> = T extends readonly unknown[] ? T : T extends object ? {
|
|
|
375
417
|
[K in keyof T]?: DeepPartial<T[K]>;
|
|
376
418
|
} : T;
|
|
377
419
|
/**
|
|
378
|
-
* A per-session override of the
|
|
379
|
-
* ({@link CreateSessionInput.profile}): any subset of
|
|
380
|
-
* {@link EkycProfileSettings}, at any depth (every field optional). Objects
|
|
381
|
-
* are merged into the app's profile; arrays and scalar values replace it.
|
|
420
|
+
* A per-session override of the flow ({@link CreateSessionInput.overrides}).
|
|
382
421
|
*
|
|
383
|
-
*
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
*
|
|
387
|
-
*
|
|
388
|
-
*
|
|
422
|
+
* - `settings`: any subset of {@link FlowOverridableSettings}, at any depth.
|
|
423
|
+
* - `services`: keyed by service (applied to every node of that service): any
|
|
424
|
+
* subset of its {@link FlowServiceSettings}, or `'off'` to remove it from
|
|
425
|
+
* the flow. A service the flow does not use is ignored.
|
|
426
|
+
*
|
|
427
|
+
* Objects merge into the flow; arrays and scalar values replace. Unknown keys
|
|
428
|
+
* and invalid results answer `400 override_invalid`. An override may only
|
|
429
|
+
* make the flow stricter unless the flow allows widening; turning a service
|
|
430
|
+
* `'off'` always widens. A widening change answers `403 override_widens_flow`.
|
|
431
|
+
* The changed paths are reported on {@link Session.overriddenFields}.
|
|
432
|
+
*
|
|
433
|
+
* @example
|
|
434
|
+
* ```ts
|
|
435
|
+
* await sekyro.sessions.create({
|
|
436
|
+
* flow: "foreigners",
|
|
437
|
+
* overrides: {
|
|
438
|
+
* settings: { eligibility: { minAge: 21 } },
|
|
439
|
+
* services: { liveness: { attempts: 2 } },
|
|
440
|
+
* },
|
|
441
|
+
* });
|
|
442
|
+
* ```
|
|
443
|
+
* @public
|
|
444
|
+
*/
|
|
445
|
+
interface FlowOverrides {
|
|
446
|
+
settings?: DeepPartial<FlowOverridableSettings>;
|
|
447
|
+
services?: {
|
|
448
|
+
[S in ServiceId]?: DeepPartial<FlowServiceSettings[S]> | "off";
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* The flow version a session runs: its `flw_` id, its slug and the published
|
|
453
|
+
* version pinned at create.
|
|
389
454
|
* @public
|
|
390
455
|
*/
|
|
391
|
-
|
|
456
|
+
interface SessionFlowRef {
|
|
457
|
+
id: string;
|
|
458
|
+
slug: string;
|
|
459
|
+
version: number;
|
|
460
|
+
}
|
|
392
461
|
/**
|
|
393
|
-
*
|
|
394
|
-
*
|
|
462
|
+
* One flow of your app, from {@link Sekyro.listFlows}. Published flows only;
|
|
463
|
+
* pass `slug` or `id` as {@link CreateSessionInput.flow}.
|
|
464
|
+
* @public
|
|
465
|
+
*/
|
|
466
|
+
interface FlowSummary {
|
|
467
|
+
/** `flw_` id. */
|
|
468
|
+
id: string;
|
|
469
|
+
slug: string;
|
|
470
|
+
name: string;
|
|
471
|
+
/** The published version a new session runs. */
|
|
472
|
+
version: number;
|
|
473
|
+
/** The flow a session runs when you send no `flow`. */
|
|
474
|
+
isDefault: boolean;
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Input of {@link SessionsApi.create}. The API key belongs to an app; the
|
|
478
|
+
* app's flow (its default flow, or the one named in `flow`) decides the steps.
|
|
395
479
|
* @public
|
|
396
480
|
*/
|
|
397
481
|
interface CreateSessionInput {
|
|
482
|
+
/**
|
|
483
|
+
* The app's flow to run: its slug (e.g. `foreigners`) or `flw_` id, as
|
|
484
|
+
* {@link Sekyro.listFlows} lists them. Absent = the app's default flow.
|
|
485
|
+
* Errors: `404 flow_not_found` (no such flow in the key's app),
|
|
486
|
+
* `409 flow_not_published`, `409 flow_archived`.
|
|
487
|
+
*/
|
|
488
|
+
flow?: string;
|
|
398
489
|
/** Pins the hosted-flow language. Omit to let the person's device decide. */
|
|
399
490
|
locale?: Locale;
|
|
400
491
|
/**
|
|
401
|
-
* Pre-choose the identity method when the
|
|
402
|
-
* (the hosted
|
|
492
|
+
* Pre-choose the identity method when the flow offers a choice of identity
|
|
493
|
+
* method (the hosted choice screen is then skipped). Ignored otherwise.
|
|
403
494
|
*/
|
|
404
495
|
identityMethod?: IdentityMethod;
|
|
405
496
|
/**
|
|
406
|
-
* Session lifetime in minutes. Must fall within the
|
|
407
|
-
*
|
|
408
|
-
*
|
|
497
|
+
* Session lifetime in minutes. Must fall within the flow's link range,
|
|
498
|
+
* otherwise the API answers `400 ttl_out_of_policy`. Omit to use the
|
|
499
|
+
* flow's default.
|
|
409
500
|
*/
|
|
410
501
|
ttlMinutes?: number;
|
|
411
502
|
/** Also send the hosted link to the person by SMS or WhatsApp. */
|
|
@@ -417,12 +508,13 @@ interface CreateSessionInput {
|
|
|
417
508
|
*/
|
|
418
509
|
subject?: SessionSubjectInput;
|
|
419
510
|
/**
|
|
420
|
-
* Override the
|
|
421
|
-
*
|
|
422
|
-
*
|
|
423
|
-
* `403
|
|
511
|
+
* Override the flow for this session only ({@link FlowOverrides}): its
|
|
512
|
+
* general settings and per-service settings, or turn a service `'off'`.
|
|
513
|
+
* `400 override_invalid` for an unknown key or an invalid result;
|
|
514
|
+
* `403 override_widens_flow` for a change that makes the flow less strict
|
|
515
|
+
* when the flow does not allow widening.
|
|
424
516
|
*/
|
|
425
|
-
|
|
517
|
+
overrides?: FlowOverrides;
|
|
426
518
|
/**
|
|
427
519
|
* Step inputs consumed server-side. The known anchors are typed (all
|
|
428
520
|
* strings — an `nni` is a 10-digit string, never a number); further keys
|
|
@@ -507,6 +599,9 @@ interface CreatedSession {
|
|
|
507
599
|
clientToken: string;
|
|
508
600
|
/** Hosted verification link for this session. */
|
|
509
601
|
hostedUrl: string;
|
|
602
|
+
/** The flow version the session runs (the default flow when you sent no `flow`). */
|
|
603
|
+
flow?: SessionFlowRef;
|
|
604
|
+
/** The checks on the session's path (checks of a lane not taken are omitted). */
|
|
510
605
|
steps: SessionStep[];
|
|
511
606
|
/** ISO 8601 — when the session (and its link) stop accepting input. */
|
|
512
607
|
expiresAt: string;
|
|
@@ -612,8 +707,11 @@ interface VerifiedContacts {
|
|
|
612
707
|
*/
|
|
613
708
|
interface Session {
|
|
614
709
|
id: string;
|
|
710
|
+
/** Sekyro flows: the flow version the session runs (absent on sessions created before flows). */
|
|
711
|
+
flow?: SessionFlowRef;
|
|
615
712
|
status: SessionStatus;
|
|
616
713
|
outcome: SessionOutcome | null;
|
|
714
|
+
/** The checks on the session's path (checks of a lane the person did not take are omitted). */
|
|
617
715
|
steps: SessionStep[];
|
|
618
716
|
/** ISO 8601. */
|
|
619
717
|
expiresAt: string;
|
|
@@ -643,7 +741,10 @@ interface Session {
|
|
|
643
741
|
* `failureReason: 'device_cooldown'`.
|
|
644
742
|
*/
|
|
645
743
|
retryAfter?: string;
|
|
646
|
-
/**
|
|
744
|
+
/**
|
|
745
|
+
* Dotted paths this session's {@link CreateSessionInput.overrides} changed
|
|
746
|
+
* (e.g. `settings.decisions.mode`, `services.liveness`).
|
|
747
|
+
*/
|
|
647
748
|
overriddenFields?: string[];
|
|
648
749
|
/**
|
|
649
750
|
* Risk signals recorded on the session (e.g. `device_velocity`,
|
|
@@ -675,14 +776,17 @@ interface Session {
|
|
|
675
776
|
* `session.expired` | `session.rejected`) — ids and enums only, no civil data,
|
|
676
777
|
* scores or links. `outcome` and `steps` travel on `completed` / `failed`;
|
|
677
778
|
* `review_pending` carries `steps` without an outcome; `expired` carries the
|
|
678
|
-
* status
|
|
779
|
+
* status and the session's refs (`flow`, subject ids, `overriddenFields`).
|
|
679
780
|
* @public
|
|
680
781
|
*/
|
|
681
782
|
interface SessionLifecycleEventData {
|
|
682
783
|
sessionId: string;
|
|
683
784
|
status: SessionStatus;
|
|
684
785
|
outcome?: SessionOutcome | null;
|
|
685
|
-
|
|
786
|
+
/** The checks on the session's path (checks of a lane the person did not take are omitted). */
|
|
787
|
+
steps?: Array<Pick<SessionStep, "checkType" | "state" | "nodeId" | "service">>;
|
|
788
|
+
/** Sekyro flows: the flow version the session runs (absent on sessions created before flows). */
|
|
789
|
+
flow?: SessionFlowRef;
|
|
686
790
|
/** Machine-readable reason, when the transition has one. */
|
|
687
791
|
reason?: string;
|
|
688
792
|
/** End-user network context (no IP); on `completed` / `failed` when recorded. */
|
|
@@ -713,7 +817,7 @@ interface SessionLifecycleEventData {
|
|
|
713
817
|
* from which the device may start a new verification.
|
|
714
818
|
*/
|
|
715
819
|
retryAfter?: string;
|
|
716
|
-
/** Dotted
|
|
820
|
+
/** Dotted paths the session's create-time {@link CreateSessionInput.overrides} changed. */
|
|
717
821
|
overriddenFields?: string[];
|
|
718
822
|
/** On `completed` / `failed`: the contacts verified in this session (passed OTP checks only). */
|
|
719
823
|
verifiedContacts?: VerifiedContacts;
|
|
@@ -818,8 +922,8 @@ interface Subject {
|
|
|
818
922
|
/**
|
|
819
923
|
* A returning-user session can be created now: active, a reference photo is
|
|
820
924
|
* stored, and the last FULL verification (returning-user sessions do not
|
|
821
|
-
* reset it) is within your app's
|
|
822
|
-
* `
|
|
925
|
+
* reset it) is within the returning-user limit of your app's default flow
|
|
926
|
+
* (`settings.returning`: turned on, and `maxAgeMonths` when set).
|
|
823
927
|
*/
|
|
824
928
|
returningReady: boolean;
|
|
825
929
|
/** The verified name / birth date of the latest approved session. */
|
|
@@ -857,6 +961,12 @@ interface SessionStepCompletedEventData {
|
|
|
857
961
|
sessionId: string;
|
|
858
962
|
checkType: CheckType;
|
|
859
963
|
state: CheckState;
|
|
964
|
+
/** Sekyro flows: the flow node of the passed check. */
|
|
965
|
+
nodeId?: string;
|
|
966
|
+
/** Sekyro flows: the service of that node. */
|
|
967
|
+
service?: ServiceId;
|
|
968
|
+
/** Sekyro flows: the flow version the session runs (absent on sessions created before flows). */
|
|
969
|
+
flow?: SessionFlowRef;
|
|
860
970
|
/** The subject (person) the session is linked to, when known. */
|
|
861
971
|
subjectId?: string;
|
|
862
972
|
/** Your own id for the person, from `subject.externalRef` at create. */
|
|
@@ -884,6 +994,8 @@ interface SessionReviewDecidedEventData {
|
|
|
884
994
|
sessionId: string;
|
|
885
995
|
outcome: "pass" | "fail";
|
|
886
996
|
reason: string;
|
|
997
|
+
/** Sekyro flows: the flow version the session runs (absent on sessions created before flows). */
|
|
998
|
+
flow?: SessionFlowRef;
|
|
887
999
|
/** The subject (person) the session is linked to, when known. */
|
|
888
1000
|
subjectId?: string;
|
|
889
1001
|
/** Your own id for the person, from `subject.externalRef` at create. */
|
|
@@ -1018,6 +1130,9 @@ declare class SessionsApi {
|
|
|
1018
1130
|
* optional-document session on the person's behalf (the hosted method
|
|
1019
1131
|
* screen is then skipped). `409 method_locked` once the choice can no
|
|
1020
1132
|
* longer change; `409 session_not_active` on a finished or expired session.
|
|
1133
|
+
* On a flow session: `409 choice_not_found` (the flow has no identity-method
|
|
1134
|
+
* choice), `409 choice_locked`, `409 choice_option_unavailable` (see
|
|
1135
|
+
* {@link isFlowError}).
|
|
1021
1136
|
*/
|
|
1022
1137
|
selectMethod(id: string, method: IdentityMethod): Promise<Session>;
|
|
1023
1138
|
/** `GET /sessions/:id` — the whitelisted view (no client token). */
|
|
@@ -1079,9 +1194,17 @@ declare class SubjectsApi {
|
|
|
1079
1194
|
* @public
|
|
1080
1195
|
*/
|
|
1081
1196
|
declare class Sekyro {
|
|
1197
|
+
#private;
|
|
1082
1198
|
readonly sessions: SessionsApi;
|
|
1083
1199
|
readonly subjects: SubjectsApi;
|
|
1084
1200
|
constructor(opts: SekyroOptions);
|
|
1201
|
+
/**
|
|
1202
|
+
* `GET /flows` — the published flows of the API key's app (default flow
|
|
1203
|
+
* first, then by name). Pass a flow's `slug` or `id` as
|
|
1204
|
+
* {@link CreateSessionInput.flow}. Needs the `sessions:create` scope; a key
|
|
1205
|
+
* not bound to an app answers `401 key_not_bound`.
|
|
1206
|
+
*/
|
|
1207
|
+
listFlows(): Promise<FlowSummary[]>;
|
|
1085
1208
|
}
|
|
1086
1209
|
|
|
1087
1210
|
/** Why {@link verifyWebhook} rejected a delivery. @public */
|
|
@@ -1109,15 +1232,104 @@ declare class SekyroConfigError extends TypeError {
|
|
|
1109
1232
|
readonly code: SekyroConfigErrorCode;
|
|
1110
1233
|
constructor(code: SekyroConfigErrorCode, message?: string);
|
|
1111
1234
|
}
|
|
1235
|
+
/**
|
|
1236
|
+
* The flow codes of the partner API (Sekyro flows). Each carries
|
|
1237
|
+
* {@link SekyroApiError.details} (see {@link SekyroFlowErrorDetailsMap} and
|
|
1238
|
+
* {@link isFlowError}). On `sessions.create`:
|
|
1239
|
+
* - `flow_not_found` (404): no flow with this slug or `flw_` id in the key's app;
|
|
1240
|
+
* - `flow_not_published` (409): the flow has no published version yet;
|
|
1241
|
+
* - `flow_archived` (409): the flow is archived;
|
|
1242
|
+
* - `override_invalid` (400): an unknown key or value in `overrides`, or a
|
|
1243
|
+
* result that is not a valid flow;
|
|
1244
|
+
* - `override_widens_flow` (403): the override makes the flow less strict
|
|
1245
|
+
* (e.g. a service turned `'off'`) and the flow does not allow widening;
|
|
1246
|
+
* - `reuse_disabled` (409): `subject.reuse` on a flow whose returning-user
|
|
1247
|
+
* sessions are turned off.
|
|
1248
|
+
*
|
|
1249
|
+
* On `sessions.selectMethod` (a flow session's identity-method choice):
|
|
1250
|
+
* `choice_not_found` (409: the session's flow has no identity-method choice),
|
|
1251
|
+
* `choice_locked` (409: it can no longer change) and
|
|
1252
|
+
* `choice_option_unavailable` (409: that method is not offered).
|
|
1253
|
+
* @public
|
|
1254
|
+
*/
|
|
1255
|
+
type SekyroFlowErrorCode = "flow_not_found" | "flow_not_published" | "flow_archived" | "override_invalid" | "override_widens_flow" | "reuse_disabled" | "choice_not_found" | "choice_locked" | "choice_option_unavailable";
|
|
1256
|
+
/**
|
|
1257
|
+
* One machine-readable issue of a flow error. Never carries a value you sent.
|
|
1258
|
+
* @public
|
|
1259
|
+
*/
|
|
1260
|
+
interface FlowErrorIssue {
|
|
1261
|
+
/**
|
|
1262
|
+
* A flow validation code (e.g. `face_match_needs_liveness`), `schema_invalid`,
|
|
1263
|
+
* `schema_unknown_field`, `field_widens_flow`, or the error's own code.
|
|
1264
|
+
*/
|
|
1265
|
+
code: string;
|
|
1266
|
+
/** A short plain English sentence. */
|
|
1267
|
+
message: string;
|
|
1268
|
+
/** The field of your request body, e.g. `overrides.services.liveness.attempts`, `flow`, `subject.reuse`. */
|
|
1269
|
+
path?: string;
|
|
1270
|
+
/** A node of your app's flow. */
|
|
1271
|
+
nodeId?: string;
|
|
1272
|
+
/** The service of that node (or of the `overrides.services` key). */
|
|
1273
|
+
service?: ServiceId;
|
|
1274
|
+
/** `override_widens_flow`: the widened field, e.g. `settings.eligibility.minAge`, `services.nfc`. */
|
|
1275
|
+
field?: string;
|
|
1276
|
+
}
|
|
1277
|
+
/** `details` common to every flow error: at least one issue. @public */
|
|
1278
|
+
interface FlowErrorDetails {
|
|
1279
|
+
issues: FlowErrorIssue[];
|
|
1280
|
+
}
|
|
1281
|
+
/** `details` of `override_widens_flow`: the widened fields, plus one `field_widens_flow` issue each. @public */
|
|
1282
|
+
interface FlowWidensErrorDetails extends FlowErrorDetails {
|
|
1283
|
+
fields: string[];
|
|
1284
|
+
}
|
|
1285
|
+
/** `details` of `flow_not_published`, `flow_archived` and `reuse_disabled`: the flow concerned. @public */
|
|
1286
|
+
interface FlowRefErrorDetails extends FlowErrorDetails {
|
|
1287
|
+
flow: {
|
|
1288
|
+
id: string;
|
|
1289
|
+
slug: string;
|
|
1290
|
+
};
|
|
1291
|
+
}
|
|
1292
|
+
/**
|
|
1293
|
+
* {@link SekyroFlowErrorCode} → the shape of its {@link SekyroApiError.details}.
|
|
1294
|
+
* @public
|
|
1295
|
+
*/
|
|
1296
|
+
interface SekyroFlowErrorDetailsMap {
|
|
1297
|
+
flow_not_found: FlowErrorDetails;
|
|
1298
|
+
flow_not_published: FlowRefErrorDetails;
|
|
1299
|
+
flow_archived: FlowRefErrorDetails;
|
|
1300
|
+
override_invalid: FlowErrorDetails;
|
|
1301
|
+
override_widens_flow: FlowWidensErrorDetails;
|
|
1302
|
+
reuse_disabled: FlowRefErrorDetails;
|
|
1303
|
+
choice_not_found: FlowErrorDetails;
|
|
1304
|
+
choice_locked: FlowErrorDetails;
|
|
1305
|
+
choice_option_unavailable: FlowErrorDetails;
|
|
1306
|
+
}
|
|
1307
|
+
/**
|
|
1308
|
+
* A {@link SekyroApiError} narrowed by {@link isFlowError}: `code` is a flow
|
|
1309
|
+
* code and `details` has that code's shape.
|
|
1310
|
+
* @public
|
|
1311
|
+
*/
|
|
1312
|
+
type SekyroFlowError<C extends SekyroFlowErrorCode = SekyroFlowErrorCode> = C extends SekyroFlowErrorCode ? SekyroApiError & {
|
|
1313
|
+
readonly code: C;
|
|
1314
|
+
readonly details: SekyroFlowErrorDetailsMap[C];
|
|
1315
|
+
} : never;
|
|
1316
|
+
/**
|
|
1317
|
+
* {@link SekyroApiError.code}: an SDK code, a documented flow code, or any
|
|
1318
|
+
* other API code (the union stays open so a new API code never breaks a build).
|
|
1319
|
+
* @public
|
|
1320
|
+
*/
|
|
1321
|
+
type SekyroApiErrorCode = SekyroClientErrorCode | SekyroFlowErrorCode | (string & {});
|
|
1112
1322
|
/** Constructor input of {@link SekyroApiError}. @public */
|
|
1113
1323
|
interface SekyroApiErrorInit {
|
|
1114
1324
|
/** HTTP status; `0` when no response was received (network / timeout). */
|
|
1115
1325
|
status: number;
|
|
1116
1326
|
/** API error code, or `network` | `timeout` | `http_error` | `malformed_response`. */
|
|
1117
|
-
code:
|
|
1327
|
+
code: SekyroApiErrorCode;
|
|
1118
1328
|
message: string;
|
|
1119
1329
|
/** The API's `request_id`, when the response carried one. */
|
|
1120
1330
|
requestId?: string;
|
|
1331
|
+
/** The API's `error.details`, when the response carried them (the flow codes: {@link SekyroFlowErrorDetailsMap}). */
|
|
1332
|
+
details?: unknown;
|
|
1121
1333
|
/** Underlying error (network failures, abort reasons, JSON parse errors). */
|
|
1122
1334
|
cause?: unknown;
|
|
1123
1335
|
}
|
|
@@ -1135,11 +1347,35 @@ type SekyroClientErrorCode = "network" | "timeout" | "http_error" | "malformed_r
|
|
|
1135
1347
|
declare class SekyroApiError extends Error {
|
|
1136
1348
|
readonly name = "SekyroApiError";
|
|
1137
1349
|
readonly status: number;
|
|
1138
|
-
readonly code:
|
|
1350
|
+
readonly code: SekyroApiErrorCode;
|
|
1139
1351
|
readonly requestId: string | undefined;
|
|
1352
|
+
/**
|
|
1353
|
+
* The API's `error.details`, when the response carried them; `undefined`
|
|
1354
|
+
* otherwise. Untyped here: narrow with {@link isFlowError} to read a flow
|
|
1355
|
+
* code's documented shape ({@link SekyroFlowErrorDetailsMap}).
|
|
1356
|
+
*/
|
|
1357
|
+
readonly details: unknown;
|
|
1140
1358
|
readonly retryable: boolean;
|
|
1141
1359
|
constructor(init: SekyroApiErrorInit);
|
|
1142
1360
|
}
|
|
1361
|
+
/**
|
|
1362
|
+
* Narrow an error to a flow error, optionally to given codes: `true` only for
|
|
1363
|
+
* a {@link SekyroApiError} with a flow code whose `details` have that code's
|
|
1364
|
+
* documented shape, so `err.details` is typed after the check. An error whose
|
|
1365
|
+
* `details` are missing or unexpected is not narrowed (read `err.code`).
|
|
1366
|
+
*
|
|
1367
|
+
* @example
|
|
1368
|
+
* ```ts
|
|
1369
|
+
* try {
|
|
1370
|
+
* await sekyro.sessions.create({ flow, overrides });
|
|
1371
|
+
* } catch (err) {
|
|
1372
|
+
* if (isFlowError(err, "override_widens_flow")) err.details.fields; // string[]
|
|
1373
|
+
* else if (isFlowError(err)) err.details.issues.map((i) => i.path);
|
|
1374
|
+
* }
|
|
1375
|
+
* ```
|
|
1376
|
+
* @public
|
|
1377
|
+
*/
|
|
1378
|
+
declare function isFlowError<C extends SekyroFlowErrorCode = SekyroFlowErrorCode>(err: unknown, ...codes: C[]): err is SekyroFlowError<C>;
|
|
1143
1379
|
|
|
1144
1380
|
/**
|
|
1145
1381
|
* The raw ANRPTS `getPersonne` answer your server received with your own
|
|
@@ -1252,4 +1488,4 @@ interface VerifyWebhookOptions {
|
|
|
1252
1488
|
*/
|
|
1253
1489
|
declare function verifyWebhook(rawBody: string, header: string | null | undefined, secret: string, opts?: VerifyWebhookOptions): WebhookEnvelope;
|
|
1254
1490
|
|
|
1255
|
-
export { type AnrptsPersonneResponse, type CheckState, type CheckType, type CreateSessionInput, type CreatedSession, DEFAULT_BASE_URL, DEFAULT_TIMEOUT_MS, type DecisionReason, type DeepPartial, type DeletedSubject, type DeliverOptions, type EidResult, type
|
|
1491
|
+
export { type AnrptsPersonneResponse, type CheckState, type CheckType, type CreateSessionInput, type CreatedSession, DEFAULT_BASE_URL, DEFAULT_TIMEOUT_MS, type DecisionReason, type DeepPartial, type DeletedSubject, type DeliverOptions, type DocumentSubstitutionSettings, type EidResult, type EligibilityReason, type FetchLike, type FlowErrorDetails, type FlowErrorIssue, type FlowOverridableSettings, type FlowOverrides, type FlowRefErrorDetails, type FlowServiceSettings, type FlowSummary, type FlowWidensErrorDetails, type IdentityMethod, LEGACY_SIGNATURE_HEADER, type Locale, type MatchReason, type PolicyFailureReason, type PortraitReportEntry, type ProbeBindingReason, type ProbeQuality, type ProfileDocumentType, type RegistryFromAnrptsOptions, type RequestOptions, type RevokeSubjectInput, SEKYRO_SIGNATURE_HEADER, Sekyro, SekyroApiError, type SekyroApiErrorCode, type SekyroApiErrorInit, type SekyroClientErrorCode, SekyroConfigError, type SekyroConfigErrorCode, type SekyroEnvironment, type SekyroFlowError, type SekyroFlowErrorCode, type SekyroFlowErrorDetailsMap, type SekyroOptions, SekyroWebhookError, type SekyroWebhookErrorCode, type ServiceId, type Session, type SessionDevice, type SessionDeviceSignal, type SessionEventData, type SessionFailureReason, type SessionFlowRef, type SessionLifecycleEventData, type SessionNetwork, type SessionNetworkEvent, type SessionOutcome, type SessionPortraitLink, type SessionReviewDecidedEventData, type SessionStatus, type SessionStep, type SessionStepCompletedEventData, type SessionSubjectInput, SessionsApi, type Subject, type SubjectAssurance, type SubjectDeletedEventData, type SubjectEnrolledEventData, type SubjectReferenceSource, type SubjectReuseTarget, type SubjectSession, type SubjectStatus, type SubjectSuspiciousActivityEventData, type SubjectUpdatedEventData, SubjectsApi, type SuppliedIdentityRecord, type VerifiedContacts, type VerifyWebhookOptions, type WebhookEnvelope, type WebhookEnvelopeOf, type WebhookEventDataMap, type WebhookEventType, isFlowError, registryFromAnrpts, signatureFromHeaders, verifyWebhook };
|