@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.
Files changed (53) hide show
  1. package/dist/access.d.mts +12 -14
  2. package/dist/access.d.mts.map +1 -1
  3. package/dist/audit.d.mts +2 -4
  4. package/dist/audit.d.mts.map +1 -1
  5. package/dist/common.d.mts +8 -9
  6. package/dist/common.d.mts.map +1 -1
  7. package/dist/errors.d.mts +1 -2
  8. package/dist/errors.d.mts.map +1 -1
  9. package/dist/index.d.mts +8 -6
  10. package/dist/index.mjs +6 -3
  11. package/dist/notifications.d.mts +41 -0
  12. package/dist/notifications.d.mts.map +1 -0
  13. package/dist/notifications.mjs +21 -0
  14. package/dist/notifications.mjs.map +1 -0
  15. package/dist/organization.d.mts +9 -8
  16. package/dist/organization.d.mts.map +1 -1
  17. package/dist/project.d.mts +22 -14
  18. package/dist/project.d.mts.map +1 -1
  19. package/dist/project.mjs +13 -0
  20. package/dist/project.mjs.map +1 -0
  21. package/dist/providers.d.mts +17 -18
  22. package/dist/providers.d.mts.map +1 -1
  23. package/dist/rbac.d.mts +13 -15
  24. package/dist/rbac.d.mts.map +1 -1
  25. package/dist/realtime.d.mts +20 -27
  26. package/dist/realtime.d.mts.map +1 -1
  27. package/dist/realtime.mjs +11 -29
  28. package/dist/realtime.mjs.map +1 -1
  29. package/dist/review.d.mts +3 -5
  30. package/dist/review.d.mts.map +1 -1
  31. package/dist/risk.d.mts +99 -0
  32. package/dist/risk.d.mts.map +1 -0
  33. package/dist/risk.mjs +53 -0
  34. package/dist/risk.mjs.map +1 -0
  35. package/dist/sdk.d.mts +3 -5
  36. package/dist/sdk.d.mts.map +1 -1
  37. package/dist/settings.d.mts +6 -19
  38. package/dist/settings.d.mts.map +1 -1
  39. package/dist/settings.mjs +0 -1
  40. package/dist/settings.mjs.map +1 -1
  41. package/dist/user.d.mts +2 -4
  42. package/dist/user.d.mts.map +1 -1
  43. package/dist/verification.d.mts +6 -8
  44. package/dist/verification.d.mts.map +1 -1
  45. package/dist/webhook.d.mts +18 -11
  46. package/dist/webhook.d.mts.map +1 -1
  47. package/dist/widget.d.mts +4 -6
  48. package/dist/widget.d.mts.map +1 -1
  49. package/dist/workflow.d.mts +30 -22
  50. package/dist/workflow.d.mts.map +1 -1
  51. package/dist/workflow.mjs +17 -2
  52. package/dist/workflow.mjs.map +1 -1
  53. package/package.json +1 -1
