react-native-usesense 2.0.0 → 2.1.1

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.
@@ -3,8 +3,22 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = exports.UseSense = void 0;
6
+ Object.defineProperty(exports, "FlowError", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _flows.FlowError;
10
+ }
11
+ });
12
+ exports.UseSense = void 0;
13
+ Object.defineProperty(exports, "UseSenseFlows", {
14
+ enumerable: true,
15
+ get: function () {
16
+ return _flows.UseSenseFlows;
17
+ }
18
+ });
19
+ exports.default = void 0;
7
20
  var _reactNative = require("react-native");
21
+ var _flows = require("./flows");
8
22
  const LINKING_ERROR = `react-native-usesense: the native module could not be found.\n\n` + _reactNative.Platform.select({
9
23
  ios: `iOS: run \`cd ios && pod install\` and rebuild the app.`,
10
24
  android: `Android: rebuild the app after installing the package.`,
@@ -137,7 +151,9 @@ class UseSense {
137
151
  apiKey: config.apiKey,
138
152
  environment: config.environment ?? 'auto',
139
153
  apiEndpoint: config.apiEndpoint,
140
- branding: config.branding
154
+ branding: config.branding,
155
+ antispoofOnDeviceEnabled: config.antispoofOnDeviceEnabled ?? false,
156
+ liveSenseV4Enabled: config.liveSenseV4Enabled ?? false
141
157
  });
142
158
  }
143
159
 
@@ -194,7 +210,43 @@ class UseSense {
194
210
  static async isInitialized() {
195
211
  return UseSenseModule.isInitialized();
196
212
  }
213
+
214
+ // ─── LiveSense v4 ─────────────────────────────────────────────────────
215
+ // Phase 1 ticket R-1.
216
+ //
217
+ // v4 runs the perspective-distortion zoom-motion capture. Passthrough
218
+ // to the native SDK's startV4Session (iOS) / startV4Verification
219
+ // (Android). The returned promise resolves with the opaque verdict;
220
+ // sub-scores and pillar verdicts are never exposed.
221
+
222
+ /**
223
+ * Start a LiveSense v4 session.
224
+ *
225
+ * The session must already have been created on your backend and the
226
+ * session_token + nonce forwarded to the client. The native SDK drives
227
+ * the camera, signs the frame hash chain with the platform-attested
228
+ * key, uploads, and returns the opaque verdict.
229
+ */
230
+ static async startV4Verification(request) {
231
+ return UseSenseModule.startV4Verification({
232
+ sessionId: request.sessionId,
233
+ sessionToken: request.sessionToken,
234
+ nonce: request.nonce,
235
+ apiBaseUrl: request.apiBaseUrl,
236
+ environment: request.environment ?? 'production',
237
+ displayName: request.displayName,
238
+ brandPrimaryColor: request.brandPrimaryColor
239
+ });
240
+ }
197
241
  }
242
+
243
+ // ─── LiveSense v4 types (R-1) ─────────────────────────────────────────────
244
+
245
+ /**
246
+ * Opaque verdict from POST /v1/sessions/:id/result. Matches the server
247
+ * contract exactly; no sub-scores leak through.
248
+ */
198
249
  exports.UseSense = UseSense;
