@arkyc/types 1.0.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/audit.d.mts +27 -0
- package/dist/audit.d.mts.map +1 -0
- package/dist/common.d.mts +36 -0
- package/dist/common.d.mts.map +1 -0
- package/dist/index.d.mts +16 -0
- package/dist/index.mjs +4 -0
- package/dist/organization.d.mts +41 -0
- package/dist/organization.d.mts.map +1 -0
- package/dist/project.d.mts +104 -0
- package/dist/project.d.mts.map +1 -0
- package/dist/providers.d.mts +121 -0
- package/dist/providers.d.mts.map +1 -0
- package/dist/rbac.d.mts +80 -0
- package/dist/rbac.d.mts.map +1 -0
- package/dist/realtime.d.mts +56 -0
- package/dist/realtime.d.mts.map +1 -0
- package/dist/realtime.mjs +49 -0
- package/dist/realtime.mjs.map +1 -0
- package/dist/review.d.mts +27 -0
- package/dist/review.d.mts.map +1 -0
- package/dist/sdk.d.mts +34 -0
- package/dist/sdk.d.mts.map +1 -0
- package/dist/settings.d.mts +47 -0
- package/dist/settings.d.mts.map +1 -0
- package/dist/settings.mjs +15 -0
- package/dist/settings.mjs.map +1 -0
- package/dist/user.d.mts +17 -0
- package/dist/user.d.mts.map +1 -0
- package/dist/verification.d.mts +44 -0
- package/dist/verification.d.mts.map +1 -0
- package/dist/webhook.d.mts +63 -0
- package/dist/webhook.d.mts.map +1 -0
- package/dist/widget.d.mts +29 -0
- package/dist/widget.d.mts.map +1 -0
- package/dist/workflow.d.mts +59 -0
- package/dist/workflow.d.mts.map +1 -0
- package/dist/workflow.mjs +48 -0
- package/dist/workflow.mjs.map +1 -0
- package/package.json +25 -0
package/dist/audit.d.mts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Id, IsoDateTime, Metadata } from "./common.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/audit.d.ts
|
|
4
|
+
/** Who performed an audited action. */
|
|
5
|
+
type ActorType = 'user' | 'api_key' | 'system';
|
|
6
|
+
/**
|
|
7
|
+
* An immutable audit log entry. Project scope is optional (some actions are
|
|
8
|
+
* organization-level only). Audit rows are append-only and carry no `updated_at`.
|
|
9
|
+
*/
|
|
10
|
+
interface AuditLog {
|
|
11
|
+
id: Id;
|
|
12
|
+
organization_id: Id;
|
|
13
|
+
project_id: Id | null;
|
|
14
|
+
actor_id: Id | null;
|
|
15
|
+
actor_type: ActorType;
|
|
16
|
+
/** Action key, e.g. `session.approved`, `api_key.created`. */
|
|
17
|
+
action: string;
|
|
18
|
+
entity_type: string;
|
|
19
|
+
entity_id: Id | null;
|
|
20
|
+
metadata: Metadata;
|
|
21
|
+
ip_address: string | null;
|
|
22
|
+
user_agent: string | null;
|
|
23
|
+
created_at: IsoDateTime;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { ActorType, AuditLog };
|
|
27
|
+
//# sourceMappingURL=audit.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.mts","names":[],"sources":["../src/audit.ts"],"mappings":";;;;KAGY,SAAA;AAAZ;;;;AAAA,UAMiB,QAAA;EACf,EAAA,EAAI,EAAA;EACJ,eAAA,EAAiB,EAAA;EACjB,UAAA,EAAY,EAAA;EACZ,QAAA,EAAU,EAAA;EACV,UAAA,EAAY,SAAA;EAFA;EAIZ,MAAA;EACA,WAAA;EACA,SAAA,EAAW,EAAA;EACX,QAAA,EAAU,QAAA;EACV,UAAA;EACA,UAAA;EACA,UAAA,EAAY,WAAA;AAAA"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//#region src/common.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Shared primitive aliases used across Arkyc domain types.
|
|
4
|
+
*
|
|
5
|
+
* These are intentionally light: they document intent at call sites without
|
|
6
|
+
* adding runtime weight. IDs are strings (prefixed identifiers like
|
|
7
|
+
* `kyc_sess_…`, `organization_…`, `project_…`); timestamps are ISO-8601 strings.
|
|
8
|
+
*/
|
|
9
|
+
/** A unique identifier (typically a prefixed, URL-safe string). */
|
|
10
|
+
type Id = string;
|
|
11
|
+
/** An ISO-8601 date-time string, e.g. `2026-06-20T00:00:00.000Z`. */
|
|
12
|
+
type IsoDateTime = string;
|
|
13
|
+
/** An ISO-8601 date string (no time component), e.g. `1990-05-21`. */
|
|
14
|
+
type IsoDate = string;
|
|
15
|
+
/** Arbitrary, JSON-serialisable metadata attached to an entity. */
|
|
16
|
+
type Metadata = Record<string, unknown>;
|
|
17
|
+
/** Columns shared by every persisted entity. */
|
|
18
|
+
interface Timestamps {
|
|
19
|
+
created_at: IsoDateTime;
|
|
20
|
+
updated_at: IsoDateTime;
|
|
21
|
+
}
|
|
22
|
+
/** A persisted entity: an `id` plus creation/update timestamps. */
|
|
23
|
+
interface Entity extends Timestamps {
|
|
24
|
+
id: Id;
|
|
25
|
+
}
|
|
26
|
+
/** Scoping columns present on every organization-owned entity. */
|
|
27
|
+
interface OrganizationScoped {
|
|
28
|
+
organization_id: Id;
|
|
29
|
+
}
|
|
30
|
+
/** Scoping columns present on every project-owned entity. */
|
|
31
|
+
interface ProjectScoped extends OrganizationScoped {
|
|
32
|
+
project_id: Id;
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { Entity, Id, IsoDate, IsoDateTime, Metadata, OrganizationScoped, ProjectScoped, Timestamps };
|
|
36
|
+
//# sourceMappingURL=common.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.d.mts","names":[],"sources":["../src/common.ts"],"mappings":";;AASA;;;;AAAc;AAGd;;KAHY,EAAA;;KAGA,WAAA;AAGZ;AAAA,KAAY,OAAA;;KAGA,QAAA,GAAW,MAAM;AAHV;AAAA,UAMF,UAAA;EACf,UAAA,EAAY,WAAA;EACZ,UAAA,EAAY,WAAW;AAAA;AALI;AAAA,UASZ,MAAA,SAAe,UAAU;EACxC,EAAA,EAAI,EAAA;AAAA;;UAIW,kBAAA;EACf,eAAA,EAAiB,EAAE;AAAA;;UAIJ,aAAA,SAAsB,kBAAkB;EACvD,UAAA,EAAY,EAAA;AAAA"}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Entity, Id, IsoDate, IsoDateTime, Metadata, OrganizationScoped, ProjectScoped, Timestamps } from "./common.mjs";
|
|
2
|
+
import { PublicUser, User } from "./user.mjs";
|
|
3
|
+
import { InvitationStatus, MembershipStatus, Organization, OrganizationInvitation, OrganizationMember, OrganizationSettings } from "./organization.mjs";
|
|
4
|
+
import { AdminPermission, AdminPermissionGroup, AdminPermissionKey, AdminRoleSlug, AnyPermissionGroup, AnyPermissionKey, Permission, PermissionGroup, PermissionKey, Role, RolePermission, SystemRoleSlug, UserPermission } from "./rbac.mjs";
|
|
5
|
+
import { CaptureModel, DEFAULT_GLOBAL_SETTINGS, GlobalSetting, GlobalSettings, RealtimeTransport } from "./settings.mjs";
|
|
6
|
+
import { DecisionReason, LivenessChallenge, LivenessMode, VerificationDecision, VerificationSession, VerificationStatus } from "./verification.mjs";
|
|
7
|
+
import { REALTIME_EVENT, RealtimeEventName, ReviewActionEvent, SessionTransitionEvent, parseRealtimeChannel, realtimeChannels } from "./realtime.mjs";
|
|
8
|
+
import { ApiKey, ApiKeyWithSecret, Project, ProjectBranding, ProjectContext, ProjectEnvironment, ProjectHandoffSettings, ProjectMember, ProjectSettings, ProjectStatus, VerificationThresholds } from "./project.mjs";
|
|
9
|
+
import { DocumentCapture, DocumentPortrait, DocumentType, FaceMatchCheck, FaceMatchResultData, LivenessCheck, LivenessResultData, OcrAuthenticity, OcrFields, OcrResult, OcrResultData, SpoofSignals } from "./providers.mjs";
|
|
10
|
+
import { DEFAULT_WORKFLOW_CONFIG, WORKFLOW_STEP_KEYS, Workflow, WorkflowConfig, WorkflowOptions, WorkflowStep, WorkflowStepKey, workflowEnabledSteps, workflowEnables, workflowRunsOcr } from "./workflow.mjs";
|
|
11
|
+
import { Review, ReviewAction, ReviewNote } from "./review.mjs";
|
|
12
|
+
import { WebhookChecks, WebhookDelivery, WebhookDeliveryStatus, WebhookEndpoint, WebhookEndpointStatus, WebhookEvent, WebhookEventName } from "./webhook.mjs";
|
|
13
|
+
import { ActorType, AuditLog } from "./audit.mjs";
|
|
14
|
+
import { CreateSessionParams, SdkOptions, SessionResource } from "./sdk.mjs";
|
|
15
|
+
import { WidgetMode, WidgetOptions, WidgetResult, WidgetStep } from "./widget.mjs";
|
|
16
|
+
export { ActorType, AdminPermission, AdminPermissionGroup, AdminPermissionKey, AdminRoleSlug, AnyPermissionGroup, AnyPermissionKey, ApiKey, ApiKeyWithSecret, AuditLog, CaptureModel, CreateSessionParams, DEFAULT_GLOBAL_SETTINGS, DEFAULT_WORKFLOW_CONFIG, DecisionReason, DocumentCapture, DocumentPortrait, DocumentType, Entity, FaceMatchCheck, FaceMatchResultData, GlobalSetting, GlobalSettings, Id, InvitationStatus, IsoDate, IsoDateTime, LivenessChallenge, LivenessCheck, LivenessMode, LivenessResultData, MembershipStatus, Metadata, OcrAuthenticity, OcrFields, OcrResult, OcrResultData, Organization, OrganizationInvitation, OrganizationMember, OrganizationScoped, OrganizationSettings, Permission, PermissionGroup, PermissionKey, Project, ProjectBranding, ProjectContext, ProjectEnvironment, ProjectHandoffSettings, ProjectMember, ProjectScoped, ProjectSettings, ProjectStatus, PublicUser, REALTIME_EVENT, RealtimeEventName, RealtimeTransport, Review, ReviewAction, ReviewActionEvent, ReviewNote, Role, RolePermission, SdkOptions, SessionResource, SessionTransitionEvent, SpoofSignals, SystemRoleSlug, Timestamps, User, UserPermission, VerificationDecision, VerificationSession, VerificationStatus, VerificationThresholds, WORKFLOW_STEP_KEYS, WebhookChecks, WebhookDelivery, WebhookDeliveryStatus, WebhookEndpoint, WebhookEndpointStatus, WebhookEvent, WebhookEventName, WidgetMode, WidgetOptions, WidgetResult, WidgetStep, Workflow, WorkflowConfig, WorkflowOptions, WorkflowStep, WorkflowStepKey, parseRealtimeChannel, realtimeChannels, workflowEnabledSteps, workflowEnables, workflowRunsOcr };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { DEFAULT_GLOBAL_SETTINGS } from "./settings.mjs";
|
|
2
|
+
import { REALTIME_EVENT, parseRealtimeChannel, realtimeChannels } from "./realtime.mjs";
|
|
3
|
+
import { DEFAULT_WORKFLOW_CONFIG, WORKFLOW_STEP_KEYS, workflowEnabledSteps, workflowEnables, workflowRunsOcr } from "./workflow.mjs";
|
|
4
|
+
export { DEFAULT_GLOBAL_SETTINGS, DEFAULT_WORKFLOW_CONFIG, REALTIME_EVENT, WORKFLOW_STEP_KEYS, parseRealtimeChannel, realtimeChannels, workflowEnabledSteps, workflowEnables, workflowRunsOcr };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Entity, Id, IsoDateTime, Metadata, OrganizationScoped } from "./common.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/organization.d.ts
|
|
4
|
+
/** Membership lifecycle states for organization/project members. */
|
|
5
|
+
type MembershipStatus = 'active' | 'invited' | 'suspended';
|
|
6
|
+
/** Invitation lifecycle states. */
|
|
7
|
+
type InvitationStatus = 'pending' | 'accepted' | 'expired' | 'revoked';
|
|
8
|
+
/**
|
|
9
|
+
* An organization, business, or workspace using Arkyc. An organization owns projects,
|
|
10
|
+
* members, roles, API keys, sessions, webhooks, and audit logs.
|
|
11
|
+
*/
|
|
12
|
+
interface Organization extends Entity {
|
|
13
|
+
name: string;
|
|
14
|
+
slug: string;
|
|
15
|
+
logo_url: string | null;
|
|
16
|
+
settings: OrganizationSettings;
|
|
17
|
+
}
|
|
18
|
+
/** Organization-level configuration (free-form, with known optional keys). */
|
|
19
|
+
interface OrganizationSettings extends Metadata {
|
|
20
|
+
/** Days to retain verification media before cleanup (Phase 15). */
|
|
21
|
+
retention_days?: number;
|
|
22
|
+
}
|
|
23
|
+
/** Links a {@link User} to a {@link Organization} with a role. */
|
|
24
|
+
interface OrganizationMember extends Entity, OrganizationScoped {
|
|
25
|
+
user_id: Id;
|
|
26
|
+
role_id: Id;
|
|
27
|
+
status: MembershipStatus;
|
|
28
|
+
joined_at: IsoDateTime | null;
|
|
29
|
+
}
|
|
30
|
+
/** A pending invitation to join an organization with a given role. */
|
|
31
|
+
interface OrganizationInvitation extends Entity, OrganizationScoped {
|
|
32
|
+
email: string;
|
|
33
|
+
role_id: Id;
|
|
34
|
+
/** Hash of the single-use invitation token; the raw token is emailed once. */
|
|
35
|
+
token_hash: string;
|
|
36
|
+
expires_at: IsoDateTime;
|
|
37
|
+
accepted_at: IsoDateTime | null;
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
export { InvitationStatus, MembershipStatus, Organization, OrganizationInvitation, OrganizationMember, OrganizationSettings };
|
|
41
|
+
//# sourceMappingURL=organization.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organization.d.mts","names":[],"sources":["../src/organization.ts"],"mappings":";;;;KAGY,gBAAA;AAAZ;AAAA,KAGY,gBAAA;;;AAHgB;AAG5B;UAMiB,YAAA,SAAqB,MAAM;EAC1C,IAAA;EACA,IAAA;EACA,QAAA;EACA,QAAA,EAAU,oBAAA;AAAA;;UAIK,oBAAA,SAA6B,QAAQ;EARhB;EAUpC,cAAc;AAAA;;UAIC,kBAAA,SAA2B,MAAA,EAAQ,kBAAA;EAClD,OAAA,EAAS,EAAA;EACT,OAAA,EAAS,EAAA;EACT,MAAA,EAAQ,gBAAA;EACR,SAAA,EAAW,WAAA;AAAA;;UAII,sBAAA,SAA+B,MAAA,EAAQ,kBAAA;EACtD,KAAA;EACA,OAAA,EAAS,EAAA;EAVyB;EAYlC,UAAA;EACA,UAAA,EAAY,WAAA;EACZ,WAAA,EAAa,WAAA;AAAA"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { Entity, Id, IsoDateTime, Metadata, OrganizationScoped, ProjectScoped } from "./common.mjs";
|
|
2
|
+
import { MembershipStatus } from "./organization.mjs";
|
|
3
|
+
import { CaptureModel } from "./settings.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/project.d.ts
|
|
6
|
+
/** Deployment environment for a project. */
|
|
7
|
+
type ProjectEnvironment = 'production' | 'staging' | 'development';
|
|
8
|
+
/** Project lifecycle status. */
|
|
9
|
+
type ProjectStatus = 'active' | 'paused' | 'archived';
|
|
10
|
+
/**
|
|
11
|
+
* Per-project, configurable thresholds the decision engine compares scores
|
|
12
|
+
* against. Defaults live in `@arkyc/core`; projects may override any subset.
|
|
13
|
+
*/
|
|
14
|
+
interface VerificationThresholds {
|
|
15
|
+
documentQualityThreshold: number;
|
|
16
|
+
ocrConfidenceThreshold: number;
|
|
17
|
+
livenessThreshold: number;
|
|
18
|
+
faceMatchThreshold: number;
|
|
19
|
+
}
|
|
20
|
+
/** Visual branding applied to the widget for a project. */
|
|
21
|
+
interface ProjectBranding {
|
|
22
|
+
logo_url?: string | null;
|
|
23
|
+
primary_color?: string;
|
|
24
|
+
border_radius?: number;
|
|
25
|
+
theme?: 'light' | 'dark';
|
|
26
|
+
/** Display name (company/product) shown in the widget header. */
|
|
27
|
+
name?: string | null;
|
|
28
|
+
/**
|
|
29
|
+
* Whether to show the project's name/logo in the widget header. Defaults to
|
|
30
|
+
* shown; set `false` for an unbranded (white-label) header.
|
|
31
|
+
*/
|
|
32
|
+
show_branding?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Cross-device handoff: a desktop user continues an in-progress verification on
|
|
36
|
+
* their phone by scanning a QR code.
|
|
37
|
+
* The QR is shown first on desktop.
|
|
38
|
+
*/
|
|
39
|
+
interface ProjectHandoffSettings {
|
|
40
|
+
/** Whether desktop users are offered the QR handoff to their phone. */
|
|
41
|
+
enabled?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Whether a desktop user may instead continue on the desktop device. When
|
|
44
|
+
* `false`, a desktop user must scan to a phone (no "continue here"). Defaults true.
|
|
45
|
+
*/
|
|
46
|
+
allow_desktop?: boolean;
|
|
47
|
+
}
|
|
48
|
+
/** Project-level configuration. */
|
|
49
|
+
interface ProjectSettings extends Metadata {
|
|
50
|
+
thresholds?: Partial<VerificationThresholds>;
|
|
51
|
+
allowed_origins?: string[];
|
|
52
|
+
/** Maximum verification attempts before a session is hard-failed. */
|
|
53
|
+
max_retries?: number;
|
|
54
|
+
/** Overrides the global capture model for this project (Phase 17). */
|
|
55
|
+
capture_model?: CaptureModel;
|
|
56
|
+
/** Cross-device session handoff (QR). Off unless the project opts in. */
|
|
57
|
+
handoff?: ProjectHandoffSettings;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* A specific application, environment, or product integration owned by a
|
|
61
|
+
* organization. Sessions, API keys, and webhooks are scoped to a project.
|
|
62
|
+
*/
|
|
63
|
+
interface Project extends Entity, OrganizationScoped {
|
|
64
|
+
name: string;
|
|
65
|
+
slug: string;
|
|
66
|
+
environment: ProjectEnvironment;
|
|
67
|
+
settings: ProjectSettings;
|
|
68
|
+
branding: ProjectBranding;
|
|
69
|
+
status: ProjectStatus;
|
|
70
|
+
has_ai_grant?: boolean;
|
|
71
|
+
}
|
|
72
|
+
/** Links a user to a project with a role (narrower tha organization membership). */
|
|
73
|
+
interface ProjectMember extends Entity, ProjectScoped {
|
|
74
|
+
user_id: Id;
|
|
75
|
+
role_id: Id;
|
|
76
|
+
status: MembershipStatus;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* A project API key. Only `key_prefix` is stored in clear; the secret is hashed
|
|
80
|
+
* (`key_hash`) and shown to the integrator exactly once at creation.
|
|
81
|
+
*/
|
|
82
|
+
interface ApiKey extends Entity, ProjectScoped {
|
|
83
|
+
name: string;
|
|
84
|
+
key_prefix: string;
|
|
85
|
+
key_hash: string;
|
|
86
|
+
last_used_at: IsoDateTime | null;
|
|
87
|
+
expires_at: IsoDateTime | null;
|
|
88
|
+
revoked_at: IsoDateTime | null;
|
|
89
|
+
}
|
|
90
|
+
/** An API key plus its one-time-visible secret, returned only at creation. */
|
|
91
|
+
interface ApiKeyWithSecret {
|
|
92
|
+
api_key: ApiKey;
|
|
93
|
+
/** The full secret key, e.g. `sk_live_…`. Never persisted in clear. */
|
|
94
|
+
secret: string;
|
|
95
|
+
}
|
|
96
|
+
/** Resolves the organization + project + (optionally) acting user for a request. */
|
|
97
|
+
interface ProjectContext {
|
|
98
|
+
organization_id: Id;
|
|
99
|
+
project_id: Id;
|
|
100
|
+
api_key_id?: Id;
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
export { ApiKey, ApiKeyWithSecret, Project, ProjectBranding, ProjectContext, ProjectEnvironment, ProjectHandoffSettings, ProjectMember, ProjectSettings, ProjectStatus, VerificationThresholds };
|
|
104
|
+
//# sourceMappingURL=project.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.d.mts","names":[],"sources":["../src/project.ts"],"mappings":";;;;;;KAMY,kBAAA;AAAZ;AAAA,KAGY,aAAA;;;AAHkB;AAG9B;UAMiB,sBAAA;EACf,wBAAA;EACA,sBAAA;EACA,iBAAA;EACA,kBAAA;AAAA;;UAIe,eAAA;EACf,QAAA;EACA,aAAA;EACA,aAAA;EACA,KAAA;EARkB;EAUlB,IAAA;EANe;;;;EAWf,aAAA;AAAA;;;;;;UAQe,sBAAA;EAAA;EAEf,OAAA;;;AAKa;AAIf;EAJE,aAAa;AAAA;;UAIE,eAAA,SAAwB,QAAA;EACvC,UAAA,GAAa,OAAA,CAAQ,sBAAA;EACrB,eAAA;EAFuC;EAIvC,WAAA;EAJ+C;EAM/C,aAAA,GAAgB,YAAA;EALhB;EAOA,OAAA,GAAU,sBAAA;AAAA;;;;;UAOK,OAAA,SAAgB,MAAA,EAAQ,kBAAA;EACvC,IAAA;EACA,IAAA;EACA,WAAA,EAAa,kBAAA;EACb,QAAA,EAAU,eAAA;EACV,QAAA,EAAU,eAAA;EACV,MAAA,EAAQ,aAAA;EACR,YAAA;AAAA;;UAIe,aAAA,SAAsB,MAAA,EAAQ,aAAA;EAC7C,OAAA,EAAS,EAAA;EACT,OAAA,EAAS,EAAA;EACT,MAAA,EAAQ,gBAAA;AAAA;;;;;UAOO,MAAA,SAAe,MAAA,EAAQ,aAAA;EACtC,IAAA;EACA,UAAA;EACA,QAAA;EACA,YAAA,EAAc,WAAA;EACd,UAAA,EAAY,WAAA;EACZ,UAAA,EAAY,WAAA;AAAA;;UAIG,gBAAA;EACf,OAAA,EAAS,MAAM;EArBA;EAuBf,MAAA;AAAA;;UAIe,cAAA;EACf,eAAA,EAAiB,EAAA;EACjB,UAAA,EAAY,EAAA;EACZ,UAAA,GAAa,EAAA;AAAA"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { Entity, Id, IsoDate, ProjectScoped } from "./common.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/providers.d.ts
|
|
4
|
+
/** Supported identity document categories. */
|
|
5
|
+
type DocumentType = 'passport' | 'id_card' | 'drivers_license' | 'residence_permit';
|
|
6
|
+
/** Structured identity fields extracted from a document via OCR. */
|
|
7
|
+
interface OcrFields {
|
|
8
|
+
firstName?: string;
|
|
9
|
+
lastName?: string;
|
|
10
|
+
fullName?: string;
|
|
11
|
+
dateOfBirth?: IsoDate;
|
|
12
|
+
documentNumber?: string;
|
|
13
|
+
expiryDate?: IsoDate;
|
|
14
|
+
nationality?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Best-effort, image-only authenticity read from an OCR driver capable of it
|
|
18
|
+
* (the `ai` vision driver). Advisory anti-spoofing signals — a flagged document
|
|
19
|
+
* is routed to manual review, never auto-rejected on the model's say-so.
|
|
20
|
+
*/
|
|
21
|
+
interface OcrAuthenticity {
|
|
22
|
+
/** False when any tamper/replay signal fired. */
|
|
23
|
+
genuine: boolean;
|
|
24
|
+
/** Model's authenticity confidence in [0, 1]: 1 = clearly an original, 0 = clearly fake/replayed. */
|
|
25
|
+
confidence: number;
|
|
26
|
+
/** Looks like a photo of a screen (moiré, screen glare/banding, bezel) — a replay attack. */
|
|
27
|
+
screenReplay: boolean;
|
|
28
|
+
/** Looks like a photo/scan of a printout or photocopy rather than the physical document. */
|
|
29
|
+
photocopy: boolean;
|
|
30
|
+
/** Signs of digital editing (mismatched fonts, misaligned/recoloured text, cloned regions, edited photo/dates). */
|
|
31
|
+
digitalTampering: boolean;
|
|
32
|
+
/** Signs of physical tampering (substituted photo, peeled laminate, scratched/overwritten fields). */
|
|
33
|
+
physicalTampering: boolean;
|
|
34
|
+
/** Brief human-readable observations supporting the flags. */
|
|
35
|
+
observations: string[];
|
|
36
|
+
}
|
|
37
|
+
/** The shape returned by any OCR driver. */
|
|
38
|
+
interface OcrResultData {
|
|
39
|
+
fields: OcrFields;
|
|
40
|
+
/** Overall extraction confidence in [0, 1]. */
|
|
41
|
+
confidence: number;
|
|
42
|
+
/** Best-effort authenticity assessment, when the driver supports it. */
|
|
43
|
+
authenticity?: OcrAuthenticity;
|
|
44
|
+
/** Raw provider payload, retained for audit/debugging. */
|
|
45
|
+
raw?: unknown;
|
|
46
|
+
}
|
|
47
|
+
/** Anti-spoofing signals surfaced by a liveness driver. */
|
|
48
|
+
interface SpoofSignals {
|
|
49
|
+
screenReplay?: boolean;
|
|
50
|
+
printedPhoto?: boolean;
|
|
51
|
+
maskDetected?: boolean;
|
|
52
|
+
multipleFaces?: boolean;
|
|
53
|
+
faceNotCentered?: boolean;
|
|
54
|
+
poorLighting?: boolean;
|
|
55
|
+
}
|
|
56
|
+
/** The shape returned by any passive-liveness driver. */
|
|
57
|
+
interface LivenessResultData {
|
|
58
|
+
passed: boolean;
|
|
59
|
+
/** Liveness confidence in [0, 1]. */
|
|
60
|
+
score: number;
|
|
61
|
+
spoofSignals: SpoofSignals;
|
|
62
|
+
raw?: unknown;
|
|
63
|
+
}
|
|
64
|
+
/** The shape returned by any face-match driver. */
|
|
65
|
+
interface FaceMatchResultData {
|
|
66
|
+
passed: boolean;
|
|
67
|
+
/** Similarity between document portrait and selfie in [0, 1]. */
|
|
68
|
+
similarityScore: number;
|
|
69
|
+
/** Driver confidence in the comparison, in [0, 1]. */
|
|
70
|
+
confidence: number;
|
|
71
|
+
raw?: unknown;
|
|
72
|
+
}
|
|
73
|
+
/** A captured identity document (front and optional back) for a session. */
|
|
74
|
+
interface DocumentCapture extends Entity, ProjectScoped {
|
|
75
|
+
session_id: Id;
|
|
76
|
+
country: string | null;
|
|
77
|
+
document_type: DocumentType | null;
|
|
78
|
+
front_image_path: string | null;
|
|
79
|
+
back_image_path: string | null;
|
|
80
|
+
quality_score: number | null;
|
|
81
|
+
}
|
|
82
|
+
/** Persisted OCR output for a document capture. */
|
|
83
|
+
interface OcrResult extends Entity, ProjectScoped {
|
|
84
|
+
session_id: Id;
|
|
85
|
+
document_capture_id: Id;
|
|
86
|
+
fields: OcrFields;
|
|
87
|
+
confidence: number;
|
|
88
|
+
raw_response: unknown;
|
|
89
|
+
}
|
|
90
|
+
/** The portrait region extracted from a document, used for face matching. */
|
|
91
|
+
interface DocumentPortrait extends Entity, ProjectScoped {
|
|
92
|
+
session_id: Id;
|
|
93
|
+
document_capture_id: Id;
|
|
94
|
+
portrait_image_path: string;
|
|
95
|
+
detection_confidence: number;
|
|
96
|
+
}
|
|
97
|
+
/** Persisted passive-liveness result for a session. */
|
|
98
|
+
interface LivenessCheck extends Entity, ProjectScoped {
|
|
99
|
+
session_id: Id;
|
|
100
|
+
selfie_image_path: string | null;
|
|
101
|
+
video_path: string | null;
|
|
102
|
+
score: number;
|
|
103
|
+
passed: boolean;
|
|
104
|
+
spoof_signals: SpoofSignals;
|
|
105
|
+
provider: string;
|
|
106
|
+
raw_response: unknown;
|
|
107
|
+
}
|
|
108
|
+
/** Persisted face-match result comparing document portrait to selfie. */
|
|
109
|
+
interface FaceMatchCheck extends Entity, ProjectScoped {
|
|
110
|
+
session_id: Id;
|
|
111
|
+
id_portrait_image_path: string | null;
|
|
112
|
+
selfie_image_path: string | null;
|
|
113
|
+
similarity_score: number;
|
|
114
|
+
confidence: number;
|
|
115
|
+
passed: boolean;
|
|
116
|
+
provider: string;
|
|
117
|
+
raw_response: unknown;
|
|
118
|
+
}
|
|
119
|
+
//#endregion
|
|
120
|
+
export { DocumentCapture, DocumentPortrait, DocumentType, FaceMatchCheck, FaceMatchResultData, LivenessCheck, LivenessResultData, OcrAuthenticity, OcrFields, OcrResult, OcrResultData, SpoofSignals };
|
|
121
|
+
//# sourceMappingURL=providers.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.d.mts","names":[],"sources":["../src/providers.ts"],"mappings":";;;;KAGY,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,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"}
|
package/dist/rbac.d.mts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Entity, Id, OrganizationScoped } from "./common.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/rbac.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* The full catalogue of permission strings recognised by Arkyc.
|
|
6
|
+
*
|
|
7
|
+
* Permissions are grouped by domain (`<group>.<action>`). Effective access for
|
|
8
|
+
* a user is the union of their role permissions and any directly-assigned
|
|
9
|
+
* permissions (see `@arkyc/permissions`).
|
|
10
|
+
*/
|
|
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';
|
|
12
|
+
/** The domain groups permissions are organised under. */
|
|
13
|
+
type PermissionGroup = 'organizations' | 'members' | 'projects' | 'api_keys' | 'webhooks' | 'workflows' | 'sessions' | 'reviews' | 'audit_logs' | 'settings' | 'billing';
|
|
14
|
+
/** The built-in system roles seeded for every organization. */
|
|
15
|
+
type SystemRoleSlug = 'owner' | 'admin' | 'reviewer' | 'developer' | 'readonly';
|
|
16
|
+
/**
|
|
17
|
+
* Platform-scope permission strings, distinct from organization {@link PermissionKey}.
|
|
18
|
+
* These gate the super-admin surface above organizations and are only ever granted
|
|
19
|
+
* through {@link AdminPermission} (never an organization role). Rows carry `admin: true`.
|
|
20
|
+
*/
|
|
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.ai_processing.view' | 'admin.ai_processing.manage';
|
|
22
|
+
/** The domain groups platform-admin permissions are organised under. */
|
|
23
|
+
type AdminPermissionGroup = 'admin.organizations' | 'admin.users' | 'admin.settings' | 'admin.audit' | 'admin.billing' | 'admin.ai_processing';
|
|
24
|
+
/** Any permission string, organization- or platform-scope. */
|
|
25
|
+
type AnyPermissionKey = PermissionKey | AdminPermissionKey;
|
|
26
|
+
/** Any permission group, organization- or platform-scope. */
|
|
27
|
+
type AnyPermissionGroup = PermissionGroup | AdminPermissionGroup;
|
|
28
|
+
/** The built-in platform-admin role slug. */
|
|
29
|
+
type AdminRoleSlug = 'platform-owner';
|
|
30
|
+
/** A permission definition row. Permissions are global (not organization-scoped). */
|
|
31
|
+
interface Permission extends Entity {
|
|
32
|
+
/** The permission string, e.g. `sessions.view` or `admin.settings.view`. */
|
|
33
|
+
name: AnyPermissionKey;
|
|
34
|
+
description: string | null;
|
|
35
|
+
group: AnyPermissionGroup;
|
|
36
|
+
/** Platform-scope permission (gates the super-admin surface). */
|
|
37
|
+
admin: boolean;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A role within an organization. System roles (`is_system`) are seeded and cannot be
|
|
41
|
+
* deleted; organizations may also define custom roles.
|
|
42
|
+
*/
|
|
43
|
+
interface Role extends Entity {
|
|
44
|
+
/** Null for platform-admin roles (`admin: true`); set for organization roles. */
|
|
45
|
+
organization_id: Id | null;
|
|
46
|
+
name: string;
|
|
47
|
+
slug: string;
|
|
48
|
+
description: string | null;
|
|
49
|
+
is_system: boolean;
|
|
50
|
+
/** Platform-admin role (not organization-scoped). */
|
|
51
|
+
admin: boolean;
|
|
52
|
+
}
|
|
53
|
+
/** Join row granting a {@link Permission} to a {@link Role}. */
|
|
54
|
+
interface RolePermission extends Entity {
|
|
55
|
+
role_id: Id;
|
|
56
|
+
permission_id: Id;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A permission assigned directly to a user, on top of their role permissions.
|
|
60
|
+
* `project_id` is null for organization-level grants, set for project-level grants.
|
|
61
|
+
*/
|
|
62
|
+
interface UserPermission extends Entity, OrganizationScoped {
|
|
63
|
+
project_id: Id | null;
|
|
64
|
+
user_id: Id;
|
|
65
|
+
permission_id: Id;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* A platform-admin grant to a user. Mirrors {@link UserPermission} but without
|
|
69
|
+
* organization/project scope. A row is EITHER a role grant (`role_id` set) or a direct
|
|
70
|
+
* permission grant (`permission_id` set). Effective admin access is the union of
|
|
71
|
+
* both, resolved by `@arkyc/permissions`.
|
|
72
|
+
*/
|
|
73
|
+
interface AdminPermission extends Entity {
|
|
74
|
+
user_id: Id;
|
|
75
|
+
permission_id: Id | null;
|
|
76
|
+
role_id: Id | null;
|
|
77
|
+
}
|
|
78
|
+
//#endregion
|
|
79
|
+
export { AdminPermission, AdminPermissionGroup, AdminPermissionKey, AdminRoleSlug, AnyPermissionGroup, AnyPermissionKey, Permission, PermissionGroup, PermissionKey, Role, RolePermission, SystemRoleSlug, UserPermission };
|
|
80
|
+
//# sourceMappingURL=rbac.d.mts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Id } from "./common.mjs";
|
|
2
|
+
import { VerificationStatus } from "./verification.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/realtime.d.ts
|
|
5
|
+
/**
|
|
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.
|
|
9
|
+
*/
|
|
10
|
+
/** 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). */
|
|
13
|
+
readonly reviewAction: "review.action";
|
|
14
|
+
};
|
|
15
|
+
type RealtimeEventName = (typeof REALTIME_EVENT)[keyof typeof REALTIME_EVENT];
|
|
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.
|
|
19
|
+
*/
|
|
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). */
|
|
23
|
+
session: (sessionId: Id) => string;
|
|
24
|
+
};
|
|
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
|
+
/** Payload for {@link REALTIME_EVENT.sessionTransition}. */
|
|
38
|
+
interface SessionTransitionEvent {
|
|
39
|
+
session_id: Id;
|
|
40
|
+
organization_id: Id;
|
|
41
|
+
project_id: Id | null;
|
|
42
|
+
status: VerificationStatus;
|
|
43
|
+
previous_status: VerificationStatus | null;
|
|
44
|
+
}
|
|
45
|
+
/** Payload for {@link REALTIME_EVENT.reviewAction}. */
|
|
46
|
+
interface ReviewActionEvent {
|
|
47
|
+
session_id: Id;
|
|
48
|
+
organization_id: Id;
|
|
49
|
+
project_id: Id | null;
|
|
50
|
+
/** The audit action, e.g. `review.assigned`, `review.note`, `review.approved`. */
|
|
51
|
+
action: string;
|
|
52
|
+
actor_id: Id | null;
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
export { REALTIME_EVENT, RealtimeEventName, ReviewActionEvent, SessionTransitionEvent, parseRealtimeChannel, realtimeChannels };
|
|
56
|
+
//# sourceMappingURL=realtime.d.mts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
//#region src/realtime.ts
|
|
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.
|
|
6
|
+
*/
|
|
7
|
+
/** Events the API broadcasts. Clients react by invalidating their caches. */
|
|
8
|
+
const REALTIME_EVENT = {
|
|
9
|
+
/** A verification session changed status (the `transitionTo` choke point). */
|
|
10
|
+
sessionTransition: "session.transition",
|
|
11
|
+
/** A reviewer acted on a session (assign/note/suspicious/decision/retry). */
|
|
12
|
+
reviewAction: "review.action"
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
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.
|
|
17
|
+
*/
|
|
18
|
+
const realtimeChannels = {
|
|
19
|
+
/** Everything in an organization. */
|
|
20
|
+
organization: (organizationId) => `private-organization-${organizationId}`,
|
|
21
|
+
/** Everything in a project. */
|
|
22
|
+
project: (organizationId, projectId) => `private-organization-${organizationId}-project-${projectId}`,
|
|
23
|
+
/** A single verification session (used by the widget via client token). */
|
|
24
|
+
session: (sessionId) => `private-session-${sessionId}`
|
|
25
|
+
};
|
|
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
|
+
//#endregion
|
|
47
|
+
export { REALTIME_EVENT, parseRealtimeChannel, realtimeChannels };
|
|
48
|
+
|
|
49
|
+
//# sourceMappingURL=realtime.mjs.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Entity, Id, ProjectScoped } from "./common.mjs";
|
|
2
|
+
import { VerificationStatus } from "./verification.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/review.d.ts
|
|
5
|
+
/** 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';
|
|
7
|
+
/**
|
|
8
|
+
* An audited review action recording a status transition performed by a
|
|
9
|
+
* reviewer (or the system) on a session.
|
|
10
|
+
*/
|
|
11
|
+
interface Review extends Entity, ProjectScoped {
|
|
12
|
+
session_id: Id;
|
|
13
|
+
reviewer_id: Id | null;
|
|
14
|
+
previous_status: VerificationStatus;
|
|
15
|
+
new_status: VerificationStatus;
|
|
16
|
+
reason: string | null;
|
|
17
|
+
note: string | null;
|
|
18
|
+
}
|
|
19
|
+
/** A free-standing reviewer note attached to a session. */
|
|
20
|
+
interface ReviewNote extends Entity, ProjectScoped {
|
|
21
|
+
session_id: Id;
|
|
22
|
+
reviewer_id: Id;
|
|
23
|
+
note: string;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { Review, ReviewAction, ReviewNote };
|
|
27
|
+
//# sourceMappingURL=review.d.mts.map
|
|
@@ -0,0 +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"}
|
package/dist/sdk.d.mts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Metadata } from "./common.mjs";
|
|
2
|
+
import { VerificationDecision, VerificationStatus } from "./verification.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/sdk.d.ts
|
|
5
|
+
/** Options for constructing the server SDK client (`new Arkyc(...)`). */
|
|
6
|
+
interface SdkOptions {
|
|
7
|
+
/** Project secret key, e.g. `sk_live_…`. */
|
|
8
|
+
secretKey: string;
|
|
9
|
+
/** API base URL; defaults to the hosted Arkyc API. */
|
|
10
|
+
baseUrl?: string;
|
|
11
|
+
/** Request timeout in milliseconds. */
|
|
12
|
+
timeoutMs?: number;
|
|
13
|
+
}
|
|
14
|
+
/** Parameters for creating a verification session from a backend. */
|
|
15
|
+
interface CreateSessionParams {
|
|
16
|
+
userReference?: string;
|
|
17
|
+
metadata?: Metadata;
|
|
18
|
+
/** Optional override for how long the session/client token stays valid. */
|
|
19
|
+
expiresInSeconds?: number;
|
|
20
|
+
}
|
|
21
|
+
/** The session representation returned by the SDK/public API. */
|
|
22
|
+
interface SessionResource {
|
|
23
|
+
id: string;
|
|
24
|
+
status: VerificationStatus;
|
|
25
|
+
user_reference: string | null;
|
|
26
|
+
decision: VerificationDecision | null;
|
|
27
|
+
/** Short-lived client token for launching the widget (create response only). */
|
|
28
|
+
client_token?: string;
|
|
29
|
+
expires_at: string;
|
|
30
|
+
created_at: string;
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { CreateSessionParams, SdkOptions, SessionResource };
|
|
34
|
+
//# sourceMappingURL=sdk.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.d.mts","names":[],"sources":["../src/sdk.ts"],"mappings":";;;;;UAIiB,UAAA;EAAA;EAEf,SAAA;;EAEA,OAAA;EAFA;EAIA,SAAA;AAAA;;UAIe,mBAAA;EACf,aAAA;EACA,QAAA,GAAW,QAAQ;;EAEnB,gBAAA;AAAA;;UAIe,eAAA;EACf,EAAA;EACA,MAAA,EAAQ,kBAAA;EACR,cAAA;EACA,QAAA,EAAU,oBAAoB;EAJA;EAM9B,YAAA;EACA,UAAA;EACA,UAAA;AAAA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Entity } from "./common.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/settings.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Realtime transport for verification events (Phase 16). `pusher` covers both
|
|
6
|
+
* hosted Pusher Channels (default, via a cluster) and self-hosted soketi (opt-in,
|
|
7
|
+
* via a host) — they share the Pusher protocol. `polling` carries no push
|
|
8
|
+
* transport: clients poll the session endpoint instead (a universal fallback that
|
|
9
|
+
* needs no infrastructure). `off` disables live updates entirely.
|
|
10
|
+
*/
|
|
11
|
+
type RealtimeTransport = 'pusher' | 'firebase' | 'polling' | 'off';
|
|
12
|
+
/**
|
|
13
|
+
* Which capture/liveness flow the widget offers (Phase 17). `passive` = the
|
|
14
|
+
* current selfie flow; `active` = guided active-liveness challenges; `both` =
|
|
15
|
+
* offer active, falling back to passive on failure/unsupported devices.
|
|
16
|
+
*/
|
|
17
|
+
type CaptureModel = 'passive' | 'active' | 'both';
|
|
18
|
+
/**
|
|
19
|
+
* Platform-wide settings, managed by platform admins on the `/admin` surface and
|
|
20
|
+
* read by the app at runtime. A single typed record (see {@link GlobalSetting}),
|
|
21
|
+
* always merged over {@link DEFAULT_GLOBAL_SETTINGS} so every key is present.
|
|
22
|
+
*/
|
|
23
|
+
interface GlobalSettings {
|
|
24
|
+
/** Branding/basics for the whole platform. */
|
|
25
|
+
platform: {
|
|
26
|
+
name: string;
|
|
27
|
+
support_email: string | null; /** Whether new organization sign-ups are accepted. */
|
|
28
|
+
signups_enabled: boolean;
|
|
29
|
+
};
|
|
30
|
+
/** Realtime delivery configuration (consumed in Phase 16). */
|
|
31
|
+
realtime: {
|
|
32
|
+
transport: RealtimeTransport;
|
|
33
|
+
};
|
|
34
|
+
/** Default capture/liveness flow offered to widgets (Phase 17). */
|
|
35
|
+
capture: {
|
|
36
|
+
model: CaptureModel;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/** The persisted singleton row backing {@link GlobalSettings}. */
|
|
40
|
+
interface GlobalSetting extends Entity {
|
|
41
|
+
settings: GlobalSettings;
|
|
42
|
+
}
|
|
43
|
+
/** Defaults applied when a settings key is unset. */
|
|
44
|
+
declare const DEFAULT_GLOBAL_SETTINGS: GlobalSettings;
|
|
45
|
+
//#endregion
|
|
46
|
+
export { CaptureModel, DEFAULT_GLOBAL_SETTINGS, GlobalSetting, GlobalSettings, RealtimeTransport };
|
|
47
|
+
//# sourceMappingURL=settings.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.d.mts","names":[],"sources":["../src/settings.ts"],"mappings":";;;;;AASA;;;;AAA6B;KAAjB,iBAAA;;;;AAOY;AAOxB;KAPY,YAAA;;;;;;UAOK,cAAA;EASf;EAPA,QAAA;IACE,IAAA;IACA,aAAA,iBAUA;IARA,eAAA;EAAA;EAQmB;EALrB,QAAA;IACE,SAAA,EAAW,iBAAA;EAAA;EAS8B;EAN3C,OAAA;IACE,KAAA,EAAO,YAAY;EAAA;AAAA;AAMG;AAAA,UADT,aAAA,SAAsB,MAAM;EAC3C,QAAA,EAAU,cAAA;AAAA;;cAIC,uBAAA,EAAyB,cAYrC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/settings.ts
|
|
2
|
+
/** Defaults applied when a settings key is unset. */
|
|
3
|
+
const DEFAULT_GLOBAL_SETTINGS = {
|
|
4
|
+
platform: {
|
|
5
|
+
name: "Arkyc",
|
|
6
|
+
support_email: null,
|
|
7
|
+
signups_enabled: true
|
|
8
|
+
},
|
|
9
|
+
realtime: { transport: "off" },
|
|
10
|
+
capture: { model: "passive" }
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
export { DEFAULT_GLOBAL_SETTINGS };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=settings.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.mjs","names":[],"sources":["../src/settings.ts"],"sourcesContent":["import type { Entity } from './common'\n\n/**\n * Realtime transport for verification events (Phase 16). `pusher` covers both\n * hosted Pusher Channels (default, via a cluster) and self-hosted soketi (opt-in,\n * via a host) — they share the Pusher protocol. `polling` carries no push\n * transport: clients poll the session endpoint instead (a universal fallback that\n * needs no infrastructure). `off` disables live updates entirely.\n */\nexport type RealtimeTransport = 'pusher' | 'firebase' | 'polling' | 'off'\n\n/**\n * Which capture/liveness flow the widget offers (Phase 17). `passive` = the\n * current selfie flow; `active` = guided active-liveness challenges; `both` =\n * offer active, falling back to passive on failure/unsupported devices.\n */\nexport type CaptureModel = 'passive' | 'active' | 'both'\n\n/**\n * Platform-wide settings, managed by platform admins on the `/admin` surface and\n * read by the app at runtime. A single typed record (see {@link GlobalSetting}),\n * always merged over {@link DEFAULT_GLOBAL_SETTINGS} so every key is present.\n */\nexport interface GlobalSettings {\n /** Branding/basics for the whole platform. */\n platform: {\n name: string\n support_email: string | null\n /** Whether new organization sign-ups are accepted. */\n signups_enabled: boolean\n }\n /** Realtime delivery configuration (consumed in Phase 16). */\n realtime: {\n transport: RealtimeTransport\n }\n /** Default capture/liveness flow offered to widgets (Phase 17). */\n capture: {\n model: CaptureModel\n }\n}\n\n/** The persisted singleton row backing {@link GlobalSettings}. */\nexport interface GlobalSetting extends Entity {\n settings: GlobalSettings\n}\n\n/** Defaults applied when a settings key is unset. */\nexport const DEFAULT_GLOBAL_SETTINGS: GlobalSettings = {\n platform: {\n name: 'Arkyc',\n support_email: null,\n signups_enabled: true,\n },\n realtime: {\n transport: 'off',\n },\n capture: {\n model: 'passive',\n },\n}\n"],"mappings":";;AA+CA,MAAa,0BAA0C;CACrD,UAAU;EACR,MAAM;EACN,eAAe;EACf,iBAAiB;CACnB;CACA,UAAU,EACR,WAAW,MACb;CACA,SAAS,EACP,OAAO,UACT;AACF"}
|
package/dist/user.d.mts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Entity, IsoDateTime } from "./common.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/user.d.ts
|
|
4
|
+
/** A platform user account. Users belong to one or more organizations via membership. */
|
|
5
|
+
interface User extends Entity {
|
|
6
|
+
name: string;
|
|
7
|
+
email: string;
|
|
8
|
+
/** Never serialised to clients; present on the DB row only. */
|
|
9
|
+
password_hash?: string;
|
|
10
|
+
avatar_url: string | null;
|
|
11
|
+
last_login_at: IsoDateTime | null;
|
|
12
|
+
}
|
|
13
|
+
/** A user shape safe to expose to clients (no credential material). */
|
|
14
|
+
type PublicUser = Omit<User, 'password_hash'>;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { PublicUser, User };
|
|
17
|
+
//# sourceMappingURL=user.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.d.mts","names":[],"sources":["../src/user.ts"],"mappings":";;;;UAGiB,IAAA,SAAa,MAAM;EAClC,IAAA;EACA,KAAA;;EAEA,aAAA;EACA,UAAA;EACA,aAAA,EAAe,WAAA;AAAA;;KAIL,UAAA,GAAa,IAAI,CAAC,IAAA"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Entity, Id, IsoDateTime, Metadata, ProjectScoped } from "./common.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/verification.d.ts
|
|
4
|
+
/** The lifecycle state of a verification session. */
|
|
5
|
+
type VerificationStatus = 'pending' | 'started' | 'document_submitted' | 'liveness_submitted' | 'processing' | 'requires_review' | 'approved' | 'rejected' | 'expired' | 'cancelled';
|
|
6
|
+
/** The outcome of the decision engine (or a manual review). */
|
|
7
|
+
type VerificationDecision = 'approved' | 'requires_review' | 'rejected';
|
|
8
|
+
/** Whether liveness is checked passively (a selfie) or actively (a challenge video). */
|
|
9
|
+
type LivenessMode = 'passive' | 'active';
|
|
10
|
+
/**
|
|
11
|
+
* A single active-liveness challenge the user is prompted to perform. The server
|
|
12
|
+
* issues a randomized sequence per session; the widget records the user doing
|
|
13
|
+
* them and submits the sequence it performed for the driver to validate.
|
|
14
|
+
*/
|
|
15
|
+
type LivenessChallenge = 'turn_left' | 'turn_right' | 'blink' | 'smile' | 'nod' | 'move_closer';
|
|
16
|
+
/** Why a session reached its decision. */
|
|
17
|
+
type DecisionReason = 'AUTO_APPROVED' | 'LOW_DOCUMENT_QUALITY' | 'OCR_LOW_CONFIDENCE' | 'DOCUMENT_EXPIRED' | 'LIVENESS_FAILED' | 'LIVENESS_LOW_CONFIDENCE' | 'FACE_MATCH_FAILED' | 'FACE_MATCH_LOW_CONFIDENCE' | 'MULTIPLE_FACES_DETECTED' | 'MANUAL_APPROVAL' | 'MANUAL_REJECTION' | 'RETRY_REQUESTED';
|
|
18
|
+
/**
|
|
19
|
+
* A verification session: the full lifecycle of one verification flow, owned by
|
|
20
|
+
* a project (and organization). Created from an integrator's backend, driven by the
|
|
21
|
+
* widget, decided automatically and/or by a human reviewer.
|
|
22
|
+
*/
|
|
23
|
+
interface VerificationSession extends Entity, ProjectScoped {
|
|
24
|
+
/** Integrator's own reference for the end user being verified. */
|
|
25
|
+
user_reference: string | null;
|
|
26
|
+
/** Person's name extracted from the document (OCR), when available. */
|
|
27
|
+
name?: string | null;
|
|
28
|
+
status: VerificationStatus;
|
|
29
|
+
auto_decision: VerificationDecision | null;
|
|
30
|
+
final_decision: VerificationDecision | null;
|
|
31
|
+
decision_reason: DecisionReason | null;
|
|
32
|
+
/** Aggregate risk score in [0, 1]; higher means riskier. */
|
|
33
|
+
risk_score: number | null;
|
|
34
|
+
/** Hash of the short-lived client token issued to the widget. */
|
|
35
|
+
client_token_hash: string | null;
|
|
36
|
+
expires_at: IsoDateTime;
|
|
37
|
+
completed_at: IsoDateTime | null;
|
|
38
|
+
reviewed_at: IsoDateTime | null;
|
|
39
|
+
reviewed_by: Id | null;
|
|
40
|
+
metadata: Metadata;
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { DecisionReason, LivenessChallenge, LivenessMode, VerificationDecision, VerificationSession, VerificationStatus };
|
|
44
|
+
//# sourceMappingURL=verification.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification.d.mts","names":[],"sources":["../src/verification.ts"],"mappings":";;;;KAGY,kBAAA;AAAZ;AAAA,KAaY,oBAAA;;KAGA,YAAA;AAhBkB;AAa9B;;;;AAb8B,KAuBlB,iBAAA;AAPZ;AAAA,KAUY,cAAA;;;AAVY;AAOxB;;UAsBiB,mBAAA,SAA4B,MAAA,EAAQ,aAAA;EAtBxB;EAwB3B,cAAA;EArBU;EAuBV,IAAA;EACA,MAAA,EAAQ,kBAAA;EACR,aAAA,EAAe,oBAAA;EACf,cAAA,EAAgB,oBAAA;EAChB,eAAA,EAAiB,cAAA;EARkB;EAUnC,UAAA;EALQ;EAOR,iBAAA;EACA,UAAA,EAAY,WAAA;EACZ,YAAA,EAAc,WAAA;EACd,WAAA,EAAa,WAAA;EACb,WAAA,EAAa,EAAA;EACb,QAAA,EAAU,QAAA;AAAA"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Entity, Id, IsoDateTime, ProjectScoped } from "./common.mjs";
|
|
2
|
+
import { DecisionReason, VerificationStatus } from "./verification.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/webhook.d.ts
|
|
5
|
+
/** The set of webhook event names Arkyc can deliver. */
|
|
6
|
+
type WebhookEventName = 'verification.started' | 'verification.document_submitted' | 'verification.processing' | 'verification.requires_review' | 'verification.approved' | 'verification.rejected' | 'verification.completed' | 'verification.expired' | 'verification.cancelled';
|
|
7
|
+
/** Per-check summary included in a webhook payload. */
|
|
8
|
+
interface WebhookChecks {
|
|
9
|
+
document?: {
|
|
10
|
+
quality_score: number;
|
|
11
|
+
ocr_confidence: number;
|
|
12
|
+
expired: boolean; /** Which parser produced the OCR fields: the MRZ, a custom parser, or the generic scraper. */
|
|
13
|
+
ocr_parse_stage?: 'mrz' | 'custom' | 'generic';
|
|
14
|
+
};
|
|
15
|
+
liveness?: {
|
|
16
|
+
passed: boolean;
|
|
17
|
+
score: number;
|
|
18
|
+
};
|
|
19
|
+
face_match?: {
|
|
20
|
+
passed: boolean;
|
|
21
|
+
similarity_score: number;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/** The JSON body delivered to a webhook endpoint. */
|
|
25
|
+
interface WebhookEvent {
|
|
26
|
+
event: WebhookEventName;
|
|
27
|
+
session_id: Id;
|
|
28
|
+
organization_id: Id;
|
|
29
|
+
project_id: Id;
|
|
30
|
+
user_reference: string | null;
|
|
31
|
+
status: VerificationStatus;
|
|
32
|
+
checks: WebhookChecks;
|
|
33
|
+
decision_reason: DecisionReason | null;
|
|
34
|
+
/** Signed, time-limited URLs for captured assets, served inline as images (when any exist). */
|
|
35
|
+
assets: Record<string, string> | null;
|
|
36
|
+
created_at: IsoDateTime;
|
|
37
|
+
}
|
|
38
|
+
/** Webhook endpoint lifecycle status. */
|
|
39
|
+
type WebhookEndpointStatus = 'active' | 'disabled';
|
|
40
|
+
/** A configured webhook endpoint for a project. */
|
|
41
|
+
interface WebhookEndpoint extends Entity, ProjectScoped {
|
|
42
|
+
url: string;
|
|
43
|
+
/** Hash of the signing secret; the raw secret is shown once at creation. */
|
|
44
|
+
secret_hash: string;
|
|
45
|
+
events: WebhookEventName[];
|
|
46
|
+
status: WebhookEndpointStatus;
|
|
47
|
+
}
|
|
48
|
+
/** Delivery attempt state for a webhook. */
|
|
49
|
+
type WebhookDeliveryStatus = 'pending' | 'delivered' | 'failed';
|
|
50
|
+
/** A record of a webhook delivery (and its retries). */
|
|
51
|
+
interface WebhookDelivery extends Entity, ProjectScoped {
|
|
52
|
+
webhook_endpoint_id: Id;
|
|
53
|
+
event: WebhookEventName;
|
|
54
|
+
payload: WebhookEvent;
|
|
55
|
+
status: WebhookDeliveryStatus;
|
|
56
|
+
response_status: number | null;
|
|
57
|
+
response_body: string | null;
|
|
58
|
+
attempts: number;
|
|
59
|
+
next_retry_at: IsoDateTime | null;
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
export { WebhookChecks, WebhookDelivery, WebhookDeliveryStatus, WebhookEndpoint, WebhookEndpointStatus, WebhookEvent, WebhookEventName };
|
|
63
|
+
//# sourceMappingURL=webhook.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.d.mts","names":[],"sources":["../src/webhook.ts"],"mappings":";;;;;KAIY,gBAAA;AAAZ;AAAA,UAYiB,aAAA;EACf,QAAA;IACE,aAAA;IACA,cAAA;IACA,OAAA,WAJ0B;IAM1B,eAAA;EAAA;EAEF,QAAA;IACE,MAAA;IACA,KAAA;EAAA;EAEF,UAAA;IACE,MAAA;IACA,gBAAA;EAAA;AAAA;;UAKa,YAAA;EACf,KAAA,EAAO,gBAAA;EACP,UAAA,EAAY,EAAA;EACZ,eAAA,EAAiB,EAAA;EACjB,UAAA,EAAY,EAAA;EACZ,cAAA;EACA,MAAA,EAAQ,kBAAA;EACR,MAAA,EAAQ,aAAA;EACR,eAAA,EAAiB,cAAA;EAJL;EAMZ,MAAA,EAAQ,MAAA;EACR,UAAA,EAAY,WAAA;AAAA;;KAIF,qBAAA;;UAGK,eAAA,SAAwB,MAAA,EAAQ,aAAA;EAC/C,GAAA;EAlBO;EAoBP,WAAA;EACA,MAAA,EAAQ,gBAAA;EACR,MAAA,EAAQ,qBAAA;AAAA;;KAIE,qBAAA;;UAGK,eAAA,SAAwB,MAAA,EAAQ,aAAA;EAC/C,mBAAA,EAAqB,EAAA;EACrB,KAAA,EAAO,gBAAA;EACP,OAAA,EAAS,YAAA;EACT,MAAA,EAAQ,qBAAA;EACR,eAAA;EACA,aAAA;EACA,QAAA;EACA,aAAA,EAAe,WAAA;AAAA"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { VerificationDecision, VerificationStatus } from "./verification.mjs";
|
|
2
|
+
import { ProjectBranding } from "./project.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/widget.d.ts
|
|
5
|
+
/** How the widget mounts into the host page. */
|
|
6
|
+
type WidgetMode = 'overlay' | 'inline' | 'hosted';
|
|
7
|
+
/** The screens of the widget verification flow, in order. */
|
|
8
|
+
type WidgetStep = 'welcome' | 'document_selection' | 'front_capture' | 'back_capture' | 'ocr_processing' | 'active_liveness' | 'selfie_capture' | 'passive_liveness' | 'face_match' | 'processing' | 'result';
|
|
9
|
+
/** The result handed to the widget's `onComplete` callback. */
|
|
10
|
+
interface WidgetResult {
|
|
11
|
+
status: VerificationStatus;
|
|
12
|
+
decision: VerificationDecision | null;
|
|
13
|
+
}
|
|
14
|
+
/** Options for launching/mounting the embeddable widget. */
|
|
15
|
+
interface WidgetOptions {
|
|
16
|
+
/** Short-lived client token minted by the backend for this session. */
|
|
17
|
+
token: string;
|
|
18
|
+
mode?: WidgetMode;
|
|
19
|
+
/** Element (or selector) to mount into when `mode` is `inline`. */
|
|
20
|
+
container?: string | HTMLElement;
|
|
21
|
+
branding?: ProjectBranding;
|
|
22
|
+
baseUrl?: string;
|
|
23
|
+
onComplete?: (result: WidgetResult) => void;
|
|
24
|
+
onError?: (error: Error) => void;
|
|
25
|
+
onClose?: () => void;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { WidgetMode, WidgetOptions, WidgetResult, WidgetStep };
|
|
29
|
+
//# sourceMappingURL=widget.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget.d.mts","names":[],"sources":["../src/widget.ts"],"mappings":";;;;;KAIY,UAAA;AAAZ;AAAA,KAGY,UAAA;;UAcK,YAAA;EACf,MAAA,EAAQ,kBAAA;EACR,QAAA,EAAU,oBAAoB;AAAA;;UAIf,aAAA;EApBK;EAsBpB,KAAA;EACA,IAAA,GAAO,UAAA;;EAEP,SAAA,YAAqB,WAAA;EACrB,QAAA,GAAW,eAAA;EACX,OAAA;EACA,UAAA,IAAc,MAAA,EAAQ,YAAA;EACtB,OAAA,IAAW,KAAA,EAAO,KAAA;EAClB,OAAA;AAAA"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Id, IsoDateTime } from "./common.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/workflow.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Workflows (Phase 19).
|
|
6
|
+
*
|
|
7
|
+
* An organization-scoped, reusable recipe that determines the order of the
|
|
8
|
+
* coarse verification stages, lets each be turned off, and can skip OCR parsing
|
|
9
|
+
* (capture-only). Workflows are optional: a session created without one runs the
|
|
10
|
+
* default pipeline (document → liveness → face match, OCR on). A workflow's
|
|
11
|
+
* config is snapshotted onto each session at creation, so editing it never
|
|
12
|
+
* disturbs sessions already in flight.
|
|
13
|
+
*/
|
|
14
|
+
/** A coarse verification stage a workflow can order and toggle. */
|
|
15
|
+
type WorkflowStepKey = 'document' | 'liveness' | 'face_match';
|
|
16
|
+
/** The canonical stage order used as the default and to normalise stored steps. */
|
|
17
|
+
declare const WORKFLOW_STEP_KEYS: readonly WorkflowStepKey[];
|
|
18
|
+
/** One stage within a workflow, in pipeline order, on or off. */
|
|
19
|
+
interface WorkflowStep {
|
|
20
|
+
key: WorkflowStepKey;
|
|
21
|
+
enabled: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** Workflow-wide toggles. */
|
|
24
|
+
interface WorkflowOptions {
|
|
25
|
+
/**
|
|
26
|
+
* Skip OCR parsing — capture the document image but don't extract fields.
|
|
27
|
+
* Useful when Arkyc is only used for data capture and the assets are handed
|
|
28
|
+
* to a third party. Disables the document portrait too, so face match can't run.
|
|
29
|
+
*/
|
|
30
|
+
skip_ocr: boolean;
|
|
31
|
+
}
|
|
32
|
+
/** The portable config of a workflow: ordered stages + options. */
|
|
33
|
+
interface WorkflowConfig {
|
|
34
|
+
steps: WorkflowStep[];
|
|
35
|
+
options: WorkflowOptions;
|
|
36
|
+
}
|
|
37
|
+
/** A saved, organization-scoped workflow. */
|
|
38
|
+
interface Workflow extends WorkflowConfig {
|
|
39
|
+
id: Id;
|
|
40
|
+
organization_id: Id;
|
|
41
|
+
name: string;
|
|
42
|
+
created_at: IsoDateTime;
|
|
43
|
+
updated_at: IsoDateTime;
|
|
44
|
+
}
|
|
45
|
+
/** The default pipeline applied when a session has no workflow. */
|
|
46
|
+
declare const DEFAULT_WORKFLOW_CONFIG: WorkflowConfig;
|
|
47
|
+
/**
|
|
48
|
+
* Whether a stage runs under a config. A `null` config means "no workflow" — the
|
|
49
|
+
* default pipeline, where every stage runs. Within a real config, a stage that is
|
|
50
|
+
* absent or `enabled: false` does not run.
|
|
51
|
+
*/
|
|
52
|
+
declare function workflowEnables(config: WorkflowConfig | null | undefined, key: WorkflowStepKey): boolean;
|
|
53
|
+
/** Whether OCR parsing should run: the document stage is on and `skip_ocr` is off. */
|
|
54
|
+
declare function workflowRunsOcr(config: WorkflowConfig | null | undefined): boolean;
|
|
55
|
+
/** The enabled stages in pipeline order (used by the widget to sequence its steps). */
|
|
56
|
+
declare function workflowEnabledSteps(config: WorkflowConfig | null | undefined): WorkflowStepKey[];
|
|
57
|
+
//#endregion
|
|
58
|
+
export { DEFAULT_WORKFLOW_CONFIG, WORKFLOW_STEP_KEYS, Workflow, WorkflowConfig, WorkflowOptions, WorkflowStep, WorkflowStepKey, workflowEnabledSteps, workflowEnables, workflowRunsOcr };
|
|
59
|
+
//# sourceMappingURL=workflow.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow.d.mts","names":[],"sources":["../src/workflow.ts"],"mappings":";;;;;AAcA;;;;AAA2B;AAG3B;;;;KAHY,eAAA;AAMZ;AAAA,cAHa,kBAAA,WAA6B,eAAe;;UAGxC,YAAA;EACf,GAAA,EAAK,eAAe;EACpB,OAAA;AAAA;;UAIe,eAAA;EAAA;;;;AAMP;EAAR,QAAQ;AAAA;;UAIO,cAAA;EACf,KAAA,EAAO,YAAA;EACP,OAAA,EAAS,eAAe;AAAA;;UAIT,QAAA,SAAiB,cAAA;EAChC,EAAA,EAAI,EAAA;EACJ,eAAA,EAAiB,EAAA;EACjB,IAAA;EACA,UAAA,EAAY,WAAA;EACZ,UAAA,EAAY,WAAA;AAAA;;cAID,uBAAA,EAAyB,cAOrC;;;;;;iBAOe,eAAA,CAAgB,MAAA,EAAQ,cAAA,qBAAmC,GAAA,EAAK,eAAe;;iBAO/E,eAAA,CAAgB,MAAyC,EAAjC,cAAc;;iBAOtC,oBAAA,CAAqB,MAAA,EAAQ,cAAA,sBAAoC,eAAe"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
//#region src/workflow.ts
|
|
2
|
+
/** The canonical stage order used as the default and to normalise stored steps. */
|
|
3
|
+
const WORKFLOW_STEP_KEYS = [
|
|
4
|
+
"document",
|
|
5
|
+
"liveness",
|
|
6
|
+
"face_match"
|
|
7
|
+
];
|
|
8
|
+
/** The default pipeline applied when a session has no workflow. */
|
|
9
|
+
const DEFAULT_WORKFLOW_CONFIG = {
|
|
10
|
+
steps: [
|
|
11
|
+
{
|
|
12
|
+
key: "document",
|
|
13
|
+
enabled: true
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
key: "liveness",
|
|
17
|
+
enabled: true
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
key: "face_match",
|
|
21
|
+
enabled: true
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
options: { skip_ocr: false }
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Whether a stage runs under a config. A `null` config means "no workflow" — the
|
|
28
|
+
* default pipeline, where every stage runs. Within a real config, a stage that is
|
|
29
|
+
* absent or `enabled: false` does not run.
|
|
30
|
+
*/
|
|
31
|
+
function workflowEnables(config, key) {
|
|
32
|
+
if (!config) return true;
|
|
33
|
+
return config.steps.some((step) => step.key === key && step.enabled);
|
|
34
|
+
}
|
|
35
|
+
/** Whether OCR parsing should run: the document stage is on and `skip_ocr` is off. */
|
|
36
|
+
function workflowRunsOcr(config) {
|
|
37
|
+
if (!config) return true;
|
|
38
|
+
return workflowEnables(config, "document") && !config.options.skip_ocr;
|
|
39
|
+
}
|
|
40
|
+
/** The enabled stages in pipeline order (used by the widget to sequence its steps). */
|
|
41
|
+
function workflowEnabledSteps(config) {
|
|
42
|
+
if (!config) return [...WORKFLOW_STEP_KEYS];
|
|
43
|
+
return config.steps.filter((step) => step.enabled).map((step) => step.key);
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
export { DEFAULT_WORKFLOW_CONFIG, WORKFLOW_STEP_KEYS, workflowEnabledSteps, workflowEnables, workflowRunsOcr };
|
|
47
|
+
|
|
48
|
+
//# sourceMappingURL=workflow.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow.mjs","names":[],"sources":["../src/workflow.ts"],"sourcesContent":["import type { Id, IsoDateTime } from './common'\n\n/**\n * Workflows (Phase 19).\n *\n * An organization-scoped, reusable recipe that determines the order of the\n * coarse verification stages, lets each be turned off, and can skip OCR parsing\n * (capture-only). Workflows are optional: a session created without one runs the\n * default pipeline (document → liveness → face match, OCR on). A workflow's\n * config is snapshotted onto each session at creation, so editing it never\n * disturbs sessions already in flight.\n */\n\n/** A coarse verification stage a workflow can order and toggle. */\nexport type WorkflowStepKey = 'document' | 'liveness' | 'face_match'\n\n/** The canonical stage order used as the default and to normalise stored steps. */\nexport const WORKFLOW_STEP_KEYS: readonly WorkflowStepKey[] = ['document', 'liveness', 'face_match']\n\n/** One stage within a workflow, in pipeline order, on or off. */\nexport interface WorkflowStep {\n key: WorkflowStepKey\n enabled: boolean\n}\n\n/** Workflow-wide toggles. */\nexport interface WorkflowOptions {\n /**\n * Skip OCR parsing — capture the document image but don't extract fields.\n * Useful when Arkyc is only used for data capture and the assets are handed\n * to a third party. Disables the document portrait too, so face match can't run.\n */\n skip_ocr: boolean\n}\n\n/** The portable config of a workflow: ordered stages + options. */\nexport interface WorkflowConfig {\n steps: WorkflowStep[]\n options: WorkflowOptions\n}\n\n/** A saved, organization-scoped workflow. */\nexport interface Workflow extends WorkflowConfig {\n id: Id\n organization_id: Id\n name: string\n created_at: IsoDateTime\n updated_at: IsoDateTime\n}\n\n/** The default pipeline applied when a session has no workflow. */\nexport const DEFAULT_WORKFLOW_CONFIG: WorkflowConfig = {\n steps: [\n { key: 'document', enabled: true },\n { key: 'liveness', enabled: true },\n { key: 'face_match', enabled: true },\n ],\n options: { skip_ocr: false },\n}\n\n/**\n * Whether a stage runs under a config. A `null` config means \"no workflow\" — the\n * default pipeline, where every stage runs. Within a real config, a stage that is\n * absent or `enabled: false` does not run.\n */\nexport function workflowEnables(config: WorkflowConfig | null | undefined, key: WorkflowStepKey): boolean {\n if (!config) return true\n\n return config.steps.some((step) => step.key === key && step.enabled)\n}\n\n/** Whether OCR parsing should run: the document stage is on and `skip_ocr` is off. */\nexport function workflowRunsOcr(config: WorkflowConfig | null | undefined): boolean {\n if (!config) return true\n\n return workflowEnables(config, 'document') && !config.options.skip_ocr\n}\n\n/** The enabled stages in pipeline order (used by the widget to sequence its steps). */\nexport function workflowEnabledSteps(config: WorkflowConfig | null | undefined): WorkflowStepKey[] {\n if (!config) return [...WORKFLOW_STEP_KEYS]\n\n return config.steps.filter((step) => step.enabled).map((step) => step.key)\n}\n"],"mappings":";;AAiBA,MAAa,qBAAiD;CAAC;CAAY;CAAY;AAAY;;AAkCnG,MAAa,0BAA0C;CACrD,OAAO;EACL;GAAE,KAAK;GAAY,SAAS;EAAK;EACjC;GAAE,KAAK;GAAY,SAAS;EAAK;EACjC;GAAE,KAAK;GAAc,SAAS;EAAK;CACrC;CACA,SAAS,EAAE,UAAU,MAAM;AAC7B;;;;;;AAOA,SAAgB,gBAAgB,QAA2C,KAA+B;CACxG,IAAI,CAAC,QAAQ,OAAO;CAEpB,OAAO,OAAO,MAAM,MAAM,SAAS,KAAK,QAAQ,OAAO,KAAK,OAAO;AACrE;;AAGA,SAAgB,gBAAgB,QAAoD;CAClF,IAAI,CAAC,QAAQ,OAAO;CAEpB,OAAO,gBAAgB,QAAQ,UAAU,KAAK,CAAC,OAAO,QAAQ;AAChE;;AAGA,SAAgB,qBAAqB,QAA8D;CACjG,IAAI,CAAC,QAAQ,OAAO,CAAC,GAAG,kBAAkB;CAE1C,OAAO,OAAO,MAAM,QAAQ,SAAS,KAAK,OAAO,CAAC,CAAC,KAAK,SAAS,KAAK,GAAG;AAC3E"}
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@arkyc/types",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Shared domain types and contracts for Arkyc",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.mjs",
|
|
8
|
+
"module": "./dist/index.mjs",
|
|
9
|
+
"types": "./dist/index.d.mts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.mts",
|
|
13
|
+
"import": "./dist/index.mjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"typecheck": "tsc --noEmit",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"lint": "eslint src",
|
|
23
|
+
"clean": "rm -rf dist"
|
|
24
|
+
}
|
|
25
|
+
}
|