@kernaq/verify-react-native 2.0.0 → 2.0.2

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/README.md CHANGED
@@ -159,7 +159,7 @@ Never expose a live API key in your app. Instead, forward requests through your
159
159
  />
160
160
  ```
161
161
 
162
- Your backend endpoint receives a `multipart/form-data` POST with `document`, `selfie`, `video`, `document_type`, `country`, and `reference` fields. Forward it to `https://api.identity.kernaq.com/v1/verify` with your secret key.
162
+ Your backend endpoint receives a `multipart/form-data` POST with `doc_front`, `doc_back`, `selfie`, `video`, `document_type`, `country`, and `reference` fields. Forward it to `https://api.identity.kernaq.com/v1/verify` with your secret key.
163
163
 
164
164
  ## Result object
165
165
 
package/dist/index.d.ts CHANGED
@@ -1,9 +1,13 @@
1
1
  import React from 'react';
2
2
 
3
3
  /**
4
- * @kernaq/verify-react-native — public types
4
+ * @kernaq/verify-react-native — public types (v2)
5
5
  */
6
- type VerifyStep = 'intro' | 'document' | 'selfie' | 'liveness' | 'processing' | 'result';
6
+ type VerifyStep = 'intro' | 'doc-front' | 'doc-back' | 'selfie' | 'liveness' | 'processing' | 'result';
7
+ /** Which capture steps to include. Default: all three. */
8
+ type VerifyStepName = 'document' | 'selfie' | 'liveness';
9
+ /** Liveness challenge tasks */
10
+ type LivenessTask = 'blink' | 'turn-left' | 'turn-right' | 'nod' | 'open-mouth';
7
11
  type DocumentType = 'national_id' | 'passport' | 'driver_license' | 'alien_card';
8
12
  type VerifyVerdict = 'pass' | 'fail' | 'review';