199
- var _default = exports.default = UseSense;
250
+ var _default = exports.default = UseSense; // Slice 5d: Flows. A parallel surface to Sessions — host apps choose one
251
+ // per call. See guides/flows/sessions-vs-flows in the API docs.
200
252
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","LINKING_ERROR","Platform","select","ios","android","default","UseSenseModule","NativeModules","Error","eventEmitter","NativeEventEmitter","UseSense","initialize","config","apiKey","err","code","message","isRetryable","environment","apiEndpoint","branding","startVerification","request","sessionType","externalUserId","identityId","metadata","addListener","callback","subscription","raw","remove","reset","isInitialized","exports","_default"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_reactNative","require","_flows","LINKING_ERROR","Platform","select","ios","android","default","UseSenseModule","NativeModules","Error","eventEmitter","NativeEventEmitter","UseSense","initialize","config","apiKey","err","code","message","isRetryable","environment","apiEndpoint","branding","antispoofOnDeviceEnabled","liveSenseV4Enabled","startVerification","request","sessionType","externalUserId","identityId","metadata","addListener","callback","subscription","raw","remove","reset","isInitialized","startV4Verification","sessionId","sessionToken","nonce","apiBaseUrl","displayName","brandPrimaryColor","exports","_default"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * React Native wrapper for the UseSense Flows runner.
3
+ *
4
+ * Coexists with the existing Sessions API (`UseSense.startSession`, etc.);
5
+ * this is a parallel surface, not a replacement. See `guides/flows/sessions-vs-flows`
6
+ * in the API docs for when to use which.
7
+ *
8
+ * Usage:
9
+ *
10
+ * import { UseSenseFlows, FlowError } from 'react-native-usesense';
11
+ *
12
+ * try {
13
+ * const result = await UseSenseFlows.runFlow({ flowRunId, sdkToken });
14
+ * console.log(result.outcome); // 'APPROVE' | 'REJECT' | 'MANUAL_REVIEW' | null
15
+ * } catch (e) {
16
+ * if (e instanceof FlowError) {
17
+ * // e.code: 'token_expired' | 'token_invalid' | ...
18
+ * }
19
+ * }
20
+ */
21
+
22
+ import { NativeModules, Platform } from 'react-native';
23
+ const LINKING_ERROR = `react-native-usesense (flows): the native module could not be found.\n\n` + Platform.select({
24
+ ios: `iOS: run \`cd ios && pod install\` and rebuild the app.`,
25
+ android: `Android: rebuild the app after installing the package.`,
26
+ default: ''
27
+ });
28
+
29
+ // Lazy lookup so this module doesn't throw at import time on platforms that
30
+ // haven't been re-linked yet. The Sessions module mirrors this pattern.
31
+ function nativeModule() {
32
+ const m = NativeModules.UseSenseFlowsModule;
33
+ if (!m) throw new Error(LINKING_ERROR);
34
+ return m;
35
+ }
36
+
37
+ /**
38
+ * Server-driven flow run state. Host apps see only the terminal ones via
39
+ * `FlowRunResult`; intermediate states drive the runner internally.
40
+ */
41
+
42
+ /** Terminal outcome of a flow run. */
43
+
44
+ /**
45
+ * Uniform error taxonomy across every SDK. See `guides/flows/errors` in the
46
+ * API docs for per-code recovery patterns.
47
+ */
48
+
49
+ const FLOW_ERROR_CODES = ['token_expired', 'token_invalid', 'network_unavailable', 'permission_denied', 'provider_unavailable', 'cancelled', 'unsupported_action', 'invalid_input', 'unknown'];
50
+ function normaliseCode(code) {
51
+ return typeof code === 'string' && FLOW_ERROR_CODES.includes(code) ? code : 'unknown';
52
+ }
53
+
54
+ /** Result returned to the host app's `runFlow` promise on terminal state. */
55
+
56
+ /**
57
+ * Typed error thrown by `runFlow` when the native runner reports a failure.
58
+ * Mirrors the web / iOS / Android / Flutter SDKs so host apps catch one
59
+ * taxonomy regardless of platform.
60
+ */
61
+ export class FlowError extends Error {
62
+ constructor(code, message) {
63
+ super(message);
64
+ this.name = 'FlowError';
65
+ this.code = code;
66
+ }
67
+ }
68
+
69
+ /** Options for `UseSenseFlows.runFlow`. */
70
+
71
+ /**
72
+ * Public entry point for the Flows runner. Sessions APIs are untouched;
73
+ * this is a parallel namespace.
74
+ */
75
+ export const UseSenseFlows = {
76
+ /**
77
+ * Run an operator-authored Flow inside the host app. Resolves with a
78
+ * [FlowRunResult] when the run reaches a terminal state (completed,
79
+ * cancelled, errored, abandoned). Rejects with a [FlowError] on transport
80
+ * / token / unsupported-action faults.
81
+ */
82
+ async runFlow(options) {
83
+ try {
84
+ const native = await nativeModule().runFlow(options.flowRunId, options.sdkToken, options.apiBaseUrl ?? null);
85
+ return {
86
+ flowRunId: native.flowRunId,
87
+ state: native.state,
88
+ outcome: native.outcome
89
+ };
90
+ } catch (e) {
91
+ // RN bridge errors are surfaced as `Error` with `.code` and `.message`
92
+ // properties when the native side calls `reject(code, message, null)`.
93
+ const code = normaliseCode(e.code);
94
+ const message = e.message ?? 'Flow failed';
95
+ throw new FlowError(code, message);
96
+ }
97
+ }
98
+ };
99
+ //# sourceMappingURL=flows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["NativeModules","Platform","LINKING_ERROR","select","ios","android","default","nativeModule","m","UseSenseFlowsModule","Error","FLOW_ERROR_CODES","normaliseCode","code","includes","FlowError","constructor","message","name","UseSenseFlows","runFlow","options","native","flowRunId","sdkToken","apiBaseUrl","state","outcome","e"],"sourceRoot":"../../src","sources":["flows.ts"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AAEtD,MAAMC,aAAa,GACjB,0EAA0E,GAC1ED,QAAQ,CAACE,MAAM,CAAC;EACdC,GAAG,EAAE,yDAAyD;EAC9DC,OAAO,EAAE,wDAAwD;EACjEC,OAAO,EAAE;AACX,CAAC,CAAC;;AAEJ;AACA;AACA,SAASC,YAAYA,CAAA,EAAG;EACtB,MAAMC,CAAC,GAAGR,aAAa,CAACS,mBAAmB;EAC3C,IAAI,CAACD,CAAC,EAAE,MAAM,IAAIE,KAAK,CAACR,aAAa,CAAC;EACtC,OAAOM,CAAC;AACV;;AAEA;AACA;AACA;AACA;;AAWA;;AAGA;AACA;AACA;AACA;;AAeA,MAAMG,gBAA0C,GAAG,CACjD,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,WAAW,EACX,oBAAoB,EACpB,eAAe,EACf,SAAS,CACD;AAEV,SAASC,aAAaA,CAACC,IAAa,EAAiB;EACnD,OAAO,OAAOA,IAAI,KAAK,QAAQ,IAAKF,gBAAgB,CAAuBG,QAAQ,CAACD,IAAI,CAAC,GACpFA,IAAI,GACL,SAAS;AACf;;AAEA;;AAaA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAME,SAAS,SAASL,KAAK,CAAC;EAEnCM,WAAWA,CAACH,IAAmB,EAAEI,OAAe,EAAE;IAChD,KAAK,CAACA,OAAO,CAAC;IACd,IAAI,CAACC,IAAI,GAAG,WAAW;IACvB,IAAI,CAACL,IAAI,GAAGA,IAAI;EAClB;AACF;;AAEA;;AAQA;AACA;AACA;AACA;AACA,OAAO,MAAMM,aAAa,GAAG;EAC3B;AACF;AACA;AACA;AACA;AACA;EACE,MAAMC,OAAOA,CAACC,OAAuB,EAA0B;IAC7D,IAAI;MACF,MAAMC,MAAM,GAAG,MAAMf,YAAY,CAAC,CAAC,CAACa,OAAO,CACzCC,OAAO,CAACE,SAAS,EACjBF,OAAO,CAACG,QAAQ,EAChBH,OAAO,CAACI,UAAU,IAAI,IACxB,CAAC;MACD,OAAO;QACLF,SAAS,EAAED,MAAM,CAACC,SAAS;QAC3BG,KAAK,EAAEJ,MAAM,CAACI,KAAK;QACnBC,OAAO,EAAEL,MAAM,CAACK;MAClB,CAAC;IACH,CAAC,CAAC,OAAOC,CAAC,EAAE;MACV;MACA;MACA,MAAMf,IAAI,GAAGD,aAAa,CAAEgB,CAAC,CAAuBf,IAAI,CAAC;MACzD,MAAMI,OAAO,GAAIW,CAAC,CAA0BX,OAAO,IAAI,aAAa;MACpE,MAAM,IAAIF,SAAS,CAACF,IAAI,EAAEI,OAAO,CAAC;IACpC;EACF;AACF,CAAC","ignoreList":[]}
@@ -131,7 +131,9 @@ export class UseSense {
131
131
  apiKey: config.apiKey,
132
132
  environment: config.environment ?? 'auto',
133
133
  apiEndpoint: config.apiEndpoint,
134
- branding: config.branding
134
+ branding: config.branding,
135
+ antispoofOnDeviceEnabled: config.antispoofOnDeviceEnabled ?? false,
136
+ liveSenseV4Enabled: config.liveSenseV4Enabled ?? false
135
137
  });
