@arkyc/types 1.2.11 → 2.1.0
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/dist/access.d.mts +12 -14
- package/dist/access.d.mts.map +1 -1
- package/dist/audit.d.mts +2 -4
- package/dist/audit.d.mts.map +1 -1
- package/dist/common.d.mts +8 -9
- package/dist/common.d.mts.map +1 -1
- package/dist/errors.d.mts +1 -2
- package/dist/errors.d.mts.map +1 -1
- package/dist/index.d.mts +8 -6
- package/dist/index.mjs +6 -3
- package/dist/notifications.d.mts +41 -0
- package/dist/notifications.d.mts.map +1 -0
- package/dist/notifications.mjs +21 -0
- package/dist/notifications.mjs.map +1 -0
- package/dist/organization.d.mts +9 -8
- package/dist/organization.d.mts.map +1 -1
- package/dist/project.d.mts +22 -14
- package/dist/project.d.mts.map +1 -1
- package/dist/project.mjs +13 -0
- package/dist/project.mjs.map +1 -0
- package/dist/providers.d.mts +17 -18
- package/dist/providers.d.mts.map +1 -1
- package/dist/rbac.d.mts +13 -15
- package/dist/rbac.d.mts.map +1 -1
- package/dist/realtime.d.mts +20 -27
- package/dist/realtime.d.mts.map +1 -1
- package/dist/realtime.mjs +11 -29
- package/dist/realtime.mjs.map +1 -1
- package/dist/review.d.mts +3 -5
- package/dist/review.d.mts.map +1 -1
- package/dist/risk.d.mts +99 -0
- package/dist/risk.d.mts.map +1 -0
- package/dist/risk.mjs +53 -0
- package/dist/risk.mjs.map +1 -0
- package/dist/sdk.d.mts +3 -5
- package/dist/sdk.d.mts.map +1 -1
- package/dist/settings.d.mts +6 -19
- package/dist/settings.d.mts.map +1 -1
- package/dist/settings.mjs +0 -1
- package/dist/settings.mjs.map +1 -1
- package/dist/user.d.mts +2 -4
- package/dist/user.d.mts.map +1 -1
- package/dist/verification.d.mts +6 -8
- package/dist/verification.d.mts.map +1 -1
- package/dist/webhook.d.mts +18 -11
- package/dist/webhook.d.mts.map +1 -1
- package/dist/widget.d.mts +4 -6
- package/dist/widget.d.mts.map +1 -1
- package/dist/workflow.d.mts +30 -22
- package/dist/workflow.d.mts.map +1 -1
- package/dist/workflow.mjs +17 -2
- package/dist/workflow.mjs.map +1 -1
- package/package.json +1 -1
package/dist/providers.d.mts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { Entity, Id, IsoDate, ProjectScoped } from "./common.mjs";
|
|
2
2
|
import { AddressMethod } from "./workflow.mjs";
|
|
3
|
-
|
|
4
3
|
//#region src/providers.d.ts
|
|
5
4
|
/** Supported identity document categories. */
|
|
6
|
-
type DocumentType = 'passport' | 'id_card' | 'drivers_license' | 'residence_permit';
|
|
5
|
+
export type DocumentType = 'passport' | 'id_card' | 'drivers_license' | 'residence_permit';
|
|
7
6
|
/** Structured identity fields extracted from a document via OCR. */
|
|
8
|
-
interface OcrFields {
|
|
7
|
+
export interface OcrFields {
|
|
9
8
|
firstName?: string;
|
|
10
9
|
lastName?: string;
|
|
11
10
|
fullName?: string;
|
|
12
11
|
dateOfBirth?: IsoDate;
|
|
13
12
|
documentNumber?: string;
|
|
14
13
|
expiryDate?: IsoDate;
|
|
14
|
+
issueDate?: IsoDate;
|
|
15
15
|
nationality?: string;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
@@ -19,7 +19,7 @@ interface OcrFields {
|
|
|
19
19
|
* (the `ai` vision driver). Advisory anti-spoofing signals — a flagged document
|
|
20
20
|
* is routed to manual review, never auto-rejected on the model's say-so.
|
|
21
21
|
*/
|
|
22
|
-
interface OcrAuthenticity {
|
|
22
|
+
export interface OcrAuthenticity {
|
|
23
23
|
/** False when any tamper/replay signal fired. */
|
|
24
24
|
genuine: boolean;
|
|
25
25
|
/** Model's authenticity confidence in [0, 1]: 1 = clearly an original, 0 = clearly fake/replayed. */
|
|
@@ -36,7 +36,7 @@ interface OcrAuthenticity {
|
|
|
36
36
|
observations: string[];
|
|
37
37
|
}
|
|
38
38
|
/** The shape returned by any OCR driver. */
|
|
39
|
-
interface OcrResultData {
|
|
39
|
+
export interface OcrResultData {
|
|
40
40
|
fields: OcrFields;
|
|
41
41
|
/** Overall extraction confidence in [0, 1]. */
|
|
42
42
|
confidence: number;
|
|
@@ -46,7 +46,7 @@ interface OcrResultData {
|
|
|
46
46
|
raw?: unknown;
|
|
47
47
|
}
|
|
48
48
|
/** Anti-spoofing signals surfaced by a liveness driver. */
|
|
49
|
-
interface SpoofSignals {
|
|
49
|
+
export interface SpoofSignals {
|
|
50
50
|
screenReplay?: boolean;
|
|
51
51
|
printedPhoto?: boolean;
|
|
52
52
|
maskDetected?: boolean;
|
|
@@ -55,7 +55,7 @@ interface SpoofSignals {
|
|
|
55
55
|
poorLighting?: boolean;
|
|
56
56
|
}
|
|
57
57
|
/** The shape returned by any passive-liveness driver. */
|
|
58
|
-
interface LivenessResultData {
|
|
58
|
+
export interface LivenessResultData {
|
|
59
59
|
passed: boolean;
|
|
60
60
|
/** Liveness confidence in [0, 1]. */
|
|
61
61
|
score: number;
|
|
@@ -63,7 +63,7 @@ interface LivenessResultData {
|
|
|
63
63
|
raw?: unknown;
|
|
64
64
|
}
|
|
65
65
|
/** The shape returned by any face-match driver. */
|
|
66
|
-
interface FaceMatchResultData {
|
|
66
|
+
export interface FaceMatchResultData {
|
|
67
67
|
passed: boolean;
|
|
68
68
|
/** Similarity between document portrait and selfie in [0, 1]. */
|
|
69
69
|
similarityScore: number;
|
|
@@ -72,7 +72,7 @@ interface FaceMatchResultData {
|
|
|
72
72
|
raw?: unknown;
|
|
73
73
|
}
|
|
74
74
|
/** A normalized postal address. Any field may be absent depending on the source. */
|
|
75
|
-
interface PostalAddress {
|
|
75
|
+
export interface PostalAddress {
|
|
76
76
|
line1?: string;
|
|
77
77
|
line2?: string;
|
|
78
78
|
city?: string;
|
|
@@ -86,7 +86,7 @@ interface PostalAddress {
|
|
|
86
86
|
longitude?: number;
|
|
87
87
|
}
|
|
88
88
|
/** One method's contribution to address verification. */
|
|
89
|
-
interface AddressMethodResult {
|
|
89
|
+
export interface AddressMethodResult {
|
|
90
90
|
method: AddressMethod;
|
|
91
91
|
/** Whether this method produced a usable, valid result. */
|
|
92
92
|
passed: boolean;
|
|
@@ -105,7 +105,7 @@ interface AddressMethodResult {
|
|
|
105
105
|
raw?: unknown;
|
|
106
106
|
}
|
|
107
107
|
/** The shape returned by an address verifier — the aggregate of its methods. */
|
|
108
|
-
interface AddressResultData {
|
|
108
|
+
export interface AddressResultData {
|
|
109
109
|
passed: boolean;
|
|
110
110
|
/** Overall confidence in [0, 1]. */
|
|
111
111
|
score: number;
|
|
@@ -116,7 +116,7 @@ interface AddressResultData {
|
|
|
116
116
|
raw?: unknown;
|
|
117
117
|
}
|
|
118
118
|
/** A captured identity document (front and optional back) for a session. */
|
|
119
|
-
interface DocumentCapture extends Entity, ProjectScoped {
|
|
119
|
+
export interface DocumentCapture extends Entity, ProjectScoped {
|
|
120
120
|
session_id: Id;
|
|
121
121
|
country: string | null;
|
|
122
122
|
document_type: DocumentType | null;
|
|
@@ -125,7 +125,7 @@ interface DocumentCapture extends Entity, ProjectScoped {
|
|
|
125
125
|
quality_score: number | null;
|
|
126
126
|
}
|
|
127
127
|
/** Persisted OCR output for a document capture. */
|
|
128
|
-
interface OcrResult extends Entity, ProjectScoped {
|
|
128
|
+
export interface OcrResult extends Entity, ProjectScoped {
|
|
129
129
|
session_id: Id;
|
|
130
130
|
document_capture_id: Id;
|
|
131
131
|
fields: OcrFields;
|
|
@@ -133,14 +133,14 @@ interface OcrResult extends Entity, ProjectScoped {
|
|
|
133
133
|
raw_response: unknown;
|
|
134
134
|
}
|
|
135
135
|
/** The portrait region extracted from a document, used for face matching. */
|
|
136
|
-
interface DocumentPortrait extends Entity, ProjectScoped {
|
|
136
|
+
export interface DocumentPortrait extends Entity, ProjectScoped {
|
|
137
137
|
session_id: Id;
|
|
138
138
|
document_capture_id: Id;
|
|
139
139
|
portrait_image_path: string;
|
|
140
140
|
detection_confidence: number;
|
|
141
141
|
}
|
|
142
142
|
/** Persisted passive-liveness result for a session. */
|
|
143
|
-
interface LivenessCheck extends Entity, ProjectScoped {
|
|
143
|
+
export interface LivenessCheck extends Entity, ProjectScoped {
|
|
144
144
|
session_id: Id;
|
|
145
145
|
selfie_image_path: string | null;
|
|
146
146
|
video_path: string | null;
|
|
@@ -151,7 +151,7 @@ interface LivenessCheck extends Entity, ProjectScoped {
|
|
|
151
151
|
raw_response: unknown;
|
|
152
152
|
}
|
|
153
153
|
/** Persisted face-match result comparing document portrait to selfie. */
|
|
154
|
-
interface FaceMatchCheck extends Entity, ProjectScoped {
|
|
154
|
+
export interface FaceMatchCheck extends Entity, ProjectScoped {
|
|
155
155
|
session_id: Id;
|
|
156
156
|
id_portrait_image_path: string | null;
|
|
157
157
|
selfie_image_path: string | null;
|
|
@@ -162,7 +162,7 @@ interface FaceMatchCheck extends Entity, ProjectScoped {
|
|
|
162
162
|
raw_response: unknown;
|
|
163
163
|
}
|
|
164
164
|
/** Persisted address-verification result for a session. */
|
|
165
|
-
interface AddressVerification extends Entity, ProjectScoped {
|
|
165
|
+
export interface AddressVerification extends Entity, ProjectScoped {
|
|
166
166
|
session_id: Id;
|
|
167
167
|
/** The address the user claimed (typed in the widget), when provided. */
|
|
168
168
|
claimed_address: PostalAddress | null;
|
|
@@ -180,5 +180,4 @@ interface AddressVerification extends Entity, ProjectScoped {
|
|
|
180
180
|
raw_response: unknown;
|
|
181
181
|
}
|
|
182
182
|
//#endregion
|
|
183
|
-
export { AddressMethodResult, AddressResultData, AddressVerification, DocumentCapture, DocumentPortrait, DocumentType, FaceMatchCheck, FaceMatchResultData, LivenessCheck, LivenessResultData, OcrAuthenticity, OcrFields, OcrResult, OcrResultData, PostalAddress, SpoofSignals };
|
|
184
183
|
//# sourceMappingURL=providers.d.mts.map
|
package/dist/providers.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providers.d.mts","names":[],"sources":["../src/providers.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"providers.d.mts","names":[],"sources":["../src/providers.ts"],"mappings":";;;;YAIY;;iBAGK;EACf;EACA;EACA;EACA,cAAc;EACd;EACA,aAAa;EACb,YAAY;EACZ;;;;;;;iBAQe;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;;iBAIe;EACf,QAAQ;;EAER;;EAEA,eAAe;;EAEf;;;iBAIe;EACf;EACA;EACA;EACA;EACA;EACA;;;iBAIe;EACf;;EAEA;EACA,cAAc;EACd;;;iBAIe;EACf;;EAEA;;EAEA;EACA;;;iBAIe;EACf;EACA;EACA;;EAEA;EACA;;EAEA;;EAEA;EACA;;;iBAIe;EACf,QAAQ;;EAER;;EAEA;;EAEA,WAAW;;;;;;EAMX;;EAEA;EACA;;;iBAIe;EACf;;EAEA;;EAEA,SAAS;;EAET;EACA;;;iBAIe,wBAAwB,QAAQ;EAC/C,YAAY;EACZ;EACA,eAAe;EACf;EACA;EACA;;;iBAIe,kBAAkB,QAAQ;EACzC,YAAY;EACZ,qBAAqB;EACrB,QAAQ;EACR;EACA;;;iBAIe,yBAAyB,QAAQ;EAChD,YAAY;EACZ,qBAAqB;EACrB;EACA;;;iBAIe,sBAAsB,QAAQ;EAC7C,YAAY;EACZ;EACA;EACA;EACA;EACA,eAAe;EACf;EACA;;;iBAIe,uBAAuB,QAAQ;EAC9C,YAAY;EACZ;EACA;EACA;EACA;EACA;EACA;EACA;;;iBAIe,4BAA4B,QAAQ;EACnD,YAAY;;EAEZ,iBAAiB;;EAEjB;;EAEA;EACA;EACA;;EAEA;;EAEA,SAAS;EACT;EACA"}
|
package/dist/rbac.d.mts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Entity, Id, OrganizationScoped } from "./common.mjs";
|
|
2
|
-
|
|
3
2
|
//#region src/rbac.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* The full catalogue of permission strings recognised by Arkyc.
|
|
@@ -8,27 +7,27 @@ import { Entity, Id, OrganizationScoped } from "./common.mjs";
|
|
|
8
7
|
* a user is the union of their role permissions and any directly-assigned
|
|
9
8
|
* permissions (see `@arkyc/permissions`).
|
|
10
9
|
*/
|
|
11
|
-
type PermissionKey = 'organizations.view' | 'organizations.update' | 'organizations.delete' | 'members.view' | 'members.invite' | 'members.update' | 'members.remove' | 'projects.view' | 'projects.create' | 'projects.update' | 'projects.delete' | 'api_keys.view' | 'api_keys.create' | 'api_keys.revoke' | 'webhooks.view' | 'webhooks.create' | 'webhooks.update' | 'webhooks.delete' | 'webhooks.test' | 'workflows.view' | 'workflows.create' | 'workflows.update' | 'workflows.delete' | 'sessions.view' | 'sessions.create' | 'sessions.cancel' | 'sessions.retry' | 'sessions.export' | 'reviews.view' | 'reviews.assign' | 'reviews.approve' | 'reviews.reject' | 'reviews.request_retry' | 'reviews.note' | 'audit_logs.view' | 'settings.view' | 'settings.update' | 'billing.view' | 'billing.update';
|
|
10
|
+
export type PermissionKey = 'organizations.view' | 'organizations.update' | 'organizations.delete' | 'members.view' | 'members.invite' | 'members.update' | 'members.remove' | 'projects.view' | 'projects.create' | 'projects.update' | 'projects.delete' | 'api_keys.view' | 'api_keys.create' | 'api_keys.revoke' | 'webhooks.view' | 'webhooks.create' | 'webhooks.update' | 'webhooks.delete' | 'webhooks.test' | 'workflows.view' | 'workflows.create' | 'workflows.update' | 'workflows.delete' | 'sessions.view' | 'sessions.create' | 'sessions.cancel' | 'sessions.retry' | 'sessions.export' | 'reviews.view' | 'reviews.assign' | 'reviews.approve' | 'reviews.reject' | 'reviews.request_retry' | 'reviews.note' | 'audit_logs.view' | 'settings.view' | 'settings.update' | 'billing.view' | 'billing.update';
|
|
12
11
|
/** The domain groups permissions are organised under. */
|
|
13
|
-
type PermissionGroup = 'organizations' | 'members' | 'projects' | 'api_keys' | 'webhooks' | 'workflows' | 'sessions' | 'reviews' | 'audit_logs' | 'settings' | 'billing';
|
|
12
|
+
export type PermissionGroup = 'organizations' | 'members' | 'projects' | 'api_keys' | 'webhooks' | 'workflows' | 'sessions' | 'reviews' | 'audit_logs' | 'settings' | 'billing';
|
|
14
13
|
/** The built-in system roles seeded for every organization. */
|
|
15
|
-
type SystemRoleSlug = 'owner' | 'admin' | 'reviewer' | 'developer' | 'readonly';
|
|
14
|
+
export type SystemRoleSlug = 'owner' | 'admin' | 'reviewer' | 'developer' | 'readonly';
|
|
16
15
|
/**
|
|
17
16
|
* Platform-scope permission strings, distinct from organization {@link PermissionKey}.
|
|
18
17
|
* These gate the super-admin surface above organizations and are only ever granted
|
|
19
18
|
* through {@link AdminPermission} (never an organization role). Rows carry `admin: true`.
|
|
20
19
|
*/
|
|
21
|
-
type AdminPermissionKey = 'admin.organizations.view' | 'admin.organizations.manage' | 'admin.users.view' | 'admin.users.manage' | 'admin.settings.view' | 'admin.settings.update' | 'admin.audit.view' | 'admin.billing.view' | 'admin.billing.update' | 'admin.extended_access.view' | 'admin.extended_access.manage';
|
|
20
|
+
export type AdminPermissionKey = 'admin.organizations.view' | 'admin.organizations.manage' | 'admin.users.view' | 'admin.users.manage' | 'admin.settings.view' | 'admin.settings.update' | 'admin.audit.view' | 'admin.billing.view' | 'admin.billing.update' | 'admin.extended_access.view' | 'admin.extended_access.manage';
|
|
22
21
|
/** The domain groups platform-admin permissions are organised under. */
|
|
23
|
-
type AdminPermissionGroup = 'admin.organizations' | 'admin.users' | 'admin.settings' | 'admin.audit' | 'admin.billing' | 'admin.extended_access';
|
|
22
|
+
export type AdminPermissionGroup = 'admin.organizations' | 'admin.users' | 'admin.settings' | 'admin.audit' | 'admin.billing' | 'admin.extended_access';
|
|
24
23
|
/** Any permission string, organization- or platform-scope. */
|
|
25
|
-
type AnyPermissionKey = PermissionKey | AdminPermissionKey;
|
|
24
|
+
export type AnyPermissionKey = PermissionKey | AdminPermissionKey;
|
|
26
25
|
/** Any permission group, organization- or platform-scope. */
|
|
27
|
-
type AnyPermissionGroup = PermissionGroup | AdminPermissionGroup;
|
|
26
|
+
export type AnyPermissionGroup = PermissionGroup | AdminPermissionGroup;
|
|
28
27
|
/** The built-in platform-admin role slug. */
|
|
29
|
-
type AdminRoleSlug = 'platform-owner';
|
|
28
|
+
export type AdminRoleSlug = 'platform-owner';
|
|
30
29
|
/** A permission definition row. Permissions are global (not organization-scoped). */
|
|
31
|
-
interface Permission extends Entity {
|
|
30
|
+
export interface Permission extends Entity {
|
|
32
31
|
/** The permission string, e.g. `sessions.view` or `admin.settings.view`. */
|
|
33
32
|
name: AnyPermissionKey;
|
|
34
33
|
description: string | null;
|
|
@@ -40,7 +39,7 @@ interface Permission extends Entity {
|
|
|
40
39
|
* A role within an organization. System roles (`is_system`) are seeded and cannot be
|
|
41
40
|
* deleted; organizations may also define custom roles.
|
|
42
41
|
*/
|
|
43
|
-
interface Role extends Entity {
|
|
42
|
+
export interface Role extends Entity {
|
|
44
43
|
/** Null for platform-admin roles (`admin: true`); set for organization roles. */
|
|
45
44
|
organization_id: Id | null;
|
|
46
45
|
name: string;
|
|
@@ -51,7 +50,7 @@ interface Role extends Entity {
|
|
|
51
50
|
admin: boolean;
|
|
52
51
|
}
|
|
53
52
|
/** Join row granting a {@link Permission} to a {@link Role}. */
|
|
54
|
-
interface RolePermission extends Entity {
|
|
53
|
+
export interface RolePermission extends Entity {
|
|
55
54
|
role_id: Id;
|
|
56
55
|
permission_id: Id;
|
|
57
56
|
}
|
|
@@ -59,7 +58,7 @@ interface RolePermission extends Entity {
|
|
|
59
58
|
* A permission assigned directly to a user, on top of their role permissions.
|
|
60
59
|
* `project_id` is null for organization-level grants, set for project-level grants.
|
|
61
60
|
*/
|
|
62
|
-
interface UserPermission extends Entity, OrganizationScoped {
|
|
61
|
+
export interface UserPermission extends Entity, OrganizationScoped {
|
|
63
62
|
project_id: Id | null;
|
|
64
63
|
user_id: Id;
|
|
65
64
|
permission_id: Id;
|
|
@@ -70,11 +69,10 @@ interface UserPermission extends Entity, OrganizationScoped {
|
|
|
70
69
|
* permission grant (`permission_id` set). Effective admin access is the union of
|
|
71
70
|
* both, resolved by `@arkyc/permissions`.
|
|
72
71
|
*/
|
|
73
|
-
interface AdminPermission extends Entity {
|
|
72
|
+
export interface AdminPermission extends Entity {
|
|
74
73
|
user_id: Id;
|
|
75
74
|
permission_id: Id | null;
|
|
76
75
|
role_id: Id | null;
|
|
77
76
|
}
|
|
78
77
|
//#endregion
|
|
79
|
-
export { AdminPermission, AdminPermissionGroup, AdminPermissionKey, AdminRoleSlug, AnyPermissionGroup, AnyPermissionKey, Permission, PermissionGroup, PermissionKey, Role, RolePermission, SystemRoleSlug, UserPermission };
|
|
80
78
|
//# sourceMappingURL=rbac.d.mts.map
|
package/dist/rbac.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rbac.d.mts","names":[],"sources":["../src/rbac.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"rbac.d.mts","names":[],"sources":["../src/rbac.ts"],"mappings":";;;;;;;;;YASY;;YA0CA;;YAcA;;;;;;YAOA;;YAcA;;YASA,mBAAmB,gBAAgB;;YAGnC,qBAAqB,kBAAkB;;YAGvC;;iBAGK,mBAAmB;;EAElC,MAAM;EACN;EACA,OAAO;;EAEP;;;;;;iBAOe,aAAa;;EAE5B,iBAAiB;EACjB;EACA;EACA;EACA;;EAEA;;;iBAIe,uBAAuB;EACtC,SAAS;EACT,eAAe;;;;;;iBAOA,uBAAuB,QAAQ;EAC9C,YAAY;EACZ,SAAS;EACT,eAAe;;;;;;;;iBASA,wBAAwB;EACvC,SAAS;EACT,eAAe;EACf,SAAS"}
|
package/dist/realtime.d.mts
CHANGED
|
@@ -1,41 +1,35 @@
|
|
|
1
1
|
import { Id } from "./common.mjs";
|
|
2
2
|
import { VerificationStatus } from "./verification.mjs";
|
|
3
|
-
|
|
4
3
|
//#region src/realtime.d.ts
|
|
5
4
|
/**
|
|
6
|
-
* Realtime
|
|
7
|
-
*
|
|
8
|
-
* channel and event names never drift between them.
|
|
5
|
+
* Realtime contracts shared by the API (server publish) and the dashboard and
|
|
6
|
+
* widget (client subscribe), so channel and event names never drift between them.
|
|
9
7
|
*/
|
|
10
8
|
/** Events the API broadcasts. Clients react by invalidating their caches. */
|
|
11
|
-
declare const REALTIME_EVENT: {
|
|
12
|
-
/** A verification session changed status (the `transitionTo` choke point). */
|
|
9
|
+
export declare const REALTIME_EVENT: {
|
|
10
|
+
/** A verification session changed status (the `transitionTo` choke point). */
|
|
11
|
+
readonly sessionTransition: "session.transition";
|
|
12
|
+
/** A reviewer acted on a session (assign/note/suspicious/decision/retry). */
|
|
13
13
|
readonly reviewAction: "review.action";
|
|
14
14
|
};
|
|
15
|
-
type RealtimeEventName = (typeof REALTIME_EVENT)[keyof typeof REALTIME_EVENT];
|
|
15
|
+
export type RealtimeEventName = (typeof REALTIME_EVENT)[keyof typeof REALTIME_EVENT];
|
|
16
16
|
/**
|
|
17
|
-
* Private channel name builders.
|
|
18
|
-
*
|
|
17
|
+
* Private channel name builders. Every channel is `private-`, so a subscription
|
|
18
|
+
* must be authorized by the API. Segments are dot-separated so the API's channel
|
|
19
|
+
* rules can capture each id.
|
|
19
20
|
*/
|
|
20
|
-
declare const realtimeChannels: {
|
|
21
|
-
/**
|
|
22
|
-
|
|
21
|
+
export declare const realtimeChannels: {
|
|
22
|
+
/** A user's own notifications. */
|
|
23
|
+
user: (userId: Id) => string;
|
|
24
|
+
/** Everything in an organization. */
|
|
25
|
+
organization: (organizationId: Id) => string;
|
|
26
|
+
/** Everything in a project. */
|
|
27
|
+
project: (organizationId: Id, projectId: Id) => string;
|
|
28
|
+
/** A single verification session (used by the widget via client token). */
|
|
23
29
|
session: (sessionId: Id) => string;
|
|
24
30
|
};
|
|
25
|
-
/** Parse a private channel name back into its scope, or null if unrecognized. */
|
|
26
|
-
declare function parseRealtimeChannel(channel: string): {
|
|
27
|
-
kind: 'organization';
|
|
28
|
-
organizationId: string;
|
|
29
|
-
} | {
|
|
30
|
-
kind: 'project';
|
|
31
|
-
organizationId: string;
|
|
32
|
-
projectId: string;
|
|
33
|
-
} | {
|
|
34
|
-
kind: 'session';
|
|
35
|
-
sessionId: string;
|
|
36
|
-
} | null;
|
|
37
31
|
/** Payload for {@link REALTIME_EVENT.sessionTransition}. */
|
|
38
|
-
interface SessionTransitionEvent {
|
|
32
|
+
export interface SessionTransitionEvent {
|
|
39
33
|
session_id: Id;
|
|
40
34
|
organization_id: Id;
|
|
41
35
|
project_id: Id | null;
|
|
@@ -43,7 +37,7 @@ interface SessionTransitionEvent {
|
|
|
43
37
|
previous_status: VerificationStatus | null;
|
|
44
38
|
}
|
|
45
39
|
/** Payload for {@link REALTIME_EVENT.reviewAction}. */
|
|
46
|
-
interface ReviewActionEvent {
|
|
40
|
+
export interface ReviewActionEvent {
|
|
47
41
|
session_id: Id;
|
|
48
42
|
organization_id: Id;
|
|
49
43
|
project_id: Id | null;
|
|
@@ -52,5 +46,4 @@ interface ReviewActionEvent {
|
|
|
52
46
|
actor_id: Id | null;
|
|
53
47
|
}
|
|
54
48
|
//#endregion
|
|
55
|
-
export { REALTIME_EVENT, RealtimeEventName, ReviewActionEvent, SessionTransitionEvent, parseRealtimeChannel, realtimeChannels };
|
|
56
49
|
//# sourceMappingURL=realtime.d.mts.map
|
package/dist/realtime.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realtime.d.mts","names":[],"sources":["../src/realtime.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"realtime.d.mts","names":[],"sources":["../src/realtime.ts"],"mappings":";;;;;;;;qBASa;;WAAA;;WAAA;;YAOD,4BAA4B,6BAA6B;;;;;;qBAOxD;;EAEI,OAAA,QAAA;;EAEgB,eAAA,gBAAA;;EAEL,UAAA,gBAAA,IAAE,WAAa;;EAEpB,UAAA,WAAA;;;iBAIN;EACf,YAAY;EACZ,iBAAiB;EACjB,YAAY;EACZ,QAAQ;EACR,iBAAiB;;;iBAIF;EACf,YAAY;EACZ,iBAAiB;EACjB,YAAY;;EAEZ;EACA,UAAU"}
|
package/dist/realtime.mjs
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
//#region src/realtime.ts
|
|
2
2
|
/**
|
|
3
|
-
* Realtime
|
|
4
|
-
*
|
|
5
|
-
* channel and event names never drift between them.
|
|
3
|
+
* Realtime contracts shared by the API (server publish) and the dashboard and
|
|
4
|
+
* widget (client subscribe), so channel and event names never drift between them.
|
|
6
5
|
*/
|
|
7
6
|
/** Events the API broadcasts. Clients react by invalidating their caches. */
|
|
8
7
|
const REALTIME_EVENT = {
|
|
@@ -12,38 +11,21 @@ const REALTIME_EVENT = {
|
|
|
12
11
|
reviewAction: "review.action"
|
|
13
12
|
};
|
|
14
13
|
/**
|
|
15
|
-
* Private channel name builders.
|
|
16
|
-
*
|
|
14
|
+
* Private channel name builders. Every channel is `private-`, so a subscription
|
|
15
|
+
* must be authorized by the API. Segments are dot-separated so the API's channel
|
|
16
|
+
* rules can capture each id.
|
|
17
17
|
*/
|
|
18
18
|
const realtimeChannels = {
|
|
19
|
+
/** A user's own notifications. */
|
|
20
|
+
user: (userId) => `private-user.${userId}`,
|
|
19
21
|
/** Everything in an organization. */
|
|
20
|
-
organization: (organizationId) => `private-organization
|
|
22
|
+
organization: (organizationId) => `private-organization.${organizationId}`,
|
|
21
23
|
/** Everything in a project. */
|
|
22
|
-
project: (organizationId, projectId) => `private-organization
|
|
24
|
+
project: (organizationId, projectId) => `private-organization.${organizationId}.project.${projectId}`,
|
|
23
25
|
/** A single verification session (used by the widget via client token). */
|
|
24
|
-
session: (sessionId) => `private-session
|
|
26
|
+
session: (sessionId) => `private-session.${sessionId}`
|
|
25
27
|
};
|
|
26
|
-
/** Parse a private channel name back into its scope, or null if unrecognized. */
|
|
27
|
-
function parseRealtimeChannel(channel) {
|
|
28
|
-
const project = /^private-organization-(.+)-project-(.+)$/.exec(channel);
|
|
29
|
-
if (project) return {
|
|
30
|
-
kind: "project",
|
|
31
|
-
organizationId: project[1],
|
|
32
|
-
projectId: project[2]
|
|
33
|
-
};
|
|
34
|
-
const organization = /^private-organization-(.+)$/.exec(channel);
|
|
35
|
-
if (organization) return {
|
|
36
|
-
kind: "organization",
|
|
37
|
-
organizationId: organization[1]
|
|
38
|
-
};
|
|
39
|
-
const session = /^private-session-(.+)$/.exec(channel);
|
|
40
|
-
if (session) return {
|
|
41
|
-
kind: "session",
|
|
42
|
-
sessionId: session[1]
|
|
43
|
-
};
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
28
|
//#endregion
|
|
47
|
-
export { REALTIME_EVENT,
|
|
29
|
+
export { REALTIME_EVENT, realtimeChannels };
|
|
48
30
|
|
|
49
31
|
//# sourceMappingURL=realtime.mjs.map
|
package/dist/realtime.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realtime.mjs","names":[],"sources":["../src/realtime.ts"],"sourcesContent":["import type { Id } from './common'\nimport type { VerificationStatus } from './verification'\n\n/**\n * Realtime
|
|
1
|
+
{"version":3,"file":"realtime.mjs","names":[],"sources":["../src/realtime.ts"],"sourcesContent":["import type { Id } from './common'\nimport type { VerificationStatus } from './verification'\n\n/**\n * Realtime contracts shared by the API (server publish) and the dashboard and\n * widget (client subscribe), so channel and event names never drift between them.\n */\n\n/** Events the API broadcasts. Clients react by invalidating their caches. */\nexport const REALTIME_EVENT = {\n /** A verification session changed status (the `transitionTo` choke point). */\n sessionTransition: 'session.transition',\n /** A reviewer acted on a session (assign/note/suspicious/decision/retry). */\n reviewAction: 'review.action',\n} as const\n\nexport type RealtimeEventName = (typeof REALTIME_EVENT)[keyof typeof REALTIME_EVENT]\n\n/**\n * Private channel name builders. Every channel is `private-`, so a subscription\n * must be authorized by the API. Segments are dot-separated so the API's channel\n * rules can capture each id.\n */\nexport const realtimeChannels = {\n /** A user's own notifications. */\n user: (userId: Id): string => `private-user.${userId}`,\n /** Everything in an organization. */\n organization: (organizationId: Id): string => `private-organization.${organizationId}`,\n /** Everything in a project. */\n project: (organizationId: Id, projectId: Id): string => `private-organization.${organizationId}.project.${projectId}`,\n /** A single verification session (used by the widget via client token). */\n session: (sessionId: Id): string => `private-session.${sessionId}`,\n}\n\n/** Payload for {@link REALTIME_EVENT.sessionTransition}. */\nexport interface SessionTransitionEvent {\n session_id: Id\n organization_id: Id\n project_id: Id | null\n status: VerificationStatus\n previous_status: VerificationStatus | null\n}\n\n/** Payload for {@link REALTIME_EVENT.reviewAction}. */\nexport interface ReviewActionEvent {\n session_id: Id\n organization_id: Id\n project_id: Id | null\n /** The audit action, e.g. `review.assigned`, `review.note`, `review.approved`. */\n action: string\n actor_id: Id | null\n}\n"],"mappings":";;;;;;AASA,MAAa,iBAAiB;;CAE5B,mBAAmB;;CAEnB,cAAc;AAChB;;;;;;AASA,MAAa,mBAAmB;;CAE9B,OAAO,WAAuB,gBAAgB;;CAE9C,eAAe,mBAA+B,wBAAwB;;CAEtE,UAAU,gBAAoB,cAA0B,wBAAwB,eAAe,WAAW;;CAE1G,UAAU,cAA0B,mBAAmB;AACzD"}
|
package/dist/review.d.mts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { Entity, Id, ProjectScoped } from "./common.mjs";
|
|
2
2
|
import { VerificationStatus } from "./verification.mjs";
|
|
3
|
-
|
|
4
3
|
//#region src/review.d.ts
|
|
5
4
|
/** Actions a human reviewer can take on a session. */
|
|
6
|
-
type ReviewAction = 'approve' | 'reject' | 'request_document_retry' | 'request_selfie_retry' | 'request_full_retry' | 'mark_suspicious' | 'note';
|
|
5
|
+
export type ReviewAction = 'approve' | 'reject' | 'request_document_retry' | 'request_selfie_retry' | 'request_full_retry' | 'mark_suspicious' | 'note';
|
|
7
6
|
/**
|
|
8
7
|
* An audited review action recording a status transition performed by a
|
|
9
8
|
* reviewer (or the system) on a session.
|
|
10
9
|
*/
|
|
11
|
-
interface Review extends Entity, ProjectScoped {
|
|
10
|
+
export interface Review extends Entity, ProjectScoped {
|
|
12
11
|
session_id: Id;
|
|
13
12
|
reviewer_id: Id | null;
|
|
14
13
|
previous_status: VerificationStatus;
|
|
@@ -17,11 +16,10 @@ interface Review extends Entity, ProjectScoped {
|
|
|
17
16
|
note: string | null;
|
|
18
17
|
}
|
|
19
18
|
/** A free-standing reviewer note attached to a session. */
|
|
20
|
-
interface ReviewNote extends Entity, ProjectScoped {
|
|
19
|
+
export interface ReviewNote extends Entity, ProjectScoped {
|
|
21
20
|
session_id: Id;
|
|
22
21
|
reviewer_id: Id;
|
|
23
22
|
note: string;
|
|
24
23
|
}
|
|
25
24
|
//#endregion
|
|
26
|
-
export { Review, ReviewAction, ReviewNote };
|
|
27
25
|
//# sourceMappingURL=review.d.mts.map
|
package/dist/review.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review.d.mts","names":[],"sources":["../src/review.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"review.d.mts","names":[],"sources":["../src/review.ts"],"mappings":";;;;YAIY;;;;;iBAaK,eAAe,QAAQ;EACtC,YAAY;EACZ,aAAa;EACb,iBAAiB;EACjB,YAAY;EACZ;EACA;;;iBAIe,mBAAmB,QAAQ;EAC1C,YAAY;EACZ,aAAa;EACb"}
|
package/dist/risk.d.mts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Id, IsoDateTime } from "./common.mjs";
|
|
2
|
+
import { DecisionReason } from "./verification.mjs";
|
|
3
|
+
//#region src/risk.d.ts
|
|
4
|
+
/** A fraud or compliance signal a detector can raise against a session. */
|
|
5
|
+
export type RiskSignalKey = 'duplicate_document' | 'duplicate_identity' | 'duplicate_face' | 'document_tampering' | 'document_inconsistent' | 'sanctions_match' | 'pep_match' | 'adverse_media' | 'high_risk_network' | 'ip_country_mismatch' | 'velocity_exceeded' | 'underage';
|
|
6
|
+
/** Every signal key, in decision precedence order (most severe first). */
|
|
7
|
+
export declare const RISK_SIGNAL_KEYS: readonly RiskSignalKey[];
|
|
8
|
+
/** What a signal does to the decision: nothing (`info`), manual review, or rejection. */
|
|
9
|
+
export type RiskSeverity = 'info' | 'review' | 'reject';
|
|
10
|
+
/** How a workflow treats a signal key. */
|
|
11
|
+
export type RiskSignalPolicy = 'ignore' | 'review' | 'reject';
|
|
12
|
+
/** Per-key policy overrides. Keys left out use {@link DEFAULT_RISK_SIGNAL_POLICY}. */
|
|
13
|
+
export type RiskPolicyConfig = Partial<Record<RiskSignalKey, RiskSignalPolicy>>;
|
|
14
|
+
/** Signals route to review unless an organization opts a key into `ignore` or `reject`. */
|
|
15
|
+
export declare const DEFAULT_RISK_SIGNAL_POLICY: RiskSignalPolicy;
|
|
16
|
+
/** Signals that never reject, whatever the policy says: their evidence is too soft. */
|
|
17
|
+
export declare const REVIEW_ONLY_RISK_SIGNALS: readonly RiskSignalKey[];
|
|
18
|
+
/** The decision reason each signal key reports when it decides a session. */
|
|
19
|
+
export declare const RISK_SIGNAL_REASONS: Record<RiskSignalKey, DecisionReason>;
|
|
20
|
+
/** A signal raised by a detector, before it is stored. */
|
|
21
|
+
export interface RiskSignal {
|
|
22
|
+
key: RiskSignalKey;
|
|
23
|
+
severity: RiskSeverity;
|
|
24
|
+
/** How much the signal adds to the session's risk score, in [0, 1]. */
|
|
25
|
+
score: number;
|
|
26
|
+
/** Advisory signals (model opinions) are capped at review. */
|
|
27
|
+
advisory?: boolean;
|
|
28
|
+
/** Detector-specific facts that justify the signal. */
|
|
29
|
+
evidence: Record<string, unknown>;
|
|
30
|
+
}
|
|
31
|
+
/** A stored risk signal, as the dashboard API returns it. */
|
|
32
|
+
export interface SessionRiskSignal extends RiskSignal {
|
|
33
|
+
id: Id;
|
|
34
|
+
session_id: Id;
|
|
35
|
+
/** Which detector raised it. */
|
|
36
|
+
source: string;
|
|
37
|
+
cleared_at: IsoDateTime | null;
|
|
38
|
+
cleared_by: Id | null;
|
|
39
|
+
clear_reason: string | null;
|
|
40
|
+
created_at: IsoDateTime;
|
|
41
|
+
}
|
|
42
|
+
/** The risk block of a webhook payload. */
|
|
43
|
+
export interface WebhookRiskCheck {
|
|
44
|
+
score: number | null;
|
|
45
|
+
signals: Array<{
|
|
46
|
+
key: RiskSignalKey;
|
|
47
|
+
severity: RiskSeverity;
|
|
48
|
+
cleared: boolean;
|
|
49
|
+
}>;
|
|
50
|
+
}
|
|
51
|
+
/** A category of screening hit. */
|
|
52
|
+
export type ScreeningHitCategory = 'sanction' | 'pep' | 'adverse_media' | 'other';
|
|
53
|
+
/** One watchlist entity a screened identity matched. */
|
|
54
|
+
export interface ScreeningHit {
|
|
55
|
+
/** Provider entity id, stable across re-screens. */
|
|
56
|
+
entity_id: string;
|
|
57
|
+
name: string;
|
|
58
|
+
/** Match score in [0, 1]. */
|
|
59
|
+
score: number;
|
|
60
|
+
category: ScreeningHitCategory;
|
|
61
|
+
/** Provider topic tags, e.g. `sanction`, `role.pep`. */
|
|
62
|
+
topics: string[];
|
|
63
|
+
/** Source lists the entity appears on. */
|
|
64
|
+
datasets: string[];
|
|
65
|
+
birth_dates: string[];
|
|
66
|
+
countries: string[];
|
|
67
|
+
/** A page describing the entity, when the provider has one. */
|
|
68
|
+
url?: string;
|
|
69
|
+
}
|
|
70
|
+
/** What a screening hit does to the session. */
|
|
71
|
+
export type ScreeningOnHit = 'review' | 'reject';
|
|
72
|
+
/** Configuration for the `screening` workflow stage. */
|
|
73
|
+
export interface ScreeningStepConfig {
|
|
74
|
+
/** Minimum match score in [0, 1] that counts as a hit. */
|
|
75
|
+
threshold: number;
|
|
76
|
+
/** What a sanctions hit does. PEP and adverse media hits follow the workflow's risk policy. */
|
|
77
|
+
on_hit: ScreeningOnHit;
|
|
78
|
+
/** Re-screen the identity on a schedule after the session completes. */
|
|
79
|
+
monitor: boolean;
|
|
80
|
+
}
|
|
81
|
+
/** The default screening config applied when the stage is enabled without one. */
|
|
82
|
+
export declare const DEFAULT_SCREENING_CONFIG: ScreeningStepConfig;
|
|
83
|
+
/** Project limits for repeat sessions from one network address. */
|
|
84
|
+
export interface VelocitySettings {
|
|
85
|
+
/** Sessions from one IP, under different user references, before the signal fires. */
|
|
86
|
+
max_sessions: number;
|
|
87
|
+
/** The look-back window in minutes. */
|
|
88
|
+
window_minutes: number;
|
|
89
|
+
}
|
|
90
|
+
export declare const DEFAULT_VELOCITY_SETTINGS: VelocitySettings;
|
|
91
|
+
/** Organization-level opt-in for storing face embeddings. Off by default. */
|
|
92
|
+
export interface FaceEmbeddingSettings {
|
|
93
|
+
enabled: boolean;
|
|
94
|
+
/** Days to keep an embedding before it is deleted. */
|
|
95
|
+
retention_days: number;
|
|
96
|
+
}
|
|
97
|
+
export declare const DEFAULT_FACE_EMBEDDING_SETTINGS: FaceEmbeddingSettings;
|
|
98
|
+
//#endregion
|
|
99
|
+
//# sourceMappingURL=risk.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk.d.mts","names":[],"sources":["../src/risk.ts"],"mappings":";;;;YAIY;;qBAeC,2BAA2B;;YAgB5B;;YAGA;;YAGA,mBAAmB,QAAQ,OAAO,eAAe;;qBAGhD,4BAA4B;;qBAG5B,mCAAmC;;qBAGnC,qBAAqB,OAAO,eAAe;;iBAgBvC;EACf,KAAK;EACL,UAAU;;EAEV;;EAEA;;EAEA,UAAU;;;iBAIK,0BAA0B;EACzC,IAAI;EACJ,YAAY;;EAEZ;EACA,YAAY;EACZ,YAAY;EACZ;EACA,YAAY;;;iBAIG;EACf;EACA,SAAS;IACP,KAAK;IACL,UAAU;IACV;;;;YAKQ;;iBAGK;;EAEf;EACA;;EAEA;EACA,UAAU;;EAEV;;EAEA;EACA;EACA;;EAEA;;;YAIU;;iBAGK;;EAEf;;EAEA,QAAQ;;EAER;;;qBAIW,0BAA0B;;iBAOtB;;EAEf;;EAEA;;qBAGW,2BAA2B;;iBAMvB;EACf;;EAEA;;qBAGW,iCAAiC"}
|
package/dist/risk.mjs
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//#region src/risk.ts
|
|
2
|
+
/** Every signal key, in decision precedence order (most severe first). */
|
|
3
|
+
const RISK_SIGNAL_KEYS = [
|
|
4
|
+
"sanctions_match",
|
|
5
|
+
"underage",
|
|
6
|
+
"duplicate_document",
|
|
7
|
+
"duplicate_face",
|
|
8
|
+
"document_tampering",
|
|
9
|
+
"document_inconsistent",
|
|
10
|
+
"pep_match",
|
|
11
|
+
"adverse_media",
|
|
12
|
+
"duplicate_identity",
|
|
13
|
+
"high_risk_network",
|
|
14
|
+
"ip_country_mismatch",
|
|
15
|
+
"velocity_exceeded"
|
|
16
|
+
];
|
|
17
|
+
/** Signals route to review unless an organization opts a key into `ignore` or `reject`. */
|
|
18
|
+
const DEFAULT_RISK_SIGNAL_POLICY = "review";
|
|
19
|
+
/** Signals that never reject, whatever the policy says: their evidence is too soft. */
|
|
20
|
+
const REVIEW_ONLY_RISK_SIGNALS = ["duplicate_identity", "ip_country_mismatch"];
|
|
21
|
+
/** The decision reason each signal key reports when it decides a session. */
|
|
22
|
+
const RISK_SIGNAL_REASONS = {
|
|
23
|
+
duplicate_document: "DUPLICATE_DOCUMENT",
|
|
24
|
+
duplicate_identity: "DUPLICATE_IDENTITY",
|
|
25
|
+
duplicate_face: "DUPLICATE_FACE",
|
|
26
|
+
document_tampering: "DOCUMENT_TAMPERING",
|
|
27
|
+
document_inconsistent: "DOCUMENT_TAMPERING",
|
|
28
|
+
sanctions_match: "SANCTIONS_MATCH",
|
|
29
|
+
pep_match: "PEP_MATCH",
|
|
30
|
+
adverse_media: "ADVERSE_MEDIA_MATCH",
|
|
31
|
+
high_risk_network: "HIGH_RISK_DEVICE",
|
|
32
|
+
ip_country_mismatch: "HIGH_RISK_DEVICE",
|
|
33
|
+
velocity_exceeded: "VELOCITY_EXCEEDED",
|
|
34
|
+
underage: "UNDERAGE"
|
|
35
|
+
};
|
|
36
|
+
/** The default screening config applied when the stage is enabled without one. */
|
|
37
|
+
const DEFAULT_SCREENING_CONFIG = {
|
|
38
|
+
threshold: .7,
|
|
39
|
+
on_hit: "review",
|
|
40
|
+
monitor: false
|
|
41
|
+
};
|
|
42
|
+
const DEFAULT_VELOCITY_SETTINGS = {
|
|
43
|
+
max_sessions: 5,
|
|
44
|
+
window_minutes: 60
|
|
45
|
+
};
|
|
46
|
+
const DEFAULT_FACE_EMBEDDING_SETTINGS = {
|
|
47
|
+
enabled: false,
|
|
48
|
+
retention_days: 365
|
|
49
|
+
};
|
|
50
|
+
//#endregion
|
|
51
|
+
export { DEFAULT_FACE_EMBEDDING_SETTINGS, DEFAULT_RISK_SIGNAL_POLICY, DEFAULT_SCREENING_CONFIG, DEFAULT_VELOCITY_SETTINGS, REVIEW_ONLY_RISK_SIGNALS, RISK_SIGNAL_KEYS, RISK_SIGNAL_REASONS };
|
|
52
|
+
|
|
53
|
+
//# sourceMappingURL=risk.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk.mjs","names":[],"sources":["../src/risk.ts"],"sourcesContent":["import type { Id, IsoDateTime } from './common'\nimport type { DecisionReason } from './verification'\n\n/** A fraud or compliance signal a detector can raise against a session. */\nexport type RiskSignalKey =\n | 'duplicate_document'\n | 'duplicate_identity'\n | 'duplicate_face'\n | 'document_tampering'\n | 'document_inconsistent'\n | 'sanctions_match'\n | 'pep_match'\n | 'adverse_media'\n | 'high_risk_network'\n | 'ip_country_mismatch'\n | 'velocity_exceeded'\n | 'underage'\n\n/** Every signal key, in decision precedence order (most severe first). */\nexport const RISK_SIGNAL_KEYS: readonly RiskSignalKey[] = [\n 'sanctions_match',\n 'underage',\n 'duplicate_document',\n 'duplicate_face',\n 'document_tampering',\n 'document_inconsistent',\n 'pep_match',\n 'adverse_media',\n 'duplicate_identity',\n 'high_risk_network',\n 'ip_country_mismatch',\n 'velocity_exceeded',\n]\n\n/** What a signal does to the decision: nothing (`info`), manual review, or rejection. */\nexport type RiskSeverity = 'info' | 'review' | 'reject'\n\n/** How a workflow treats a signal key. */\nexport type RiskSignalPolicy = 'ignore' | 'review' | 'reject'\n\n/** Per-key policy overrides. Keys left out use {@link DEFAULT_RISK_SIGNAL_POLICY}. */\nexport type RiskPolicyConfig = Partial<Record<RiskSignalKey, RiskSignalPolicy>>\n\n/** Signals route to review unless an organization opts a key into `ignore` or `reject`. */\nexport const DEFAULT_RISK_SIGNAL_POLICY: RiskSignalPolicy = 'review'\n\n/** Signals that never reject, whatever the policy says: their evidence is too soft. */\nexport const REVIEW_ONLY_RISK_SIGNALS: readonly RiskSignalKey[] = ['duplicate_identity', 'ip_country_mismatch']\n\n/** The decision reason each signal key reports when it decides a session. */\nexport const RISK_SIGNAL_REASONS: Record<RiskSignalKey, DecisionReason> = {\n duplicate_document: 'DUPLICATE_DOCUMENT',\n duplicate_identity: 'DUPLICATE_IDENTITY',\n duplicate_face: 'DUPLICATE_FACE',\n document_tampering: 'DOCUMENT_TAMPERING',\n document_inconsistent: 'DOCUMENT_TAMPERING',\n sanctions_match: 'SANCTIONS_MATCH',\n pep_match: 'PEP_MATCH',\n adverse_media: 'ADVERSE_MEDIA_MATCH',\n high_risk_network: 'HIGH_RISK_DEVICE',\n ip_country_mismatch: 'HIGH_RISK_DEVICE',\n velocity_exceeded: 'VELOCITY_EXCEEDED',\n underage: 'UNDERAGE',\n}\n\n/** A signal raised by a detector, before it is stored. */\nexport interface RiskSignal {\n key: RiskSignalKey\n severity: RiskSeverity\n /** How much the signal adds to the session's risk score, in [0, 1]. */\n score: number\n /** Advisory signals (model opinions) are capped at review. */\n advisory?: boolean\n /** Detector-specific facts that justify the signal. */\n evidence: Record<string, unknown>\n}\n\n/** A stored risk signal, as the dashboard API returns it. */\nexport interface SessionRiskSignal extends RiskSignal {\n id: Id\n session_id: Id\n /** Which detector raised it. */\n source: string\n cleared_at: IsoDateTime | null\n cleared_by: Id | null\n clear_reason: string | null\n created_at: IsoDateTime\n}\n\n/** The risk block of a webhook payload. */\nexport interface WebhookRiskCheck {\n score: number | null\n signals: Array<{\n key: RiskSignalKey\n severity: RiskSeverity\n cleared: boolean\n }>\n}\n\n/** A category of screening hit. */\nexport type ScreeningHitCategory = 'sanction' | 'pep' | 'adverse_media' | 'other'\n\n/** One watchlist entity a screened identity matched. */\nexport interface ScreeningHit {\n /** Provider entity id, stable across re-screens. */\n entity_id: string\n name: string\n /** Match score in [0, 1]. */\n score: number\n category: ScreeningHitCategory\n /** Provider topic tags, e.g. `sanction`, `role.pep`. */\n topics: string[]\n /** Source lists the entity appears on. */\n datasets: string[]\n birth_dates: string[]\n countries: string[]\n /** A page describing the entity, when the provider has one. */\n url?: string\n}\n\n/** What a screening hit does to the session. */\nexport type ScreeningOnHit = 'review' | 'reject'\n\n/** Configuration for the `screening` workflow stage. */\nexport interface ScreeningStepConfig {\n /** Minimum match score in [0, 1] that counts as a hit. */\n threshold: number\n /** What a sanctions hit does. PEP and adverse media hits follow the workflow's risk policy. */\n on_hit: ScreeningOnHit\n /** Re-screen the identity on a schedule after the session completes. */\n monitor: boolean\n}\n\n/** The default screening config applied when the stage is enabled without one. */\nexport const DEFAULT_SCREENING_CONFIG: ScreeningStepConfig = {\n threshold: 0.7,\n on_hit: 'review',\n monitor: false,\n}\n\n/** Project limits for repeat sessions from one network address. */\nexport interface VelocitySettings {\n /** Sessions from one IP, under different user references, before the signal fires. */\n max_sessions: number\n /** The look-back window in minutes. */\n window_minutes: number\n}\n\nexport const DEFAULT_VELOCITY_SETTINGS: VelocitySettings = {\n max_sessions: 5,\n window_minutes: 60,\n}\n\n/** Organization-level opt-in for storing face embeddings. Off by default. */\nexport interface FaceEmbeddingSettings {\n enabled: boolean\n /** Days to keep an embedding before it is deleted. */\n retention_days: number\n}\n\nexport const DEFAULT_FACE_EMBEDDING_SETTINGS: FaceEmbeddingSettings = {\n enabled: false,\n retention_days: 365,\n}\n"],"mappings":";;AAmBA,MAAa,mBAA6C;CACxD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AAYA,MAAa,6BAA+C;;AAG5D,MAAa,2BAAqD,CAAC,sBAAsB,qBAAqB;;AAG9G,MAAa,sBAA6D;CACxE,oBAAoB;CACpB,oBAAoB;CACpB,gBAAgB;CAChB,oBAAoB;CACpB,uBAAuB;CACvB,iBAAiB;CACjB,WAAW;CACX,eAAe;CACf,mBAAmB;CACnB,qBAAqB;CACrB,mBAAmB;CACnB,UAAU;AACZ;;AAuEA,MAAa,2BAAgD;CAC3D,WAAW;CACX,QAAQ;CACR,SAAS;AACX;AAUA,MAAa,4BAA8C;CACzD,cAAc;CACd,gBAAgB;AAClB;AASA,MAAa,kCAAyD;CACpE,SAAS;CACT,gBAAgB;AAClB"}
|