9
13
  interface VerifyResult {
@@ -16,84 +20,64 @@ interface VerifyResult {
16
20
  documentFields?: Record<string, string>;
17
21
  }
18
22
  interface VerifyTheme {
19
- /** Primary accent colour. Default: #111827 */
20
23
  accentColor?: string;
21
- /** Modal background. Default: #ffffff */
22
24
  backgroundColor?: string;
23
- /** Primary text colour. Default: #111827 */
24
25
  textColor?: string;
25
- /** Subtle text colour. Default: #6b7280 */
26
26
  subtextColor?: string;
27
- /** Border/divider colour. Default: #e5e7eb */
28
27
  borderColor?: string;
29
- /** Card/surface colour. Default: #f9fafb */
30
28
  cardColor?: string;
31
- /** Border radius for buttons and cards. Default: 12 */
32
29
  borderRadius?: number;
33
- /** 'light' | 'dark' — overrides bg/text when set */
30
+ /** 'light' | 'dark' */
34
31
  mode?: 'light' | 'dark';
35
32
  }
36
33
  interface VerifyLocale {
37
34
  intro_title: string;
38
35
  intro_body: string;
39
36
  intro_cta: string;
40
- doc_title: string;
41
- doc_instruction: string;
37
+ doc_front_title: string;
38
+ doc_front_instruction: string;
39
+ doc_back_title: string;
40
+ doc_back_instruction: string;
42
41
  doc_capture_btn: string;
43
42
  doc_retake_btn: string;
44
- doc_next_btn: string;
45
43
  selfie_title: string;
46
44
  selfie_instruction: string;
47
- selfie_capture_btn: string;
48
- selfie_retake_btn: string;
49
- selfie_next_btn: string;
50
45
  liveness_title: string;
51
- liveness_instruction: string;
52
- liveness_start_btn: string;
53
- liveness_recording: string;
46
+ liveness_ready: string;
47
+ liveness_task_prefix: string;
48
+ liveness_complete: string;
54
49
  processing_title: string;
55
- processing_subtitle: string;
56
50
  result_pass_title: string;
57
51
  result_pass_body: string;
58
52
  result_fail_title: string;
59
53
  result_fail_body: string;
60
54
  result_review_title: string;
61
55
  result_review_body: string;
62
- result_retry_btn: string;
63
56
  error_camera_denied: string;
57
+ error_blur: string;
64
58
  error_quality: string;
65
59
  error_network: string;
66
60
  }
67
61
  interface VerifyConfig {
68
- /**
69
- * Your Kernaq publishable API key (k_test_... or k_live_...).
70
- * For production use a backend proxy and pass backendUrl instead.
71
- */
72
62
  apiKey?: string;
73
- /**
74
- * URL of your backend proxy that forwards to the Kernaq Identity API.
75
- * POST /verify with multipart/form-data.
76
- */
77
63
  backendUrl?: string;
78
- /** Document types the user can select. Default: ['national_id', 'passport'] */
79
- documentTypes?: DocumentType[];
80
- /** Country code (ISO 3166-1 alpha-3). Default: 'KEN' */
64
+ /** Single document type the developer specifies. Default: 'national_id' */
65
+ documentType?: DocumentType;
81
66
  country?: string;
82
- /** Your internal reference ID for this user/session */
83
67
  reference?: string;
84
- /** Use sandbox mode — no billing, test responses */
85
68
  sandbox?: boolean;
86
- /** Liveness recording duration in ms. Default: 3000 */
87
69
  livenessDuration?: number;
88
- /** Theming */
70
+ /** Number of liveness tasks. Default: 2 */
71
+ livenessTaskCount?: number;
72
+ /**
73
+ * Which steps to include. Default: all three.
74
+ * @example steps={['selfie', 'liveness']}
75
+ */
76
+ steps?: VerifyStepName[];
89
77
  theme?: VerifyTheme;
90
- /** Override any displayed string */
91
78
  locale?: Partial<VerifyLocale>;
92
- /** Called when the user dismisses without completing */
93
79
  onCancel?: () => void;
94
- /** Called when verification is complete */
95
80
  onComplete?: (result: VerifyResult) => void;
96
- /** Called on unrecoverable error */
97
81
  onError?: (error: {
98
82
  code: string;
99
83
  message: string;
@@ -101,25 +85,86 @@ interface VerifyConfig {
101
85
  }
102
86
 
103
87
  /**
104
- * <KernaqVerify /> — drop-in identity verification modal for React Native.
88
+ * <KernaqVerify /> — drop-in identity verification modal for React Native (v2).
105
89
  *
106
- * Usage:
107
- * import { KernaqVerify } from '@kernaq/verify-react-native'
90
+ * Matches @kernaq/verify web v2.0.0:
91
+ * - No header / logo
92
+ * - No progress bar
93
+ * - No cancel/close button — user must complete the flow
94
+ * - Front + back document capture
95
+ * - Auto-capture selfie with guidance pill
96
+ * - Randomised liveness tasks with in-viewport overlay
97
+ * - Configurable steps prop
98
+ * - "Secured by Kernaq" footer only
108
99
  *
100
+ * Usage:
109
101
  * <KernaqVerify
110
- * visible={showVerify}
111
- * apiKey="k_test_..."
102
+ * visible={show}
103
+ * documentType="national_id"
112
104
  * country="KEN"
113
105
  * reference={userId}
114
- * onComplete={(result) => console.log(result.verdict)}
115
- * onCancel={() => setShowVerify(false)}
106
+ * steps={['document', 'selfie', 'liveness']}
107
+ * onComplete={(r) => console.log(r.verdict)}
116
108
  * />
117
109
  */
118
110
 
119
111
  interface Props extends VerifyConfig {
120
112
  visible: boolean;
121
113
  }
122
- declare function KernaqVerify({ visible, apiKey, backendUrl, country, reference, sandbox, livenessDuration, documentTypes, theme: themeProp, locale: localeProp, onCancel, onComplete, onError, }: Props): React.JSX.Element;
114
+ declare function KernaqVerify({ visible, apiKey, backendUrl, country, reference, sandbox, livenessDuration, livenessTaskCount, documentType, steps: stepsProp, theme: themeProp, locale: localeProp, onComplete, onError, }: Props): React.JSX.Element;
115
+
116
+ /**
117
+ * quality.ts — Native port of @kernaq/capture-web analyseImage logic.
118
+ *
119
+ * React Native has no OffscreenCanvas or createImageBitmap, so we decode
120
+ * the JPEG manually from its base64 representation to extract a luminance
121
+ * sample, then run the same Laplacian variance + brightness + fill-ratio
122
+ * checks the web SDK uses.
123
+ *
124
+ * This is intentionally dependency-free — no expo-image-manipulator,
125
+ * no worklets, no native modules beyond what vision-camera already provides.
126
+ *
127
+ * The JPEG sampling approach:
128
+ * 1. takeSnapshot({ quality: 20 }) → tiny file (~5-15KB)
129
+ * 2. fetch as ArrayBuffer → raw bytes
130
+ * 3. Skip JPEG header bytes, sample raw DCT-domain luminance bytes
131
+ * as a brightness proxy (not exact, but sufficient for dark/overexposed detection)
132
+ * 4. For blur: compute variance of luminance differences between adjacent samples
133
+ *
134
+ * Limitations vs web SDK:
135
+ * - Fill ratio check is approximated via luminance variance spread
136
+ * - Glasses glare heuristic is the same eye-band brightness check
137
+ * - Blur detection is less precise but calibrated to the same thresholds
138
+ */
139
+ interface QualityReport {
140
+ passed: boolean;
141
+ blurScore: number;
142
+ brightness: number;
143
+ fillRatio: number;
144
+ failures: QualityFailure[];
145
+ }
146
+ type QualityFailure = 'too_blurry' | 'too_dark' | 'too_bright' | 'too_small';
147
+ interface QualityConfig {
148
+ minBlurScore?: number;
149
+ minBrightness?: number;
150
+ maxBrightness?: number;
151
+ minFillRatio?: number;
152
+ }
153
+ /**
154
+ * Analyse an image from a file URI.
155
+ * Reads the raw bytes, samples luminance, returns a quality report.
156
+ */
157
+ declare function analyseImageUri(uri: string, config?: QualityConfig): Promise<QualityReport>;
158
+ /**
159
+ * Selfie-specific quality check with glasses/glare heuristic.
160
+ * Takes snapshots from two regions: full frame and top-40% (eye area).
161
+ *
162
+ * Returns a guidance message (empty string = all good) and a passing flag.
163
+ */
164
+ declare function analyseSelfieFrame(uri: string, config?: QualityConfig): Promise<{
165
+ passing: boolean;
166
+ message: string;
167
+ }>;
123
168
 
124
- export { KernaqVerify };
125
- export type { DocumentType, VerifyConfig, VerifyLocale, VerifyResult, VerifyStep, VerifyTheme, VerifyVerdict };
169
+ export { KernaqVerify, analyseImageUri, analyseSelfieFrame };
170
+ export type { DocumentType, LivenessTask, QualityConfig, QualityFailure, QualityReport, VerifyConfig, VerifyLocale, VerifyResult, VerifyStep, VerifyStepName, VerifyTheme, VerifyVerdict };