136
138
  }
137
139
 
@@ -188,6 +190,46 @@ export class UseSense {
188
190
  static async isInitialized() {
189
191
  return UseSenseModule.isInitialized();
190
192
  }
193
+
194
+ // ─── LiveSense v4 ─────────────────────────────────────────────────────
195
+ // Phase 1 ticket R-1.
196
+ //
197
+ // v4 runs the perspective-distortion zoom-motion capture. Passthrough
198
+ // to the native SDK's startV4Session (iOS) / startV4Verification
199
+ // (Android). The returned promise resolves with the opaque verdict;
200
+ // sub-scores and pillar verdicts are never exposed.
201
+
202
+ /**
203
+ * Start a LiveSense v4 session.
204
+ *
205
+ * The session must already have been created on your backend and the
206
+ * session_token + nonce forwarded to the client. The native SDK drives
207
+ * the camera, signs the frame hash chain with the platform-attested
208
+ * key, uploads, and returns the opaque verdict.
209
+ */
210
+ static async startV4Verification(request) {
211
+ return UseSenseModule.startV4Verification({
212
+ sessionId: request.sessionId,
213
+ sessionToken: request.sessionToken,
214
+ nonce: request.nonce,
215
+ apiBaseUrl: request.apiBaseUrl,
216
+ environment: request.environment ?? 'production',
217
+ displayName: request.displayName,
218
+ brandPrimaryColor: request.brandPrimaryColor
219
+ });
220
+ }
191
221
  }