@@ -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
@@ -1 +1 @@
1
- {"version":3,"file":"providers.d.mts","names":[],"sources":["../src/providers.ts"],"mappings":";;;;;KAIY,YAAA;AAAZ;AAAA,UAGiB,SAAA;EACf,SAAA;EACA,QAAA;EACA,QAAA;EACA,WAAA,GAAc,OAAA;EACd,cAAA;EACA,UAAA,GAAa,OAAO;EACpB,WAAA;AAAA;;;;;;UAQe,eAAA;EATF;EAWb,OAAA;EAVW;EAYX,UAAA;EAJe;EAMf,YAAA;;EAEA,SAAA;EANA;EAQA,gBAAA;EAJA;EAMA,iBAAA;EAFA;EAIA,YAAA;AAAA;;UAIe,aAAA;EACf,MAAA,EAAQ,SAAA;EADoB;EAG5B,UAAA;EAE8B;EAA9B,YAAA,GAAe,eAAe;EAJtB;EAMR,GAAA;AAAA;;UAIe,YAAA;EACf,YAAA;EACA,YAAA;EACA,YAAA;EACA,aAAA;EACA,eAAA;EACA,YAAA;AAAA;;UAIe,kBAAA;EACf,MAAA;EANA;EAQA,KAAA;EACA,YAAA,EAAc,YAAY;EAC1B,GAAA;AAAA;;UAIe,mBAAA;EACf,MAAA;EATA;EAWA,eAAA;EARA;EAUA,UAAA;EACA,GAAA;AAAA;AAVG;AAAA,UAcY,aAAA;EACf,KAAA;EACA,KAAA;EACA,IAAA;EAZA;EAcA,MAAA;EACA,UAAA;EAVA;EAYA,OAAA;EAZG;EAcH,QAAA;EACA,SAAA;AAAA;;UAIe,mBAAA;EACf,MAAA,EAAQ,aAAA;EAbR;EAeA,MAAA;EAZA;EAcA,UAAA;EAVA;EAYA,QAAA,GAAW,aAAa;EAXf;AAAA;AAIX;;;EAaE,aAAA;EAZA;EAcA,IAAA;EACA,GAAA;AAAA;;UAIe,iBAAA;EACf,MAAA;EANA;EAQA,KAAA;EAPG;EASH,OAAA,EAAS,mBAAmB;EALb;EAOf,UAAA;EACA,GAAA;AAAA;;UAIe,eAAA,SAAwB,MAAA,EAAQ,aAAA;EAC/C,UAAA,EAAY,EAAA;EACZ,OAAA;EACA,aAAA,EAAe,YAAA;EACf,gBAAA;EACA,eAAA;EACA,aAAA;AAAA;;UAIe,SAAA,SAAkB,MAAA,EAAQ,aAAA;EACzC,UAAA,EAAY,EAAA;EACZ,mBAAA,EAAqB,EAAA;EACrB,MAAA,EAAQ,SAAA;EACR,UAAA;EACA,YAAA;AAAA;;UAIe,gBAAA,SAAyB,MAAA,EAAQ,aAAA;EAChD,UAAA,EAAY,EAAA;EACZ,mBAAA,EAAqB,EAAA;EACrB,mBAAA;EACA,oBAAA;AAAA;;UAIe,aAAA,SAAsB,MAAA,EAAQ,aAAA;EAC7C,UAAA,EAAY,EAAA;EACZ,iBAAA;EACA,UAAA;EACA,KAAA;EACA,MAAA;EACA,aAAA,EAAe,YAAA;EACf,QAAA;EACA,YAAA;AAAA;;UAIe,cAAA,SAAuB,MAAA,EAAQ,aAAA;EAC9C,UAAA,EAAY,EAAA;EACZ,sBAAA;EACA,iBAAA;EACA,gBAAA;EACA,UAAA;EACA,MAAA;EACA,QAAA;EACA,YAAA;AAAA;;UAIe,mBAAA,SAA4B,MAAA,EAAQ,aAAA;EACnD,UAAA,EAAY,EAAA;EArCA;EAuCZ,eAAA,EAAiB,aAAA;EAnCF;EAqCf,mBAAA;;EAEA,QAAA;EACA,SAAA;EACA,MAAA;EAzCgD;EA2ChD,KAAA;EA3C6D;EA6C7D,OAAA,EAAS,mBAAA;EACT,QAAA;EACA,YAAA;AAAA"}
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
@@ -1 +1 @@
1
- {"version":3,"file":"rbac.d.mts","names":[],"sources":["../src/rbac.ts"],"mappings":";;;;;AASA;;;;AAAyB;KAAb,aAAA;;KA0CA,eAAA;;KAcA,cAAA;AAAZ;;;;AAA0B;AAA1B,KAOY,kBAAA;;KAcA,oBAAA;;KASA,gBAAA,GAAmB,aAAA,GAAgB,kBAAkB;AATjE;AAAA,KAYY,kBAAA,GAAqB,eAAA,GAAkB,oBAAoB;;KAG3D,aAAA;AAfoB;AAAA,UAkBf,UAAA,SAAmB,MAAA;EATR;EAW1B,IAAA,EAAM,gBAAA;EACN,WAAA;EACA,KAAA,EAAO,kBAAA;EAVG;EAYV,KAAA;AAAA;;AAZqE;AAGvE;;UAgBiB,IAAA,SAAa,MAAM;EAhBX;EAkBvB,eAAA,EAAiB,EAAA;EACjB,IAAA;EACA,IAAA;EACA,WAAA;EACA,SAAA;EAfO;EAiBP,KAAA;AAAA;;UAIe,cAAA,SAAuB,MAAA;EACtC,OAAA,EAAS,EAAA;EACT,aAAA,EAAe,EAAA;AAAA;;;;;UAOA,cAAA,SAAuB,MAAA,EAAQ,kBAAA;EAC9C,UAAA,EAAY,EAAA;EACZ,OAAA,EAAS,EAAA;EACT,aAAA,EAAe,EAAA;AAAA;;;;;;;UASA,eAAA,SAAwB,MAAA;EACvC,OAAA,EAAS,EAAA;EACT,aAAA,EAAe,EAAA;EACf,OAAA,EAAS,EAAA;AAAA"}
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"}
@@ -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 transport contracts (Phase 16). Pure, dependency-free helpers shared
7
- * by the API (server publish) and the dashboard/widget (client subscribe), so
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). */readonly sessionTransition: "session.transition"; /** A reviewer acted on a session (assign/note/suspicious/decision/retry). */
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. All channels are `private-` (Pusher protocol),
18
- * so a subscription must be authorized server-side against the caller's scope.
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
- /** Everything in an organization. */organization: (organizationId: Id) => string; /** Everything in a project. */
22
- project: (organizationId: Id, projectId: Id) => string; /** A single verification session (used by the widget via client token). */
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
@@ -1 +1 @@
1
- {"version":3,"file":"realtime.d.mts","names":[],"sources":["../src/realtime.ts"],"mappings":";;;;;;AAUA;;;;cAAa,cAAA;EAOD,uFAFF,iBAAA;WAAA,YAAA;AAAA;AAAA,KAEE,iBAAA,WAA4B,cAAA,eAA6B,cAAc;;;;;cAMtE,gBAAA;EAMU,oEAJU,EAAA,aAIR;4BAFG,EAAA,EAAE,SAAA,EAAa,EAAA,aAFV;uBAIV,EAAA;AAAA;;iBAIP,oBAAA,CACd,OAAA;EAEI,IAAA;EAAsB,cAAA;AAAA;EACtB,IAAA;EAAiB,cAAA;EAAwB,SAAA;AAAA;EACzC,IAAA;EAAiB,SAAA;AAAA;;UAYN,sBAAA;EACf,UAAA,EAAY,EAAA;EACZ,eAAA,EAAiB,EAAA;EACjB,UAAA,EAAY,EAAA;EACZ,MAAA,EAAQ,kBAAA;EACR,eAAA,EAAiB,kBAAA;AAAA;;UAIF,iBAAA;EACf,UAAA,EAAY,EAAA;EACZ,eAAA,EAAiB,EAAA;EACjB,UAAA,EAAY,EAAA;;EAEZ,MAAA;EACA,QAAA,EAAU,EAAA;AAAA"}
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 transport contracts (Phase 16). Pure, dependency-free helpers shared
4
- * by the API (server publish) and the dashboard/widget (client subscribe), so
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. All channels are `private-` (Pusher protocol),
16
- * so a subscription must be authorized server-side against the caller's scope.
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-${organizationId}`,
22
+ organization: (organizationId) => `private-organization.${organizationId}`,
21
23
  /** Everything in a project. */
22
- project: (organizationId, projectId) => `private-organization-${organizationId}-project-${projectId}`,
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-${sessionId}`
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, parseRealtimeChannel, realtimeChannels };
29
+ export { REALTIME_EVENT, realtimeChannels };
48
30
 
