@sekyro/node 0.1.0-rc.4 → 0.1.0-rc.6
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 +26 -0
- package/README.md +112 -27
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +416 -147
- package/dist/index.d.ts +416 -147
- 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,68 +206,98 @@ 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;
|
|
207
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* An identity document for {@link SubjectReuseTarget}: the document type, the
|
|
217
|
+
* issuing country (ISO 3166-1 alpha-2 or alpha-3) and its number.
|
|
218
|
+
* @public
|
|
219
|
+
*/
|
|
220
|
+
interface SubjectReuseDocument {
|
|
221
|
+
type: "national_id" | "passport" | "residence_permit";
|
|
222
|
+
issuingCountry: string;
|
|
223
|
+
number: string;
|
|
224
|
+
}
|
|
208
225
|
/**
|
|
209
226
|
* Which subject a returning-user session re-verifies — exactly ONE of the
|
|
210
|
-
* subject id, your own `externalRef` (must match a single subject)
|
|
227
|
+
* subject id, your own `externalRef` (must match a single subject), the NNI
|
|
228
|
+
* or an identity document the person verified with.
|
|
211
229
|
* @public
|
|
212
230
|
*/
|
|
213
231
|
type SubjectReuseTarget = {
|
|
214
232
|
subjectId: string;
|
|
215
233
|
externalRef?: never;
|
|
216
234
|
nni?: never;
|
|
235
|
+
document?: never;
|
|
217
236
|
} | {
|
|
218
237
|
externalRef: string;
|
|
219
238
|
subjectId?: never;
|
|
220
239
|
nni?: never;
|
|
240
|
+
document?: never;
|
|
221
241
|
} | {
|
|
222
242
|
nni: string;
|
|
223
243
|
subjectId?: never;
|
|
224
244
|
externalRef?: never;
|
|
245
|
+
document?: never;
|
|
246
|
+
} | {
|
|
247
|
+
document: SubjectReuseDocument;
|
|
248
|
+
subjectId?: never;
|
|
249
|
+
externalRef?: never;
|
|
250
|
+
nni?: never;
|
|
225
251
|
};
|
|
226
252
|
/** A document type the backend reads (kyc-docs-v2 vocabulary; `carte_identite` = identity card of any issuer). @public */
|
|
227
253
|
type ProfileDocumentType = "carte_identite" | "passport" | "residence_permit";
|
|
228
254
|
/**
|
|
229
|
-
* The
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
* Used through {@link EkycProfileOverride}.
|
|
255
|
+
* The services a Sekyro flow is built from. A session's steps
|
|
256
|
+
* ({@link SessionStep.service}) and {@link FlowOverrides.services} use these
|
|
257
|
+
* ids; one service may run several checks (e.g. `liveness` with an ICAO
|
|
258
|
+
* portrait).
|
|
234
259
|
* @public
|
|
235
260
|
*/
|
|
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[];
|
|
261
|
+
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";
|
|
262
|
+
/**
|
|
263
|
+
* The general settings of a flow that a session may override (the flow's
|
|
264
|
+
* `link`, `language` and override policy are not overridable). Country codes
|
|
265
|
+
* are ISO 3166-1 alpha-2 (`MR`). Used through {@link FlowOverrides.settings}.
|
|
266
|
+
* @public
|
|
267
|
+
*/
|
|
268
|
+
interface FlowOverridableSettings {
|
|
269
|
+
/** Who may be verified. */
|
|
270
|
+
eligibility: {
|
|
271
|
+
/** Accepted nationalities: `'*'` or a list, optionally per IP location. */
|
|
272
|
+
nationalities: {
|
|
273
|
+
default: "*" | string[];
|
|
274
|
+
byLocation?: Record<string, "*" | string[]>;
|
|
259
275
|
};
|
|
276
|
+
/** Minimum age in years (1–120), or `null` for none. */
|
|
277
|
+
minAge: number | null;
|
|
260
278
|
};
|
|
261
|
-
/**
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
279
|
+
/** Automatic decisions instead of human review (`retryConfidentRejects` lets confident rejects retry). */
|
|
280
|
+
decisions?: {
|
|
281
|
+
mode: "automatic" | "review";
|
|
282
|
+
retryConfidentRejects: boolean;
|
|
283
|
+
};
|
|
284
|
+
/** Data consistency across sources. */
|
|
285
|
+
fraud: {
|
|
286
|
+
/** Comparison of your `subject` data with the reference identity. */
|
|
287
|
+
nameMatch?: {
|
|
288
|
+
level: "strict" | "standard" | "lenient";
|
|
289
|
+
onMismatch: "fail" | "signal";
|
|
290
|
+
};
|
|
291
|
+
};
|
|
292
|
+
/** Returning-user sessions (`subject.reuse`). */
|
|
293
|
+
returning: {
|
|
294
|
+
/** `false`: returning-user sessions are refused (`409 reuse_disabled`). */
|
|
295
|
+
enabled: boolean;
|
|
296
|
+
/** Maximum age in months (1–120) of the subject's last verification; `null` = no limit. */
|
|
297
|
+
maxAgeMonths: number | null;
|
|
298
|
+
};
|
|
299
|
+
/** Identity-document rules. */
|
|
300
|
+
documents: {
|
|
265
301
|
/** Accepted document types: `'*'` (all) or a list, optionally per issuing country. */
|
|
266
302
|
accepted: {
|
|
267
303
|
default: "*" | ProfileDocumentType[];
|
|
@@ -273,98 +309,123 @@ interface EkycProfileSettings {
|
|
|
273
309
|
};
|
|
274
310
|
authenticity: "standard" | "off";
|
|
275
311
|
};
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Document substitution: the portrait a `document` or `nfc` step produces is
|
|
315
|
+
* compared with the registry portrait (or the chip with the printed photo).
|
|
316
|
+
* `signal` records a risk signal on a clear mismatch, `review` also sends the
|
|
317
|
+
* session to review, `off` compares nothing. `failBelow` is the mismatch bound
|
|
318
|
+
* in (0, 1), absent = the platform bound.
|
|
319
|
+
* @public
|
|
320
|
+
*/
|
|
321
|
+
interface DocumentSubstitutionSettings {
|
|
322
|
+
mode: "off" | "signal" | "review";
|
|
323
|
+
failBelow?: number;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* The per-service settings a session may override, by {@link ServiceId}.
|
|
327
|
+
* `attempts` limits are per step (absent = the platform default).
|
|
328
|
+
* @public
|
|
329
|
+
*/
|
|
330
|
+
interface FlowServiceSettings {
|
|
331
|
+
/** Device & Network Intelligence: IP location, anonymizers, cooldown, device and capture postures. */
|
|
332
|
+
device_network: {
|
|
333
|
+
/** Where the end user may be (IP location). */
|
|
334
|
+
locations: {
|
|
335
|
+
mode: "all";
|
|
336
|
+
} | {
|
|
337
|
+
mode: "only" | "all_except";
|
|
338
|
+
countries: string[];
|
|
339
|
+
};
|
|
340
|
+
/** VPN / proxy / Tor. */
|
|
341
|
+
anonymizers: "allow" | "block";
|
|
342
|
+
/** Device cooldown after repeated rejections (at most 5 tiers; `[]` = off). */
|
|
343
|
+
cooldown?: {
|
|
344
|
+
tiers: Array<{
|
|
345
|
+
rejectedSessions: number;
|
|
346
|
+
windowHours: number;
|
|
347
|
+
waitMinutes: number;
|
|
348
|
+
}>;
|
|
349
|
+
};
|
|
350
|
+
/** Device tamper and velocity actions. */
|
|
351
|
+
device?: {
|
|
352
|
+
tamper: "block" | "signal";
|
|
353
|
+
velocity: {
|
|
354
|
+
maxIdentitiesPerDevice: number;
|
|
355
|
+
windowDays: number;
|
|
356
|
+
action: "signal" | "block";
|
|
357
|
+
};
|
|
358
|
+
};
|
|
359
|
+
attestation?: "off" | "signal" | "enforce";
|
|
360
|
+
captureIntegrity?: "off" | "signal" | "enforce";
|
|
283
361
|
};
|
|
284
|
-
|
|
285
|
-
|
|
362
|
+
phone_otp: {
|
|
363
|
+
/** Where the number comes from: your `subject.phone` / `input.phone`, the person, or either. */
|
|
364
|
+
numberSource: "prefilled" | "user_entered" | "prefilled_or_entered";
|
|
365
|
+
/** Narrow the channels the person may choose from (absent = every channel the org has on). */
|
|
366
|
+
channels?: Array<"whatsapp" | "sms">;
|
|
367
|
+
/** Which countries codes may be sent to (absent = the flow's allowed `locations`). */
|
|
368
|
+
destinations?: "locations" | "any" | {
|
|
369
|
+
countries: string[];
|
|
370
|
+
};
|
|
371
|
+
attempts?: number;
|
|
286
372
|
};
|
|
287
|
-
|
|
288
|
-
|
|
373
|
+
email_otp: {
|
|
374
|
+
/** Where the address comes from: your `input.email`, the person, or either. */
|
|
375
|
+
emailSource: "prefilled" | "user_entered" | "prefilled_or_entered";
|
|
376
|
+
/** Disposable (temporary) addresses: allowed, flagged as a risk signal (default), or refused. */
|
|
377
|
+
disposable?: "allow" | "signal" | "block";
|
|
378
|
+
attempts?: number;
|
|
289
379
|
};
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
380
|
+
national_eid: {
|
|
381
|
+
/**
|
|
382
|
+
* `'org'` (every national eID the org can use, resolved at session create)
|
|
383
|
+
* or provider ids (`{country}.{provider}`, e.g. `MR.houwiyeti`).
|
|
384
|
+
*/
|
|
385
|
+
providers: "org" | string[];
|
|
386
|
+
/** The eID portrait is the face-match reference. */
|
|
387
|
+
portraitReference: boolean;
|
|
294
388
|
};
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
email?: number;
|
|
300
|
-
document: number;
|
|
301
|
-
registry: number;
|
|
302
|
-
liveness: number;
|
|
303
|
-
faceMatch: number;
|
|
389
|
+
document: {
|
|
390
|
+
attempts?: number;
|
|
391
|
+
/** Compare the document photo with the registry photo (absent = the platform default). */
|
|
392
|
+
documentSubstitution?: DocumentSubstitutionSettings;
|
|
304
393
|
};
|
|
305
|
-
/**
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
countries: string[];
|
|
394
|
+
/** The chip read (its MRZ source is derived from the flow and is not overridable). */
|
|
395
|
+
nfc: {
|
|
396
|
+
maxAttempts?: number;
|
|
397
|
+
/** Compare the chip photo with the registry photo (absent = the platform default). */
|
|
398
|
+
documentSubstitution?: DocumentSubstitutionSettings;
|
|
311
399
|
};
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
400
|
+
population_registry: {
|
|
401
|
+
/** `'org'` (every registry the org can use, resolved at session create) or registry ids. */
|
|
402
|
+
sources: "org" | Array<"MR.anrpts">;
|
|
403
|
+
nniSource: "auto" | "typed" | "bound_only";
|
|
404
|
+
onUncovered: "skip";
|
|
405
|
+
attempts?: number;
|
|
317
406
|
};
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
mode: "automatic" | "review";
|
|
323
|
-
retryConfidentRejects: boolean;
|
|
407
|
+
supplied_identity: Record<string, never>;
|
|
408
|
+
summary_confirm: {
|
|
409
|
+
/** Offer « Reprendre » (re-open the identity source). */
|
|
410
|
+
retake: boolean;
|
|
324
411
|
};
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
windowHours: number;
|
|
330
|
-
waitMinutes: number;
|
|
331
|
-
}>;
|
|
412
|
+
liveness: {
|
|
413
|
+
/** `off`, selfie ICAO `alert` / `reject`, or `id_document` (ID-photo portrait, always rejects). */
|
|
414
|
+
icao: "off" | "alert" | "reject" | "id_document";
|
|
415
|
+
attempts?: number;
|
|
332
416
|
};
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
velocity: {
|
|
337
|
-
maxIdentitiesPerDevice: number;
|
|
338
|
-
windowDays: number;
|
|
339
|
-
action: "signal" | "block";
|
|
340
|
-
};
|
|
417
|
+
face_match: {
|
|
418
|
+
reference: "auto" | "document" | "registry";
|
|
419
|
+
attempts?: number;
|
|
341
420
|
};
|
|
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
|
-
};
|
|
421
|
+
aml_screening: {
|
|
422
|
+
lists: Array<"sanctions" | "pep" | "adverse_media">;
|
|
423
|
+
onHit: "review" | "fail";
|
|
424
|
+
};
|
|
425
|
+
face_dedup: {
|
|
426
|
+
scope: "app" | "org";
|
|
427
|
+
onDuplicate: "review" | "fail";
|
|
356
428
|
};
|
|
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
429
|
}
|
|
369
430
|
/**
|
|
370
431
|
* `T` with every property optional, recursively. Arrays are replaced as a
|
|
@@ -375,37 +436,86 @@ type DeepPartial<T> = T extends readonly unknown[] ? T : T extends object ? {
|
|
|
375
436
|
[K in keyof T]?: DeepPartial<T[K]>;
|
|
376
437
|
} : T;
|
|
377
438
|
/**
|
|
378
|
-
* A per-session override of the
|
|
379
|
-
*
|
|
380
|
-
* {@link
|
|
381
|
-
*
|
|
439
|
+
* A per-session override of the flow ({@link CreateSessionInput.overrides}).
|
|
440
|
+
*
|
|
441
|
+
* - `settings`: any subset of {@link FlowOverridableSettings}, at any depth.
|
|
442
|
+
* - `services`: keyed by service (applied to every node of that service): any
|
|
443
|
+
* subset of its {@link FlowServiceSettings}, or `'off'` to remove it from
|
|
444
|
+
* the flow. A service the flow does not use is ignored.
|
|
445
|
+
*
|
|
446
|
+
* Objects merge into the flow; arrays and scalar values replace. Unknown keys
|
|
447
|
+
* and invalid results answer `400 override_invalid`. An override may only
|
|
448
|
+
* make the flow stricter unless the flow allows widening; turning a service
|
|
449
|
+
* `'off'` always widens. A widening change answers `403 override_widens_flow`.
|
|
450
|
+
* The changed paths are reported on {@link Session.overriddenFields}.
|
|
382
451
|
*
|
|
383
|
-
*
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
*
|
|
387
|
-
*
|
|
388
|
-
* {
|
|
452
|
+
* @example
|
|
453
|
+
* ```ts
|
|
454
|
+
* await sekyro.sessions.create({
|
|
455
|
+
* flow: "foreigners",
|
|
456
|
+
* overrides: {
|
|
457
|
+
* settings: { eligibility: { minAge: 21 } },
|
|
458
|
+
* services: { liveness: { attempts: 2 } },
|
|
459
|
+
* },
|
|
460
|
+
* });
|
|
461
|
+
* ```
|
|
462
|
+
* @public
|
|
463
|
+
*/
|
|
464
|
+
interface FlowOverrides {
|
|
465
|
+
settings?: DeepPartial<FlowOverridableSettings>;
|
|
466
|
+
services?: {
|
|
467
|
+
[S in ServiceId]?: DeepPartial<FlowServiceSettings[S]> | "off";
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* The flow version a session runs: its `flw_` id, its slug and the published
|
|
472
|
+
* version pinned at create.
|
|
389
473
|
* @public
|
|
390
474
|
*/
|
|
391
|
-
|
|
475
|
+
interface SessionFlowRef {
|
|
476
|
+
id: string;
|
|
477
|
+
slug: string;
|
|
478
|
+
version: number;
|
|
479
|
+
}
|
|
392
480
|
/**
|
|
393
|
-
*
|
|
394
|
-
*
|
|
481
|
+
* One flow of your app, from {@link Sekyro.listFlows}. Published flows only;
|
|
482
|
+
* pass `slug` or `id` as {@link CreateSessionInput.flow}.
|
|
483
|
+
* @public
|
|
484
|
+
*/
|
|
485
|
+
interface FlowSummary {
|
|
486
|
+
/** `flw_` id. */
|
|
487
|
+
id: string;
|
|
488
|
+
slug: string;
|
|
489
|
+
name: string;
|
|
490
|
+
/** The published version a new session runs. */
|
|
491
|
+
version: number;
|
|
492
|
+
/** The flow a session runs when you send no `flow`. */
|
|
493
|
+
isDefault: boolean;
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Input of {@link SessionsApi.create}. The API key belongs to an app; the
|
|
497
|
+
* app's flow (its default flow, or the one named in `flow`) decides the steps.
|
|
395
498
|
* @public
|
|
396
499
|
*/
|
|
397
500
|
interface CreateSessionInput {
|
|
501
|
+
/**
|
|
502
|
+
* The app's flow to run: its slug (e.g. `foreigners`) or `flw_` id, as
|
|
503
|
+
* {@link Sekyro.listFlows} lists them. Absent = the app's default flow.
|
|
504
|
+
* Errors: `404 flow_not_found` (no such flow in the key's app),
|
|
505
|
+
* `409 flow_not_published`, `409 flow_archived`.
|
|
506
|
+
*/
|
|
507
|
+
flow?: string;
|
|
398
508
|
/** Pins the hosted-flow language. Omit to let the person's device decide. */
|
|
399
509
|
locale?: Locale;
|
|
400
510
|
/**
|
|
401
|
-
* Pre-choose the identity method when the
|
|
402
|
-
* (the hosted
|
|
511
|
+
* Pre-choose the identity method when the flow offers a choice of identity
|
|
512
|
+
* method (the hosted choice screen is then skipped). Ignored otherwise.
|
|
403
513
|
*/
|
|
404
514
|
identityMethod?: IdentityMethod;
|
|
405
515
|
/**
|
|
406
|
-
* Session lifetime in minutes. Must fall within the
|
|
407
|
-
*
|
|
408
|
-
*
|
|
516
|
+
* Session lifetime in minutes. Must fall within the flow's link range,
|
|
517
|
+
* otherwise the API answers `400 ttl_out_of_policy`. Omit to use the
|
|
518
|
+
* flow's default.
|
|
409
519
|
*/
|
|
410
520
|
ttlMinutes?: number;
|
|
411
521
|
/** Also send the hosted link to the person by SMS or WhatsApp. */
|
|
@@ -417,12 +527,21 @@ interface CreateSessionInput {
|
|
|
417
527
|
*/
|
|
418
528
|
subject?: SessionSubjectInput;
|
|
419
529
|
/**
|
|
420
|
-
*
|
|
421
|
-
*
|
|
422
|
-
*
|
|
423
|
-
* `403 override_widens_profile` unless the app allows widening.
|
|
530
|
+
* Your own id for the agent filming the person, for flows whose liveness
|
|
531
|
+
* capture is `assisted` (1 to 128 characters). Stored as is and echoed on
|
|
532
|
+
* the session and in webhooks.
|
|
424
533
|
*/
|
|
425
|
-
|
|
534
|
+
assistedBy?: {
|
|
535
|
+
externalRef: string;
|
|
536
|
+
};
|
|
537
|
+
/**
|
|
538
|
+
* Override the flow for this session only ({@link FlowOverrides}): its
|
|
539
|
+
* general settings and per-service settings, or turn a service `'off'`.
|
|
540
|
+
* `400 override_invalid` for an unknown key or an invalid result;
|
|
541
|
+
* `403 override_widens_flow` for a change that makes the flow less strict
|
|
542
|
+
* when the flow does not allow widening.
|
|
543
|
+
*/
|
|
544
|
+
overrides?: FlowOverrides;
|
|
426
545
|
/**
|
|
427
546
|
* Step inputs consumed server-side. The known anchors are typed (all
|
|
428
547
|
* strings — an `nni` is a 10-digit string, never a number); further keys
|
|
@@ -507,6 +626,9 @@ interface CreatedSession {
|
|
|
507
626
|
clientToken: string;
|
|
508
627
|
/** Hosted verification link for this session. */
|
|
509
628
|
hostedUrl: string;
|
|
629
|
+
/** The flow version the session runs (the default flow when you sent no `flow`). */
|
|
630
|
+
flow?: SessionFlowRef;
|
|
631
|
+
/** The checks on the session's path (checks of a lane not taken are omitted). */
|
|
510
632
|
steps: SessionStep[];
|
|
511
633
|
/** ISO 8601 — when the session (and its link) stop accepting input. */
|
|
512
634
|
expiresAt: string;
|
|
@@ -612,13 +734,18 @@ interface VerifiedContacts {
|
|
|
612
734
|
*/
|
|
613
735
|
interface Session {
|
|
614
736
|
id: string;
|
|
737
|
+
/** Sekyro flows: the flow version the session runs (absent on sessions created before flows). */
|
|
738
|
+
flow?: SessionFlowRef;
|
|
615
739
|
status: SessionStatus;
|
|
616
740
|
outcome: SessionOutcome | null;
|
|
741
|
+
/** The checks on the session's path (checks of a lane the person did not take are omitted). */
|
|
617
742
|
steps: SessionStep[];
|
|
618
743
|
/** ISO 8601. */
|
|
619
744
|
expiresAt: string;
|
|
620
745
|
/** ISO 8601. */
|
|
621
746
|
createdAt: string;
|
|
747
|
+
/** ISO 8601: when the session reached a terminal state; `null` while it is active. */
|
|
748
|
+
completedAt?: string | null;
|
|
622
749
|
/** End-user network context; absent when not recorded. */
|
|
623
750
|
network?: SessionNetwork;
|
|
624
751
|
/** End-user device; absent when not recorded. */
|
|
@@ -633,6 +760,10 @@ interface Session {
|
|
|
633
760
|
subjectId?: string;
|
|
634
761
|
/** Your own id for the person, from `subject.externalRef` at create. */
|
|
635
762
|
externalRef?: string;
|
|
763
|
+
/** The agent reference sent as `assistedBy` at create, for assisted capture. */
|
|
764
|
+
assistedBy?: {
|
|
765
|
+
externalRef: string;
|
|
766
|
+
};
|
|
636
767
|
/**
|
|
637
768
|
* `true` when an identifier this session read already belongs to a
|
|
638
769
|
* different subject than `subjectId` — the subjects are never merged.
|
|
@@ -643,7 +774,10 @@ interface Session {
|
|
|
643
774
|
* `failureReason: 'device_cooldown'`.
|
|
644
775
|
*/
|
|
645
776
|
retryAfter?: string;
|
|
646
|
-
/**
|
|
777
|
+
/**
|
|
778
|
+
* Dotted paths this session's {@link CreateSessionInput.overrides} changed
|
|
779
|
+
* (e.g. `settings.decisions.mode`, `services.liveness`).
|
|
780
|
+
*/
|
|
647
781
|
overriddenFields?: string[];
|
|
648
782
|
/**
|
|
649
783
|
* Risk signals recorded on the session (e.g. `device_velocity`,
|
|
@@ -675,14 +809,17 @@ interface Session {
|
|
|
675
809
|
* `session.expired` | `session.rejected`) — ids and enums only, no civil data,
|
|
676
810
|
* scores or links. `outcome` and `steps` travel on `completed` / `failed`;
|
|
677
811
|
* `review_pending` carries `steps` without an outcome; `expired` carries the
|
|
678
|
-
* status
|
|
812
|
+
* status and the session's refs (`flow`, subject ids, `overriddenFields`).
|
|
679
813
|
* @public
|
|
680
814
|
*/
|
|
681
815
|
interface SessionLifecycleEventData {
|
|
682
816
|
sessionId: string;
|
|
683
817
|
status: SessionStatus;
|
|
684
818
|
outcome?: SessionOutcome | null;
|
|
685
|
-
|
|
819
|
+
/** The checks on the session's path (checks of a lane the person did not take are omitted). */
|
|
820
|
+
steps?: Array<Pick<SessionStep, "checkType" | "state" | "nodeId" | "service">>;
|
|
821
|
+
/** Sekyro flows: the flow version the session runs (absent on sessions created before flows). */
|
|
822
|
+
flow?: SessionFlowRef;
|
|
686
823
|
/** Machine-readable reason, when the transition has one. */
|
|
687
824
|
reason?: string;
|
|
688
825
|
/** End-user network context (no IP); on `completed` / `failed` when recorded. */
|
|
@@ -713,7 +850,7 @@ interface SessionLifecycleEventData {
|
|
|
713
850
|
* from which the device may start a new verification.
|
|
714
851
|
*/
|
|
715
852
|
retryAfter?: string;
|
|
716
|
-
/** Dotted
|
|
853
|
+
/** Dotted paths the session's create-time {@link CreateSessionInput.overrides} changed. */
|
|
717
854
|
overriddenFields?: string[];
|
|
718
855
|
/** On `completed` / `failed`: the contacts verified in this session (passed OTP checks only). */
|
|
719
856
|
verifiedContacts?: VerifiedContacts;
|
|
@@ -818,8 +955,8 @@ interface Subject {
|
|
|
818
955
|
/**
|
|
819
956
|
* A returning-user session can be created now: active, a reference photo is
|
|
820
957
|
* stored, and the last FULL verification (returning-user sessions do not
|
|
821
|
-
* reset it) is within your app's
|
|
822
|
-
* `
|
|
958
|
+
* reset it) is within the returning-user limit of your app's default flow
|
|
959
|
+
* (`settings.returning`: turned on, and `maxAgeMonths` when set).
|
|
823
960
|
*/
|
|
824
961
|
returningReady: boolean;
|
|
825
962
|
/** The verified name / birth date of the latest approved session. */
|
|
@@ -857,6 +994,12 @@ interface SessionStepCompletedEventData {
|
|
|
857
994
|
sessionId: string;
|
|
858
995
|
checkType: CheckType;
|
|
859
996
|
state: CheckState;
|
|
997
|
+
/** Sekyro flows: the flow node of the passed check. */
|
|
998
|
+
nodeId?: string;
|
|
999
|
+
/** Sekyro flows: the service of that node. */
|
|
1000
|
+
service?: ServiceId;
|
|
1001
|
+
/** Sekyro flows: the flow version the session runs (absent on sessions created before flows). */
|
|
1002
|
+
flow?: SessionFlowRef;
|
|
860
1003
|
/** The subject (person) the session is linked to, when known. */
|
|
861
1004
|
subjectId?: string;
|
|
862
1005
|
/** Your own id for the person, from `subject.externalRef` at create. */
|
|
@@ -884,6 +1027,8 @@ interface SessionReviewDecidedEventData {
|
|
|
884
1027
|
sessionId: string;
|
|
885
1028
|
outcome: "pass" | "fail";
|
|
886
1029
|
reason: string;
|
|
1030
|
+
/** Sekyro flows: the flow version the session runs (absent on sessions created before flows). */
|
|
1031
|
+
flow?: SessionFlowRef;
|
|
887
1032
|
/** The subject (person) the session is linked to, when known. */
|
|
888
1033
|
subjectId?: string;
|
|
889
1034
|
/** Your own id for the person, from `subject.externalRef` at create. */
|
|
@@ -1018,6 +1163,9 @@ declare class SessionsApi {
|
|
|
1018
1163
|
* optional-document session on the person's behalf (the hosted method
|
|
1019
1164
|
* screen is then skipped). `409 method_locked` once the choice can no
|
|
1020
1165
|
* longer change; `409 session_not_active` on a finished or expired session.
|
|
1166
|
+
* On a flow session: `409 choice_not_found` (the flow has no identity-method
|
|
1167
|
+
* choice), `409 choice_locked`, `409 choice_option_unavailable` (see
|
|
1168
|
+
* {@link isFlowError}).
|
|
1021
1169
|
*/
|
|
1022
1170
|
selectMethod(id: string, method: IdentityMethod): Promise<Session>;
|
|
1023
1171
|
/** `GET /sessions/:id` — the whitelisted view (no client token). */
|
|
@@ -1079,9 +1227,17 @@ declare class SubjectsApi {
|
|
|
1079
1227
|
* @public
|
|
1080
1228
|
*/
|
|
1081
1229
|
declare class Sekyro {
|
|
1230
|
+
#private;
|
|
1082
1231
|
readonly sessions: SessionsApi;
|
|
1083
1232
|
readonly subjects: SubjectsApi;
|
|
1084
1233
|
constructor(opts: SekyroOptions);
|
|
1234
|
+
/**
|
|
1235
|
+
* `GET /flows` — the published flows of the API key's app (default flow
|
|
1236
|
+
* first, then by name). Pass a flow's `slug` or `id` as
|
|
1237
|
+
* {@link CreateSessionInput.flow}. Needs the `sessions:create` scope; a key
|
|
1238
|
+
* not bound to an app answers `401 key_not_bound`.
|
|
1239
|
+
*/
|
|
1240
|
+
listFlows(): Promise<FlowSummary[]>;
|
|
1085
1241
|
}
|
|
1086
1242
|
|
|
1087
1243
|
/** Why {@link verifyWebhook} rejected a delivery. @public */
|
|
@@ -1109,15 +1265,104 @@ declare class SekyroConfigError extends TypeError {
|
|
|
1109
1265
|
readonly code: SekyroConfigErrorCode;
|
|
1110
1266
|
constructor(code: SekyroConfigErrorCode, message?: string);
|
|
1111
1267
|
}
|
|
1268
|
+
/**
|
|
1269
|
+
* The flow codes of the partner API (Sekyro flows). Each carries
|
|
1270
|
+
* {@link SekyroApiError.details} (see {@link SekyroFlowErrorDetailsMap} and
|
|
1271
|
+
* {@link isFlowError}). On `sessions.create`:
|
|
1272
|
+
* - `flow_not_found` (404): no flow with this slug or `flw_` id in the key's app;
|
|
1273
|
+
* - `flow_not_published` (409): the flow has no published version yet;
|
|
1274
|
+
* - `flow_archived` (409): the flow is archived;
|
|
1275
|
+
* - `override_invalid` (400): an unknown key or value in `overrides`, or a
|
|
1276
|
+
* result that is not a valid flow;
|
|
1277
|
+
* - `override_widens_flow` (403): the override makes the flow less strict
|
|
1278
|
+
* (e.g. a service turned `'off'`) and the flow does not allow widening;
|
|
1279
|
+
* - `reuse_disabled` (409): `subject.reuse` on a flow whose returning-user
|
|
1280
|
+
* sessions are turned off.
|
|
1281
|
+
*
|
|
1282
|
+
* On `sessions.selectMethod` (a flow session's identity-method choice):
|
|
1283
|
+
* `choice_not_found` (409: the session's flow has no identity-method choice),
|
|
1284
|
+
* `choice_locked` (409: it can no longer change) and
|
|
1285
|
+
* `choice_option_unavailable` (409: that method is not offered).
|
|
1286
|
+
* @public
|
|
1287
|
+
*/
|
|
1288
|
+
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";
|
|
1289
|
+
/**
|
|
1290
|
+
* One machine-readable issue of a flow error. Never carries a value you sent.
|
|
1291
|
+
* @public
|
|
1292
|
+
*/
|
|
1293
|
+
interface FlowErrorIssue {
|
|
1294
|
+
/**
|
|
1295
|
+
* A flow validation code (e.g. `face_match_needs_liveness`), `schema_invalid`,
|
|
1296
|
+
* `schema_unknown_field`, `field_widens_flow`, or the error's own code.
|
|
1297
|
+
*/
|
|
1298
|
+
code: string;
|
|
1299
|
+
/** A short plain English sentence. */
|
|
1300
|
+
message: string;
|
|
1301
|
+
/** The field of your request body, e.g. `overrides.services.liveness.attempts`, `flow`, `subject.reuse`. */
|
|
1302
|
+
path?: string;
|
|
1303
|
+
/** A node of your app's flow. */
|
|
1304
|
+
nodeId?: string;
|
|
1305
|
+
/** The service of that node (or of the `overrides.services` key). */
|
|
1306
|
+
service?: ServiceId;
|
|
1307
|
+
/** `override_widens_flow`: the widened field, e.g. `settings.eligibility.minAge`, `services.nfc`. */
|
|
1308
|
+
field?: string;
|
|
1309
|
+
}
|
|
1310
|
+
/** `details` common to every flow error: at least one issue. @public */
|
|
1311
|
+
interface FlowErrorDetails {
|
|
1312
|
+
issues: FlowErrorIssue[];
|
|
1313
|
+
}
|
|
1314
|
+
/** `details` of `override_widens_flow`: the widened fields, plus one `field_widens_flow` issue each. @public */
|
|
1315
|
+
interface FlowWidensErrorDetails extends FlowErrorDetails {
|
|
1316
|
+
fields: string[];
|
|
1317
|
+
}
|
|
1318
|
+
/** `details` of `flow_not_published`, `flow_archived` and `reuse_disabled`: the flow concerned. @public */
|
|
1319
|
+
interface FlowRefErrorDetails extends FlowErrorDetails {
|
|
1320
|
+
flow: {
|
|
1321
|
+
id: string;
|
|
1322
|
+
slug: string;
|
|
1323
|
+
};
|
|
1324
|
+
}
|
|
1325
|
+
/**
|
|
1326
|
+
* {@link SekyroFlowErrorCode} → the shape of its {@link SekyroApiError.details}.
|
|
1327
|
+
* @public
|
|
1328
|
+
*/
|
|
1329
|
+
interface SekyroFlowErrorDetailsMap {
|
|
1330
|
+
flow_not_found: FlowErrorDetails;
|
|
1331
|
+
flow_not_published: FlowRefErrorDetails;
|
|
1332
|
+
flow_archived: FlowRefErrorDetails;
|
|
1333
|
+
override_invalid: FlowErrorDetails;
|
|
1334
|
+
override_widens_flow: FlowWidensErrorDetails;
|
|
1335
|
+
reuse_disabled: FlowRefErrorDetails;
|
|
1336
|
+
choice_not_found: FlowErrorDetails;
|
|
1337
|
+
choice_locked: FlowErrorDetails;
|
|
1338
|
+
choice_option_unavailable: FlowErrorDetails;
|
|
1339
|
+
}
|
|
1340
|
+
/**
|
|
1341
|
+
* A {@link SekyroApiError} narrowed by {@link isFlowError}: `code` is a flow
|
|
1342
|
+
* code and `details` has that code's shape.
|
|
1343
|
+
* @public
|
|
1344
|
+
*/
|
|
1345
|
+
type SekyroFlowError<C extends SekyroFlowErrorCode = SekyroFlowErrorCode> = C extends SekyroFlowErrorCode ? SekyroApiError & {
|
|
1346
|
+
readonly code: C;
|
|
1347
|
+
readonly details: SekyroFlowErrorDetailsMap[C];
|
|
1348
|
+
} : never;
|
|
1349
|
+
/**
|
|
1350
|
+
* {@link SekyroApiError.code}: an SDK code, a documented flow code, or any
|
|
1351
|
+
* other API code (the union stays open so a new API code never breaks a build).
|
|
1352
|
+
* @public
|
|
1353
|
+
*/
|
|
1354
|
+
type SekyroApiErrorCode = SekyroClientErrorCode | SekyroFlowErrorCode | (string & {});
|
|
1112
1355
|
/** Constructor input of {@link SekyroApiError}. @public */
|
|
1113
1356
|
interface SekyroApiErrorInit {
|
|
1114
1357
|
/** HTTP status; `0` when no response was received (network / timeout). */
|
|
1115
1358
|
status: number;
|
|
1116
1359
|
/** API error code, or `network` | `timeout` | `http_error` | `malformed_response`. */
|
|
1117
|
-
code:
|
|
1360
|
+
code: SekyroApiErrorCode;
|
|
1118
1361
|
message: string;
|
|
1119
1362
|
/** The API's `request_id`, when the response carried one. */
|
|
1120
1363
|
requestId?: string;
|
|
1364
|
+
/** The API's `error.details`, when the response carried them (the flow codes: {@link SekyroFlowErrorDetailsMap}). */
|
|
1365
|
+
details?: unknown;
|
|
1121
1366
|
/** Underlying error (network failures, abort reasons, JSON parse errors). */
|
|
1122
1367
|
cause?: unknown;
|
|
1123
1368
|
}
|
|
@@ -1135,11 +1380,35 @@ type SekyroClientErrorCode = "network" | "timeout" | "http_error" | "malformed_r
|
|
|
1135
1380
|
declare class SekyroApiError extends Error {
|
|
1136
1381
|
readonly name = "SekyroApiError";
|
|
1137
1382
|
readonly status: number;
|
|
1138
|
-
readonly code:
|
|
1383
|
+
readonly code: SekyroApiErrorCode;
|
|
1139
1384
|
readonly requestId: string | undefined;
|
|
1385
|
+
/**
|
|
1386
|
+
* The API's `error.details`, when the response carried them; `undefined`
|
|
1387
|
+
* otherwise. Untyped here: narrow with {@link isFlowError} to read a flow
|
|
1388
|
+
* code's documented shape ({@link SekyroFlowErrorDetailsMap}).
|
|
1389
|
+
*/
|
|
1390
|
+
readonly details: unknown;
|
|
1140
1391
|
readonly retryable: boolean;
|
|
1141
1392
|
constructor(init: SekyroApiErrorInit);
|
|
1142
1393
|
}
|
|
1394
|
+
/**
|
|
1395
|
+
* Narrow an error to a flow error, optionally to given codes: `true` only for
|
|
1396
|
+
* a {@link SekyroApiError} with a flow code whose `details` have that code's
|
|
1397
|
+
* documented shape, so `err.details` is typed after the check. An error whose
|
|
1398
|
+
* `details` are missing or unexpected is not narrowed (read `err.code`).
|
|
1399
|
+
*
|
|
1400
|
+
* @example
|
|
1401
|
+
* ```ts
|
|
1402
|
+
* try {
|
|
1403
|
+
* await sekyro.sessions.create({ flow, overrides });
|
|
1404
|
+
* } catch (err) {
|
|
1405
|
+
* if (isFlowError(err, "override_widens_flow")) err.details.fields; // string[]
|
|
1406
|
+
* else if (isFlowError(err)) err.details.issues.map((i) => i.path);
|
|
1407
|
+
* }
|
|
1408
|
+
* ```
|
|
1409
|
+
* @public
|
|
1410
|
+
*/
|
|
1411
|
+
declare function isFlowError<C extends SekyroFlowErrorCode = SekyroFlowErrorCode>(err: unknown, ...codes: C[]): err is SekyroFlowError<C>;
|
|
1143
1412
|
|
|
1144
1413
|
/**
|
|
1145
1414
|
* The raw ANRPTS `getPersonne` answer your server received with your own
|
|
@@ -1252,4 +1521,4 @@ interface VerifyWebhookOptions {
|
|
|
1252
1521
|
*/
|
|
1253
1522
|
declare function verifyWebhook(rawBody: string, header: string | null | undefined, secret: string, opts?: VerifyWebhookOptions): WebhookEnvelope;
|
|
1254
1523
|
|
|
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
|
|
1524
|
+
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 SubjectReuseDocument, 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 };
|