222
+
223
+ // ─── LiveSense v4 types (R-1) ─────────────────────────────────────────────
224
+
225
+ /**
226
+ * Opaque verdict from POST /v1/sessions/:id/result. Matches the server
227
+ * contract exactly; no sub-scores leak through.
228
+ */
229
+
192
230
  export default UseSense;
231
+
232
+ // Slice 5d: Flows. A parallel surface to Sessions — host apps choose one
233
+ // per call. See guides/flows/sessions-vs-flows in the API docs.
234
+ export { UseSenseFlows, FlowError } from './flows';
193
235
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["NativeModules","NativeEventEmitter","Platform","LINKING_ERROR","select","ios","android","default","UseSenseModule","Error","eventEmitter","UseSense","initialize","config","apiKey","err","code","message","isRetryable","environment","apiEndpoint","branding","startVerification","request","sessionType","externalUserId","identityId","metadata","addListener","callback","subscription","raw","remove","reset","isInitialized"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["NativeModules","NativeEventEmitter","Platform","LINKING_ERROR","select","ios","android","default","UseSenseModule","Error","eventEmitter","UseSense","initialize","config","apiKey","err","code","message","isRetryable","environment","apiEndpoint","branding","antispoofOnDeviceEnabled","liveSenseV4Enabled","startVerification","request","sessionType","externalUserId","identityId","metadata","addListener","callback","subscription","raw","remove","reset","isInitialized","startV4Verification","sessionId","sessionToken","nonce","apiBaseUrl","displayName","brandPrimaryColor","UseSenseFlows","FlowError"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * React Native wrapper for the UseSense Flows runner.
3
+ *
4
+ * Coexists with the existing Sessions API (`UseSense.startSession`, etc.);
5
+ * this is a parallel surface, not a replacement. See `guides/flows/sessions-vs-flows`
6
+ * in the API docs for when to use which.
7
+ *
8
+ * Usage:
9
+ *
10
+ * import { UseSenseFlows, FlowError } from 'react-native-usesense';
11
+ *
12
+ * try {
13
+ * const result = await UseSenseFlows.runFlow({ flowRunId, sdkToken });
14
+ * console.log(result.outcome); // 'APPROVE' | 'REJECT' | 'MANUAL_REVIEW' | null
15
+ * } catch (e) {
16
+ * if (e instanceof FlowError) {
17
+ * // e.code: 'token_expired' | 'token_invalid' | ...
18
+ * }
19
+ * }
20
+ */
21
+ /**
22
+ * Server-driven flow run state. Host apps see only the terminal ones via
23
+ * `FlowRunResult`; intermediate states drive the runner internally.
24
+ */
25
+ export type FlowRunState = 'pending' | 'in_progress' | 'stalled' | 'awaiting_review' | 'completed' | 'errored' | 'abandoned' | 'cancelled';
26
+ /** Terminal outcome of a flow run. */
27
+ export type FlowOutcome = 'APPROVE' | 'REJECT' | 'MANUAL_REVIEW';
28
+ /**
29
+ * Uniform error taxonomy across every SDK. See `guides/flows/errors` in the
30
+ * API docs for per-code recovery patterns.
31
+ */
32
+ export type FlowErrorCode = 'token_expired' | 'token_invalid' | 'network_unavailable' | 'permission_denied' | 'provider_unavailable' | 'cancelled' | 'unsupported_action'
33
+ /** Server form validation failed. The native runner handles this inline
34
+ * (per-field highlights) and never reports terminal — but if a host app
35
+ * drives advance() outside the runner, the 422 surfaces with this code. */
36
+ | 'invalid_input' | 'unknown';
37
+ /** Result returned to the host app's `runFlow` promise on terminal state. */
38
+ export interface FlowRunResult {
39
+ flowRunId: string;
40
+ state: FlowRunState;
41
+ outcome: FlowOutcome | null;
42
+ }
43
+ /**
44
+ * Typed error thrown by `runFlow` when the native runner reports a failure.
45
+ * Mirrors the web / iOS / Android / Flutter SDKs so host apps catch one
46
+ * taxonomy regardless of platform.
47
+ */
48
+ export declare class FlowError extends Error {
49
+ readonly code: FlowErrorCode;
50
+ constructor(code: FlowErrorCode, message: string);
51
+ }
52
+ /** Options for `UseSenseFlows.runFlow`. */
53
+ export interface RunFlowOptions {
54
+ flowRunId: string;
55
+ sdkToken: string;
56
+ /** Defaults to `https://api.usesense.ai`. */
57
+ apiBaseUrl?: string;
58
+ }
59
+ /**
60
+ * Public entry point for the Flows runner. Sessions APIs are untouched;
61
+ * this is a parallel namespace.
62
+ */
63
+ export declare const UseSenseFlows: {
64
+ /**
65
+ * Run an operator-authored Flow inside the host app. Resolves with a
66
+ * [FlowRunResult] when the run reaches a terminal state (completed,
67
+ * cancelled, errored, abandoned). Rejects with a [FlowError] on transport
68
+ * / token / unsupported-action faults.
69
+ */
70
+ runFlow(options: RunFlowOptions): Promise<FlowRunResult>;
71
+ };
72
+ //# sourceMappingURL=flows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flows.d.ts","sourceRoot":"","sources":["../../../src/flows.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAoBH;;;GAGG;AACH,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,aAAa,GACb,SAAS,GACT,iBAAiB,GACjB,WAAW,GACX,SAAS,GACT,WAAW,GACX,WAAW,CAAC;AAEhB,sCAAsC;AACtC,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,eAAe,CAAC;AAEjE;;;GAGG;AACH,MAAM,MAAM,aAAa,GACrB,eAAe,GACf,eAAe,GACf,qBAAqB,GACrB,mBAAmB,GACnB,sBAAsB,GACtB,WAAW,GACX,oBAAoB;AACtB;;4EAE4E;GAC1E,eAAe,GACf,SAAS,CAAC;AAoBd,6EAA6E;AAC7E,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,YAAY,CAAC;IACpB,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;CAC7B;AAQD;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;gBACjB,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM;CAKjD;AAED,2CAA2C;AAC3C,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa;IACxB;;;;;OAKG;qBACoB,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;CAoB/D,CAAC"}
@@ -49,6 +49,26 @@ export interface UseSenseConfig {
49
49
  apiEndpoint?: string;
50
50
  /** SDK-level branding overrides. */
51
51
  branding?: BrandingConfig;
52
+ /**
53
+ * Opt in to the on-device antispoof classifier (v4.2). When enabled the
54
+ * native layer runs the bundled CelebA-Spoof model during capture and
55
+ * attaches per-frame spoof probabilities to the uploaded metadata. When
56
+ * disabled (default), the watchtower backend runs the classifier server-side.
57
+ * See `docs/sdk-specs/antispoof-classifier-sdk-spec.md` in the watchtower
58
+ * repo for the rollout plan and crosscheck policy.
59
+ */
60
+ antispoofOnDeviceEnabled?: boolean;
61
+ /**
62
+ * Opt the session into the LiveSense v4 capture flow. When true the native
63
+ * layer:
64
+ * - sends `x-usesense-sdk-version: v4` on session creation
65
+ * - inserts a constitutive zoom-motion phase between baseline and the
66
+ * active challenge (additive, not a replacement)
67
+ * - tags every captured frame with its capture phase
68
+ * The org must also have `livesense_v4_enabled` set in its features map
69
+ * server-side.
70
+ */
71
+ liveSenseV4Enabled?: boolean;
52
72
  }
53
73
  /**
54
74
  * Request to start a verification session.
@@ -207,6 +227,42 @@ export declare class UseSense {
207
227
  * when the SDK is ready.
208
228
  */
209
229
  static isInitialized(): Promise<boolean>;
230
+ /**
231
+ * Start a LiveSense v4 session.
232
+ *
233
+ * The session must already have been created on your backend and the
234
+ * session_token + nonce forwarded to the client. The native SDK drives
235
+ * the camera, signs the frame hash chain with the platform-attested
236
+ * key, uploads, and returns the opaque verdict.
237
+ */
238
+ static startV4Verification(request: V4VerificationRequest): Promise<V4Verdict>;
239
+ }
240
+ export interface V4VerificationRequest {
241
+ sessionId: string;
242
+ sessionToken: string;
243
+ nonce: string;
244
+ apiBaseUrl: string;
245
+ environment?: UseSenseEnvironment;
246
+ displayName?: string;
247
+ brandPrimaryColor?: string;
248
+ }
249
+ export type V4Decision = 'pass' | 'fail' | 'review';
250
+ export type V4Confidence = 'high' | 'medium' | 'low';
251
+ export type V4AssuranceLevel = 'mobile_hardware' | 'web_attested' | 'web_unattested';
252
+ export type V4CaptureChannel = 'ios' | 'android' | 'rn' | 'flutter' | 'web';
253
+ /**
254
+ * Opaque verdict from POST /v1/sessions/:id/result. Matches the server
255
+ * contract exactly; no sub-scores leak through.
256
+ */
257
+ export interface V4Verdict {
258
+ session_id: string;
259
+ verdict: V4Decision;
260
+ confidence: V4Confidence;
261
+ assurance_level_achieved: V4AssuranceLevel;
262
+ capture_channel: V4CaptureChannel;
263
+ match_sense_embedding_id: string | null;
264
+ timestamp: string;
210
265
  }
211
266
  export default UseSense;
267
+ export { UseSenseFlows, FlowError, type FlowErrorCode, type FlowOutcome, type FlowRunResult, type FlowRunState, type RunFlowOptions, } from './flows';
212
268
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-usesense",
3
- "version": "2.0.0",
3
+ "version": "2.1.1",
4
4
  "description": "React Native plugin for human presence verification. Wraps the native UseSense iOS and Android SDKs.",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -60,6 +60,7 @@
60
60
  "react-native": ">=0.73.0"
61
61
  },