49
31
  //# sourceMappingURL=realtime.mjs.map
@@ -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 transport contracts (Phase 16). Pure, dependency-free helpers shared\n * by the API (server publish) and the dashboard/widget (client subscribe), so\n * 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. All channels are `private-` (Pusher protocol),\n * so a subscription must be authorized server-side against the caller's scope.\n */\nexport const realtimeChannels = {\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/** Parse a private channel name back into its scope, or null if unrecognized. */\nexport function parseRealtimeChannel(\n channel: string,\n):\n | { kind: 'organization'; organizationId: string }\n | { kind: 'project'; organizationId: string; projectId: string }\n | { kind: 'session'; sessionId: string }\n | null {\n const project = /^private-organization-(.+)-project-(.+)$/.exec(channel)\n if (project) return { kind: 'project', organizationId: project[1]!, projectId: project[2]! }\n const organization = /^private-organization-(.+)$/.exec(channel)\n if (organization) return { kind: 'organization', organizationId: organization[1]! }\n const session = /^private-session-(.+)$/.exec(channel)\n if (session) return { kind: 'session', sessionId: session[1]! }\n return null\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":";;;;;;;AAUA,MAAa,iBAAiB;;CAE5B,mBAAmB;;CAEnB,cAAc;AAChB;;;;;AAQA,MAAa,mBAAmB;;CAE9B,eAAe,mBAA+B,wBAAwB;;CAEtE,UAAU,gBAAoB,cAA0B,wBAAwB,eAAe,WAAW;;CAE1G,UAAU,cAA0B,mBAAmB;AACzD;;AAGA,SAAgB,qBACd,SAKO;CACP,MAAM,UAAU,2CAA2C,KAAK,OAAO;CACvE,IAAI,SAAS,OAAO;EAAE,MAAM;EAAW,gBAAgB,QAAQ;EAAK,WAAW,QAAQ;CAAI;CAC3F,MAAM,eAAe,8BAA8B,KAAK,OAAO;CAC/D,IAAI,cAAc,OAAO;EAAE,MAAM;EAAgB,gBAAgB,aAAa;CAAI;CAClF,MAAM,UAAU,yBAAyB,KAAK,OAAO;CACrD,IAAI,SAAS,OAAO;EAAE,MAAM;EAAW,WAAW,QAAQ;CAAI;CAC9D,OAAO;AACT"}
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
@@ -1 +1 @@
1
- {"version":3,"file":"review.d.mts","names":[],"sources":["../src/review.ts"],"mappings":";;;;;KAIY,YAAA;AAAZ;;;;AAAA,UAaiB,MAAA,SAAe,MAAA,EAAQ,aAAA;EACtC,UAAA,EAAY,EAAA;EACZ,WAAA,EAAa,EAAA;EACb,eAAA,EAAiB,kBAAA;EACjB,UAAA,EAAY,kBAAA;EACZ,MAAA;EACA,IAAA;AAAA;;UAIe,UAAA,SAAmB,MAAA,EAAQ,aAAA;EAC1C,UAAA,EAAY,EAAA;EACZ,WAAA,EAAa,EAAA;EACb,IAAA;AAAA"}
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"}
@@ -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"}