62
62
  "devDependencies": {
63
+ "@types/jest": "^29.5.14",
63
64
  "@types/react": "^18.2.0",
64
65
  "@typescript-eslint/eslint-plugin": "^7.0.0",
65
66
  "@typescript-eslint/parser": "^7.0.0",
@@ -69,6 +70,7 @@
69
70
  "react": "^18.2.0",
70
71
  "react-native": "^0.73.0",
71
72
  "react-native-builder-bob": "^0.23.0",
73
+ "ts-jest": "^29.4.11",
72
74
  "typescript": "^5.3.0"
73
75
  },
74
76
  "codegenConfig": {
@@ -26,5 +26,5 @@ Pod::Spec.new do |s|
26
26
  # redaction result type with a completely different UseSenseConfig
27
27
  # init signature. See CHANGELOG [2.0.0] for the full rewrite
28
28
  # rationale.
29
- s.dependency "UseSenseSDK", "~> 4.2"
29
+ s.dependency "UseSenseSDK", "~> 4.4"
30
30
  end
package/src/flows.ts ADDED
@@ -0,0 +1,159 @@
1
+ /**
2
+ * React Native wrapper for the UseSense Flows runner.
3
+ *
4
+ * Coexists with the existing Sessions API (`UseSense.startSession`, etc.);
5
+ * this is a parallel surface, not a replacement. See `guides/flows/sessions-vs-flows`
6
+ * in the API docs for when to use which.
7
+ *
8
+ * Usage:
9
+ *
10
+ * import { UseSenseFlows, FlowError } from 'react-native-usesense';
11
+ *
12
+ * try {
13
+ * const result = await UseSenseFlows.runFlow({ flowRunId, sdkToken });
14
+ * console.log(result.outcome); // 'APPROVE' | 'REJECT' | 'MANUAL_REVIEW' | null
15
+ * } catch (e) {
16
+ * if (e instanceof FlowError) {
17
+ * // e.code: 'token_expired' | 'token_invalid' | ...
18
+ * }
19
+ * }
20
+ */
21
+
22
+ import { NativeModules, Platform } from 'react-native';
23
+
24
+ const LINKING_ERROR =
25
+ `react-native-usesense (flows): the native module could not be found.\n\n` +
26
+ Platform.select({
27
+ ios: `iOS: run \`cd ios && pod install\` and rebuild the app.`,
28
+ android: `Android: rebuild the app after installing the package.`,
29
+ default: '',
30
+ });
31
+
32
+ // Lazy lookup so this module doesn't throw at import time on platforms that
33
+ // haven't been re-linked yet. The Sessions module mirrors this pattern.
34
+ function nativeModule() {
35
+ const m = NativeModules.UseSenseFlowsModule;
36
+ if (!m) throw new Error(LINKING_ERROR);
37
+ return m as { runFlow: (flowRunId: string, sdkToken: string, apiBaseUrl: string | null) => Promise<NativeFlowRunResult> };
38
+ }
39
+
40
+ /**
41
+ * Server-driven flow run state. Host apps see only the terminal ones via
42
+ * `FlowRunResult`; intermediate states drive the runner internally.
43
+ */
44
+ export type FlowRunState =
45
+ | 'pending'
46
+ | 'in_progress'
47
+ | 'stalled'
48
+ | 'awaiting_review'
49
+ | 'completed'
50
+ | 'errored'
51
+ | 'abandoned'
52
+ | 'cancelled';
53
+
54
+ /** Terminal outcome of a flow run. */
55
+ export type FlowOutcome = 'APPROVE' | 'REJECT' | 'MANUAL_REVIEW';
56
+
57
+ /**
58
+ * Uniform error taxonomy across every SDK. See `guides/flows/errors` in the
59
+ * API docs for per-code recovery patterns.
60
+ */
61
+ export type FlowErrorCode =
62
+ | 'token_expired'
63
+ | 'token_invalid'
64
+ | 'network_unavailable'
65
+ | 'permission_denied'
66
+ | 'provider_unavailable'
67
+ | 'cancelled'
68
+ | 'unsupported_action'
69
+ /** Server form validation failed. The native runner handles this inline
70
+ * (per-field highlights) and never reports terminal — but if a host app
71
+ * drives advance() outside the runner, the 422 surfaces with this code. */
72
+ | 'invalid_input'
73
+ | 'unknown';
74
+
75
+ const FLOW_ERROR_CODES: readonly FlowErrorCode[] = [
76
+ 'token_expired',
77
+ 'token_invalid',
78
+ 'network_unavailable',
79
+ 'permission_denied',
80
+ 'provider_unavailable',
81
+ 'cancelled',
82
+ 'unsupported_action',
83
+ 'invalid_input',
84
+ 'unknown',
85
+ ] as const;
86
+
87
+ function normaliseCode(code: unknown): FlowErrorCode {
88
+ return typeof code === 'string' && (FLOW_ERROR_CODES as readonly string[]).includes(code)
89
+ ? (code as FlowErrorCode)
90
+ : 'unknown';
91
+ }
92
+
93
+ /** Result returned to the host app's `runFlow` promise on terminal state. */
94
+ export interface FlowRunResult {
95
+ flowRunId: string;
96
+ state: FlowRunState;
97
+ outcome: FlowOutcome | null;
98
+ }
99
+
100
+ interface NativeFlowRunResult {
101
+ flowRunId: string;
102
+ state: FlowRunState;
103
+ outcome: FlowOutcome | null;
104
+ }
105
+
106
+ /**
107
+ * Typed error thrown by `runFlow` when the native runner reports a failure.
108
+ * Mirrors the web / iOS / Android / Flutter SDKs so host apps catch one
109
+ * taxonomy regardless of platform.
110
+ */
111
+ export class FlowError extends Error {
112
+ readonly code: FlowErrorCode;
113
+ constructor(code: FlowErrorCode, message: string) {
114
+ super(message);
115
+ this.name = 'FlowError';
116
+ this.code = code;
117
+ }
118
+ }
119
+
120
+ /** Options for `UseSenseFlows.runFlow`. */
121
+ export interface RunFlowOptions {
122
+ flowRunId: string;
123
+ sdkToken: string;
124
+ /** Defaults to `https://api.usesense.ai`. */
125
+ apiBaseUrl?: string;
126
+ }
127
+
128
+ /**
129
+ * Public entry point for the Flows runner. Sessions APIs are untouched;
130
+ * this is a parallel namespace.
131
+ */
132
+ export const UseSenseFlows = {
133
+ /**
134
+ * Run an operator-authored Flow inside the host app. Resolves with a
135
+ * [FlowRunResult] when the run reaches a terminal state (completed,
136
+ * cancelled, errored, abandoned). Rejects with a [FlowError] on transport
137
+ * / token / unsupported-action faults.
138
+ */
139
+ async runFlow(options: RunFlowOptions): Promise<FlowRunResult> {
140
+ try {
141
+ const native = await nativeModule().runFlow(
142
+ options.flowRunId,
143
+ options.sdkToken,
144
+ options.apiBaseUrl ?? null,
145
+ );
146
+ return {
147
+ flowRunId: native.flowRunId,
148
+ state: native.state,
149
+ outcome: native.outcome,
150
+ };
151
+ } catch (e) {
152
+ // RN bridge errors are surfaced as `Error` with `.code` and `.message`
153
+ // properties when the native side calls `reject(code, message, null)`.
154
+ const code = normaliseCode((e as { code?: string }).code);
155
+ const message = (e as { message?: string }).message ?? 'Flow failed';
156
+ throw new FlowError(code, message);
157
+ }
158
+ },
159
+ };