@kyciris/core 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.mts +75 -1
- package/dist/index.d.ts +75 -1
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +19 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/files.ts","../src/http/envelope.ts","../src/http/client.ts","../src/resources/analytics.ts","../src/poll.ts","../src/resources/identities.ts","../src/resources/levels.ts","../src/resources/media.ts","../src/types.ts","../src/resources/ocr.ts","../src/resources/verifications.ts","../src/resources/webhooks.ts","../src/storage.ts","../src/client.ts","../src/flow.ts"],"names":["bytes","mimeType","delay","DEFAULT_TIMEOUT_MS"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Every error the SDK throws is a KycirisError, so a caller can branch on\n * `code` instead of parsing messages.\n *\n * Codes come from two places. Gateway codes are the `error.code` value in the\n * API's error envelope (`{ error: { code, message, details }, meta }`) and are\n * kept in step with the gateway's own ERROR_CODE enum. SDK codes are raised\n * client-side, before or instead of a request.\n */\n\n/**\n * Error codes produced by the gateway itself.\n *\n * Mirrors `ERROR_CODE` in kyc-gateway (src/common/enums/error-codes.ts). Codes\n * the SDK does not recognise are still surfaced verbatim on `KycirisError.code`\n * — the list is for autocomplete and exhaustiveness, not for filtering.\n */\nexport const GATEWAY_ERROR_CODES = [\n // OCR processing\n 'INVALID_OCR_DATA',\n 'OCR_EXTRACTION_ERROR',\n // Document validation\n 'DOCUMENT_EXPIRED',\n 'INVALID_DOCUMENT_QUALITY',\n // Face matching\n 'FACE_MISMATCH',\n 'LOW_FACE_MATCH_SCORE',\n 'NO_FACE',\n // Manual review\n 'MANUAL_REJECTION',\n // Worker terminal failures\n 'BAD_PAYLOAD',\n 'UNSUPPORTED_DOCUMENT',\n 'BAD_IMAGE',\n // Account status\n 'ACCOUNT_SUSPENDED',\n // Generic HTTP labels\n 'VALIDATION_ERROR',\n 'UNAUTHORIZED',\n 'FORBIDDEN',\n 'NOT_FOUND',\n 'RESOURCE_ALREADY_EXISTS',\n 'RATE_LIMIT_EXCEEDED',\n 'INTERNAL_SERVER_ERROR',\n] as const;\n\nexport type GatewayErrorCode = (typeof GATEWAY_ERROR_CODES)[number];\n\n/** Error codes raised by the SDK without (or before) a gateway response. */\nexport const SDK_ERROR_CODES = [\n /** The client was constructed with an unusable configuration. */\n 'CONFIG_ERROR',\n /** A project API key was about to be sent from a browser or React Native app. */\n 'CREDENTIAL_MISUSE',\n /** The endpoint needs a credential the client was not given. */\n 'MISSING_CREDENTIAL',\n /** The request never reached the gateway (DNS, TLS, offline, CORS). */\n 'NETWORK_ERROR',\n /** The request exceeded `timeoutMs`. */\n 'TIMEOUT',\n /** An AbortSignal supplied by the caller fired. */\n 'ABORTED',\n /** A 2xx response whose body was not the documented envelope. */\n 'INVALID_RESPONSE',\n /** A file argument could not be turned into an upload on this platform. */\n 'INVALID_FILE',\n /** Polling ran past its own timeout without reaching a final state. */\n 'POLL_TIMEOUT',\n /** No verification session was found in storage to resume from. */\n 'SESSION_NOT_FOUND',\n] as const;\n\nexport type SdkErrorCode = (typeof SDK_ERROR_CODES)[number];\n\n/** Any code that can land on a KycirisError. Open-ended by design. */\nexport type KycirisErrorCode = GatewayErrorCode | SdkErrorCode | (string & {});\n\nexport interface KycirisErrorInit {\n code: KycirisErrorCode;\n /** HTTP status, when the error came from a response. */\n status?: number;\n /** `meta.requestId` from the response envelope — quote it in bug reports. */\n requestId?: string;\n /** `error.details` from the envelope, e.g. per-field validation failures. */\n details?: unknown;\n /** Whether retrying the same request could plausibly succeed. */\n retryable?: boolean;\n /** The underlying error, when this one wraps a lower-level failure. */\n cause?: unknown;\n}\n\n/**\n * The single error type the SDK throws.\n *\n * It deliberately carries no request/response objects: those hold the\n * Authorization and X-API-Key headers, and an error is the thing most likely to\n * be logged verbatim or shipped to an error tracker.\n */\nexport class KycirisError extends Error {\n readonly name = 'KycirisError';\n readonly code: KycirisErrorCode;\n readonly status?: number;\n readonly requestId?: string;\n readonly details?: unknown;\n readonly retryable: boolean;\n\n constructor(message: string, init: KycirisErrorInit) {\n super(message);\n // Assigned rather than passed to `super`: the `cause` option is ES2022,\n // and the package is compiled for ES2020 so it still loads on older\n // runtimes. The property behaves identically either way.\n if (init.cause !== undefined) {\n (this as { cause?: unknown }).cause = init.cause;\n }\n this.code = init.code;\n this.status = init.status;\n this.requestId = init.requestId;\n this.details = init.details;\n this.retryable = init.retryable ?? false;\n\n // Restores the prototype chain when the package is consumed as compiled\n // ES5/CommonJS, where extending a builtin otherwise breaks `instanceof`.\n Object.setPrototypeOf(this, KycirisError.prototype);\n }\n\n /** True when this is a KycirisError, across bundle/realm boundaries. */\n static isKycirisError(value: unknown): value is KycirisError {\n return (\n value instanceof KycirisError ||\n (typeof value === 'object' &&\n value !== null &&\n (value as { name?: unknown }).name === 'KycirisError' &&\n typeof (value as { code?: unknown }).code === 'string')\n );\n }\n}\n\n/** Convenience guard, equivalent to `KycirisError.isKycirisError`. */\nexport function isKycirisError(value: unknown): value is KycirisError {\n return KycirisError.isKycirisError(value);\n}\n\n/**\n * HTTP statuses worth retrying: the request either never ran (429) or failed\n * for a reason that is plausibly momentary.\n */\nexport function isRetryableStatus(status: number): boolean {\n return status === 408 || status === 429 || (status >= 500 && status <= 599);\n}\n","import { KycirisError } from './errors';\n\n/**\n * The largest upload the gateway accepts (MAX_IMAGE_FILE_SIZE). Checked here\n * too, when the SDK can see the bytes, so an 8MB upload fails instantly\n * instead of after the whole body has gone over the wire.\n */\nexport const MAX_IMAGE_FILE_SIZE = 8 * 1024 * 1024;\n\n/** The only image types the gateway accepts, decided by magic bytes. */\nexport type ImageMimeType = 'image/jpeg' | 'image/png';\n\n/**\n * An image to upload, in whichever form the host platform produces.\n *\n * - `Blob` / `File` — browsers, and Node 18+ (`new Blob([bytes])`).\n * - `{ uri }` — React Native: a `file://`, `content://`, `ph://` or `data:` URI\n * from the camera or image picker.\n * - `{ data }` — raw bytes, e.g. `fs.readFileSync()` in Node.\n * - `string` — a `data:` URI, a bare base64 payload, or a React Native file URI.\n */\nexport type FileInput =\n | Blob\n | { uri: string; name?: string; type?: string }\n | { data: ArrayBuffer | ArrayBufferView; name?: string; type?: string }\n | string\n | NormalizedFile;\n\n/** A file ready to be appended to FormData on this platform. */\nexport interface NormalizedFile {\n /** Blob on web/Node, `{ uri, name, type }` on React Native. */\n value: unknown;\n filename: string;\n /** Sniffed from the bytes where possible, otherwise the caller's hint. */\n mimeType: string;\n}\n\n/**\n * Marks an already-normalized file, so `normalizeFile` can be idempotent.\n *\n * That matters because validating early and uploading later are two different\n * moments: `uploadStep` checks the image before spending a request on reading\n * progress, and without this the bytes would be decoded and sniffed a second\n * time on the way out — on a multi-megabyte photo, on a phone.\n *\n * Symbol.for, not a local symbol: two copies of the package in one bundle must\n * still recognise each other's files.\n */\nconst NORMALIZED = Symbol.for('kyciris.normalizedFile');\n\nfunction mark(file: NormalizedFile): NormalizedFile {\n Object.defineProperty(file, NORMALIZED, { value: true, enumerable: false });\n return file;\n}\n\n/** True when `value` has already been through {@link normalizeFile}. */\nexport function isNormalizedFile(value: unknown): value is NormalizedFile {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as Record<symbol, unknown>)[NORMALIZED] === true\n );\n}\n\n/**\n * React Native's FormData takes `{ uri, name, type }` and streams the file\n * itself; it has no filesystem access from JS to turn that URI into a Blob.\n * Everywhere else, Blob is the portable choice.\n */\nexport function isReactNative(): boolean {\n return (\n typeof navigator !== 'undefined' &&\n (navigator as { product?: string }).product === 'ReactNative'\n );\n}\n\nconst JPEG_MAGIC = [0xff, 0xd8, 0xff];\nconst PNG_MAGIC = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];\n\nfunction startsWith(bytes: Uint8Array, magic: number[]): boolean {\n if (bytes.length < magic.length) return false;\n return magic.every((byte, index) => bytes[index] === byte);\n}\n\n/**\n * The real image type, from the first bytes.\n *\n * The gateway sniffs the same way and ignores the declared Content-Type, so a\n * caller who mislabels a PNG as image/jpeg still succeeds — and one who\n * uploads a PDF renamed to .jpg still fails. Doing it here just moves that\n * answer earlier.\n */\nexport function detectImageMimeType(bytes: Uint8Array): ImageMimeType | null {\n if (bytes.length < 8) return null;\n if (startsWith(bytes, JPEG_MAGIC)) return 'image/jpeg';\n if (startsWith(bytes, PNG_MAGIC)) return 'image/png';\n return null;\n}\n\nconst BASE64_ALPHABET = /^[A-Za-z0-9+/]+={0,2}$/;\n\n/** Decodes base64 using whichever primitive the runtime provides. */\nexport function decodeBase64(input: string): Uint8Array {\n const normalized = input.replace(/\\s/g, '');\n\n // Node (and React Native, via its Buffer polyfill) — avoids atob's\n // char-by-char loop on multi-megabyte images.\n // Typed structurally rather than as Node's `BufferConstructor`: this package\n // has no dependencies and must typecheck in a browser or React Native project\n // that has never installed @types/node. Only the one overload used is named.\n const maybeBuffer = (globalThis as { Buffer?: { from(s: string, encoding: string): Uint8Array } })\n .Buffer;\n if (maybeBuffer) {\n const buffer = maybeBuffer.from(normalized, 'base64');\n return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n }\n\n if (typeof atob === 'function') {\n const binary = atob(normalized);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n }\n\n throw new KycirisError(\n 'This runtime has neither Buffer nor atob, so base64 image data cannot be decoded. Pass a Blob or raw bytes instead.',\n { code: 'INVALID_FILE' }\n );\n}\n\nfunction toBytes(data: ArrayBuffer | ArrayBufferView): Uint8Array {\n return data instanceof ArrayBuffer\n ? new Uint8Array(data)\n : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n}\n\n/** True for the URI schemes React Native's FormData can stream by itself. */\nfunction isPlatformUri(value: string): boolean {\n return /^(file|content|ph|assets-library):/i.test(value);\n}\n\nconst DATA_URI_RE = /^data:([^;,]*)(;[^,]*)?,(.*)$/s;\n\n/** Splits a `data:` URI into its declared type and decoded bytes. */\nfunction parseDataUri(value: string): { mimeType: string; bytes: Uint8Array } {\n const match = DATA_URI_RE.exec(value);\n if (!match) {\n throw new KycirisError('Malformed data: URI.', { code: 'INVALID_FILE' });\n }\n const [, declaredType, parameters, payload] = match;\n const isBase64 = (parameters ?? '').toLowerCase().includes('base64');\n\n let bytes: Uint8Array;\n if (isBase64) {\n bytes = decodeBase64(payload);\n } else {\n // decodeURIComponent throws a bare URIError on a malformed escape, which\n // would escape the SDK as something the caller cannot branch on.\n try {\n bytes = new TextEncoder().encode(decodeURIComponent(payload));\n } catch (cause) {\n throw new KycirisError(\n 'Malformed percent-encoding in a data: URI. Image data should be base64-encoded (data:image/jpeg;base64,...) — percent-encoding is UTF-8 and cannot carry arbitrary bytes.',\n { code: 'INVALID_FILE', cause }\n );\n }\n }\n\n return { mimeType: declaredType || 'application/octet-stream', bytes };\n}\n\nfunction assertBlobSize(blob: Blob, filename: string): void {\n if (blob.size === 0) {\n throw new KycirisError(`${filename} is empty.`, { code: 'INVALID_FILE' });\n }\n if (blob.size > MAX_IMAGE_FILE_SIZE) {\n throw new KycirisError(\n `${filename} is ${(blob.size / 1024 / 1024).toFixed(1)}MB; the gateway accepts at most ${MAX_IMAGE_FILE_SIZE / 1024 / 1024}MB. Re-encode at a lower quality before uploading.`,\n { code: 'INVALID_FILE' }\n );\n }\n}\n\nfunction assertUsableImage(bytes: Uint8Array, filename: string): ImageMimeType {\n if (bytes.length === 0) {\n throw new KycirisError(`${filename} is empty.`, { code: 'INVALID_FILE' });\n }\n if (bytes.length > MAX_IMAGE_FILE_SIZE) {\n throw new KycirisError(\n `${filename} is ${(bytes.length / 1024 / 1024).toFixed(1)}MB; the gateway accepts at most ${MAX_IMAGE_FILE_SIZE / 1024 / 1024}MB. Re-encode at a lower quality before uploading.`,\n { code: 'INVALID_FILE' }\n );\n }\n const mimeType = detectImageMimeType(bytes);\n if (!mimeType) {\n throw new KycirisError(\n `${filename} is not a JPEG or PNG image. The gateway decides the type from the file's own bytes, not its name or Content-Type.`,\n { code: 'INVALID_FILE' }\n );\n }\n return mimeType;\n}\n\nfunction bytesToValue(bytes: Uint8Array, mimeType: string, filename: string): NormalizedFile {\n if (isReactNative()) {\n // React Native's FormData cannot take a Blob reliably, but its networking\n // layer does read `data:` URIs — which is why the bytes go back out as one.\n const base64 = encodeBase64(bytes);\n return mark({\n value: { uri: `data:${mimeType};base64,${base64}`, name: filename, type: mimeType },\n filename,\n mimeType,\n });\n }\n\n if (typeof Blob === 'undefined') {\n throw new KycirisError(\n 'This runtime has no Blob, so image bytes cannot be turned into an upload. Node 18+ is required.',\n { code: 'INVALID_FILE' }\n );\n }\n\n // Copied into its own ArrayBuffer: `bytes` may be a view onto a pooled\n // Node Buffer, and Blob would otherwise capture the whole pool.\n const copy = new Uint8Array(bytes.byteLength);\n copy.set(bytes);\n return mark({ value: new Blob([copy], { type: mimeType }), filename, mimeType });\n}\n\n/** Encodes bytes as base64 using whichever primitive the runtime provides. */\nexport function encodeBase64(bytes: Uint8Array): string {\n // Structural, for the reason given in decodeBase64 above.\n const maybeBuffer = (\n globalThis as { Buffer?: { from(b: Uint8Array): { toString(encoding: string): string } } }\n ).Buffer;\n if (maybeBuffer) {\n return maybeBuffer.from(bytes).toString('base64');\n }\n if (typeof btoa === 'function') {\n let binary = '';\n // Chunked: `String.fromCharCode(...bytes)` blows the argument limit on a\n // multi-megabyte photo.\n const CHUNK = 0x8000;\n for (let i = 0; i < bytes.length; i += CHUNK) {\n binary += String.fromCharCode(...bytes.subarray(i, i + CHUNK));\n }\n return btoa(binary);\n }\n throw new KycirisError(\n 'This runtime has neither Buffer nor btoa, so image bytes cannot be base64-encoded.',\n { code: 'INVALID_FILE' }\n );\n}\n\n/**\n * Turns whatever the caller has into something FormData can carry on this\n * platform, validating the bytes first whenever they are visible.\n *\n * A React Native `file://` URI is the one case where they are not: the file\n * lives on disk and only the native layer reads it, so type and size are left\n * to the gateway to enforce.\n *\n * @param input The image, in any supported form\n * @param defaultName Filename to use when the input does not carry one\n */\nexport function normalizeFile(input: FileInput, defaultName: string): NormalizedFile {\n if (input == null) {\n throw new KycirisError(`No image was given for ${defaultName}.`, {\n code: 'INVALID_FILE',\n });\n }\n\n // Already validated and converted: hand it straight back rather than\n // decoding the same photo twice.\n if (isNormalizedFile(input)) return input;\n\n if (typeof Blob !== 'undefined' && input instanceof Blob) {\n assertBlobSize(input, defaultName);\n // Not sniffed here: reading a Blob is async and this function is not. Use\n // prepareFile (which the upload path does) to have the bytes checked.\n const filename = (input as File).name || defaultName;\n return mark({ value: input, filename, mimeType: input.type || 'image/jpeg' });\n }\n\n if (typeof input === 'string') {\n if (input.startsWith('data:')) {\n const { bytes } = parseDataUri(input);\n const mimeType = assertUsableImage(bytes, defaultName);\n return bytesToValue(bytes, mimeType, defaultName);\n }\n\n if (isPlatformUri(input)) {\n if (!isReactNative()) {\n throw new KycirisError(\n `${defaultName} was given as \"${input.slice(0, 12)}…\", a URI only React Native can read. Read the file yourself and pass a Blob or its bytes.`,\n { code: 'INVALID_FILE' }\n );\n }\n return mark({\n value: { uri: input, name: defaultName, type: 'image/jpeg' },\n filename: defaultName,\n mimeType: 'image/jpeg',\n });\n }\n\n const trimmed = input.replace(/\\s/g, '');\n if (!trimmed || !BASE64_ALPHABET.test(trimmed)) {\n throw new KycirisError(\n `${defaultName} was given as a string that is neither a data: URI, a file URI, nor base64.`,\n { code: 'INVALID_FILE' }\n );\n }\n const bytes = decodeBase64(trimmed);\n const mimeType = assertUsableImage(bytes, defaultName);\n return bytesToValue(bytes, mimeType, defaultName);\n }\n\n if ('uri' in input && typeof input.uri === 'string') {\n if (input.uri.startsWith('data:')) {\n const { bytes } = parseDataUri(input.uri);\n const mimeType = assertUsableImage(bytes, input.name ?? defaultName);\n return bytesToValue(bytes, mimeType, input.name ?? defaultName);\n }\n if (!isReactNative()) {\n throw new KycirisError(\n `${defaultName} was given as a { uri } object, which only React Native can read. Read the file yourself and pass a Blob or its bytes.`,\n { code: 'INVALID_FILE' }\n );\n }\n const filename = input.name ?? defaultName;\n const mimeType = input.type ?? 'image/jpeg';\n return mark({ value: { uri: input.uri, name: filename, type: mimeType }, filename, mimeType });\n }\n\n if ('data' in input && input.data) {\n const bytes = toBytes(input.data);\n const filename = input.name ?? defaultName;\n const mimeType = assertUsableImage(bytes, filename);\n return bytesToValue(bytes, mimeType, filename);\n }\n\n throw new KycirisError(\n `${defaultName} is not a Blob, a { uri } object, a { data } object, or a base64/data: string.`,\n { code: 'INVALID_FILE' }\n );\n}\n\n/**\n * The first bytes of a Blob, or null when this runtime cannot produce them.\n *\n * `Blob.prototype.arrayBuffer` is the direct route, but it is absent in Safari\n * before 14 and in jsdom, so FileReader — which every browser that has Blob at\n * all supports — is the fallback. Enough bytes for the longest magic number\n * (PNG's eight).\n */\nasync function readBlobHead(blob: Blob): Promise<Uint8Array | null> {\n const head = blob.slice(0, 8);\n\n if (typeof (head as Blob).arrayBuffer === 'function') {\n try {\n return new Uint8Array(await head.arrayBuffer());\n } catch {\n return null;\n }\n }\n\n if (typeof FileReader === 'undefined') return null;\n\n return new Promise<Uint8Array | null>((resolve) => {\n const reader = new FileReader();\n reader.onload = () =>\n resolve(reader.result instanceof ArrayBuffer ? new Uint8Array(reader.result) : null);\n // Never rejects: a file the SDK cannot inspect is passed on to the gateway,\n // which is the authority on it anyway.\n reader.onerror = () => resolve(null);\n reader.onabort = () => resolve(null);\n try {\n reader.readAsArrayBuffer(head);\n } catch {\n resolve(null);\n }\n });\n}\n\n/**\n * {@link normalizeFile}, but able to read a Blob's first bytes.\n *\n * This is what the upload path uses. A file chosen from an `<input>` arrives\n * as a Blob whose `type` is whatever the operating system guessed from the\n * extension, so a PDF renamed `.jpg` claims to be `image/jpeg` — and the\n * synchronous path has to take that on trust. Reading eight bytes settles it\n * before megabytes go over a phone connection, using the same magic-byte test\n * the gateway applies on arrival.\n *\n * Every other input form is already validated synchronously, so it is simply\n * delegated.\n */\nexport async function prepareFile(input: FileInput, defaultName: string): Promise<NormalizedFile> {\n if (isNormalizedFile(input)) return input;\n\n if (typeof Blob !== 'undefined' && input instanceof Blob) {\n assertBlobSize(input, defaultName);\n\n const filename = (input as File).name || defaultName;\n const head = await readBlobHead(input);\n\n // Unreadable head: keep the caller's declared type rather than refusing a\n // file that may well be fine. The gateway sniffs it on arrival either way,\n // so the cost is a later failure, not a wrong accept.\n if (!head) {\n return mark({ value: input, filename, mimeType: input.type || 'image/jpeg' });\n }\n\n const mimeType = detectImageMimeType(head);\n if (!mimeType) {\n throw new KycirisError(\n `${filename} is not a JPEG or PNG image. The gateway decides the type from the file's own bytes, not its name or Content-Type.`,\n { code: 'INVALID_FILE' }\n );\n }\n\n return mark({ value: input, filename, mimeType });\n }\n\n return normalizeFile(input, defaultName);\n}\n","import { KycirisError } from '../errors';\n\n/**\n * Metadata the gateway attaches to every response, success or error.\n *\n * `requestId` is also returned as the X-Request-Id header and is the value to\n * quote when reporting a problem — it correlates the call with the gateway's\n * own logs.\n */\nexport interface ApiMeta {\n requestId: string;\n timestamp: string;\n /** The gateway's API version, not the SDK's. */\n version: string;\n}\n\nexport interface PaginationMeta {\n page: number;\n limit: number;\n total: number;\n}\n\n/** A successful response, unwrapped. */\nexport interface ApiResult<T> {\n data: T;\n meta: ApiMeta;\n /** Present only on list endpoints. */\n pagination?: PaginationMeta;\n}\n\n/** A page of results: the rows, plus the pagination block that came with them. */\nexport interface Page<T> {\n items: T[];\n pagination: PaginationMeta;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n/** The meta block, if the body carries a well-formed one. */\nexport function readMeta(body: unknown): ApiMeta | undefined {\n if (!isRecord(body) || !isRecord(body.meta)) return undefined;\n const { requestId, timestamp, version } = body.meta;\n if (typeof requestId !== 'string') return undefined;\n return {\n requestId,\n timestamp: typeof timestamp === 'string' ? timestamp : '',\n version: typeof version === 'string' ? version : '',\n };\n}\n\n/**\n * `meta.requestId` alone, for error paths where the body may be anything at\n * all (an nginx error page, a truncated stream).\n */\nexport function readRequestId(body: unknown): string | undefined {\n return readMeta(body)?.requestId;\n}\n\n/**\n * Unwraps `{ data, meta, pagination? }` into an ApiResult.\n *\n * Throws INVALID_RESPONSE rather than returning undefined: a 2xx that is not\n * the documented envelope means something other than the gateway answered\n * (a proxy, a captive portal, the wrong baseUrl), and silently handing the\n * caller `undefined` turns that into a confusing failure much further away.\n */\nexport function unwrapEnvelope<T>(body: unknown, requestPath: string): ApiResult<T> {\n const meta = readMeta(body);\n if (!isRecord(body) || !('data' in body) || !meta) {\n throw new KycirisError(\n `The response to ${requestPath} was not a KYCiris API envelope. Check that baseUrl points at the gateway and that nothing is rewriting responses in between.`,\n { code: 'INVALID_RESPONSE' }\n );\n }\n\n const result: ApiResult<T> = { data: body.data as T, meta };\n\n if (isRecord(body.pagination)) {\n const { page, limit, total } = body.pagination;\n if (\n typeof page === 'number' &&\n typeof limit === 'number' &&\n typeof total === 'number'\n ) {\n result.pagination = { page, limit, total };\n }\n }\n\n return result;\n}\n\n/**\n * Turns an unwrapped list response into a Page.\n *\n * The gateway sends the rows as `data` and the counts as a sibling\n * `pagination` block; a caller wants them together. When the endpoint returned\n * no pagination block (or an unpaginated array), the totals are derived from\n * the rows so the shape stays uniform.\n */\nexport function toPage<T>(result: ApiResult<T[]>): Page<T> {\n const items = Array.isArray(result.data) ? result.data : [];\n return {\n items,\n pagination: result.pagination ?? {\n page: 1,\n limit: items.length,\n total: items.length,\n },\n };\n}\n\n/**\n * The message and code carried by an error envelope\n * (`{ error: { code, message, details }, meta }`).\n *\n * Falls back progressively, because an error response is exactly where a\n * non-gateway intermediary is most likely to have answered instead.\n */\nexport function readErrorEnvelope(body: unknown): {\n code?: string;\n message?: string;\n details?: unknown;\n} {\n if (!isRecord(body)) {\n return typeof body === 'string' && body.trim() ? { message: body.trim() } : {};\n }\n\n const error = isRecord(body.error) ? body.error : undefined;\n if (error) {\n return {\n code: typeof error.code === 'string' ? error.code : undefined,\n message: typeof error.message === 'string' ? error.message : undefined,\n details: error.details,\n };\n }\n\n // Nest's default shape, in case a handler bypasses the exception filter.\n const message = body.message;\n return {\n message: Array.isArray(message)\n ? message.join(', ')\n : typeof message === 'string'\n ? message\n : undefined,\n };\n}\n","import { KycirisError, isRetryableStatus } from '../errors';\nimport { prepareFile, type FileInput } from '../files';\nimport {\n readErrorEnvelope,\n readRequestId,\n unwrapEnvelope,\n type ApiResult,\n} from './envelope';\n\n/** Returns a verification token, refreshing it if the cached one has expired. */\nexport type VerificationTokenProvider = () => string | Promise<string>;\n\n/** The subset of `fetch` the SDK uses, so a custom implementation can stand in. */\nexport type FetchLike = (\n input: string,\n init?: RequestInit\n) => Promise<Response>;\n\n/** Which credential an endpoint accepts. */\nexport type AuthMode = 'api-key' | 'token' | 'any' | 'none';\n\nexport interface HttpClientConfig {\n /** Origin of the gateway, e.g. `https://api.kyciris.com`. */\n baseUrl: string;\n /**\n * Project API key. A project-wide credential — server-side only. Passing it\n * from a browser or React Native app throws CREDENTIAL_MISUSE.\n */\n apiKey?: string;\n /**\n * Verification token, scoped to one end user. This is the credential a\n * client app should hold: mint it on your server with\n * `client.verifications.createToken(externalId)` and hand it out.\n *\n * A function is called before each request, so a token can be refreshed\n * without rebuilding the client.\n */\n verificationToken?: string | VerificationTokenProvider;\n /** URI version segment. Defaults to `v1`. */\n apiVersion?: string;\n /** Per-attempt timeout in ms. Defaults to 30000. */\n timeoutMs?: number;\n /** Retries for a failed attempt. Defaults to 2 (three attempts in total). */\n maxRetries?: number;\n /** Custom fetch (tests, proxies, a Node agent). Defaults to global fetch. */\n fetch?: FetchLike;\n /** Extra headers on every request. Cannot override the auth headers. */\n headers?: Record<string, string>;\n /**\n * Allows an `http://` baseUrl to a non-loopback host.\n *\n * Off by default: the requests carry a project API key or a verification\n * token and the responses carry identity-document data, none of which may\n * cross a plaintext connection.\n */\n allowInsecureBaseUrl?: boolean;\n /**\n * Allows `apiKey` in a browser or React Native app.\n *\n * Only for a trusted first-party context (an internal operations console\n * behind a login). Anything shipped to end users must use a verification\n * token: an API key in a client bundle is extractable and grants the whole\n * project, every identity in it included.\n */\n allowApiKeyInUntrustedClient?: boolean;\n}\n\nexport interface RequestOptions {\n method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n /** Path below the version segment, e.g. `/verification/start`. */\n path: string;\n query?: Record<string, unknown>;\n /** JSON request body. Mutually exclusive with `form`. */\n body?: unknown;\n /** Multipart body. Values typed `FileInput` are normalized per platform. */\n form?: Record<string, string | FileInput | undefined>;\n /** Field names in `form` that hold a file. */\n fileFields?: string[];\n auth?: AuthMode;\n signal?: AbortSignal;\n /** Overrides the client's timeout for this call. */\n timeoutMs?: number;\n /**\n * Whether a failed attempt may be repeated.\n *\n * Defaults to true for GET and false for everything else: a POST that timed\n * out may well have been processed, and re-sending an upload would emit a\n * second pipeline event. A 429 is retried regardless of method, because the\n * gateway rejected it before doing any work.\n */\n retry?: boolean;\n}\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\nconst BASE_BACKOFF_MS = 300;\nconst MAX_BACKOFF_MS = 5_000;\n\n/** Hosts for which plaintext http is legitimate: a developer's own machine. */\nconst LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '::1', '[::1]', '0.0.0.0']);\n\n/**\n * True in a context where the bundle is delivered to an end user and anything\n * inside it is readable by them: a browser page or a React Native app.\n */\nexport function isUntrustedClient(): boolean {\n if (\n typeof navigator !== 'undefined' &&\n (navigator as { product?: string }).product === 'ReactNative'\n ) {\n return true;\n }\n\n if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {\n return true;\n }\n\n // A worker is a browser context with no `window`, so the check above misses\n // it -- and code shipped to a worker is just as readable as code shipped to\n // a page. `importScripts` is the classic marker; the global-scope name\n // covers module workers, which do not have it.\n const scope = globalThis as { importScripts?: unknown; constructor?: { name?: string } };\n if (typeof scope.importScripts === 'function') return true;\n return /WorkerGlobalScope$/.test(scope.constructor?.name ?? '');\n}\n\nfunction assertUsableBaseUrl(baseUrl: string, allowInsecure: boolean): URL {\n let url: URL;\n try {\n url = new URL(baseUrl);\n } catch {\n throw new KycirisError(\n `baseUrl \"${baseUrl}\" is not a valid URL. Expected something like https://api.kyciris.com.`,\n { code: 'CONFIG_ERROR' }\n );\n }\n\n if (url.protocol === 'https:') return url;\n\n if (url.protocol !== 'http:') {\n throw new KycirisError(`baseUrl must be http:// or https://, not ${url.protocol}`, {\n code: 'CONFIG_ERROR',\n });\n }\n\n if (LOOPBACK_HOSTS.has(url.hostname) || allowInsecure) return url;\n\n throw new KycirisError(\n `baseUrl \"${baseUrl}\" is plaintext http to a remote host. API keys, verification tokens and identity-document data would travel unencrypted. Use https, or set allowInsecureBaseUrl if this is a trusted private network.`,\n { code: 'CONFIG_ERROR' }\n );\n}\n\n/** `Retry-After` as milliseconds, whether it is a delay or an HTTP date. */\nfunction parseRetryAfter(header: string | null): number | undefined {\n if (!header) return undefined;\n const seconds = Number(header);\n if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1000;\n const date = Date.parse(header);\n if (!Number.isNaN(date)) return Math.max(0, date - Date.now());\n return undefined;\n}\n\n/** Exponential backoff with full jitter, so retries do not synchronise. */\nfunction backoffDelay(attempt: number): number {\n const ceiling = Math.min(MAX_BACKOFF_MS, BASE_BACKOFF_MS * 2 ** attempt);\n return Math.random() * ceiling;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new KycirisError('The request was aborted.', { code: 'ABORTED' }));\n return;\n }\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n function onAbort() {\n clearTimeout(timer);\n reject(new KycirisError('The request was aborted.', { code: 'ABORTED' }));\n }\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n\n/**\n * The gateway's HTTP transport: URL and auth assembly, timeouts, retries, and\n * translation of the `{ data, meta }` / `{ error, meta }` envelopes into\n * values and KycirisErrors.\n */\nexport class HttpClient {\n private readonly baseUrl: URL;\n private readonly apiVersion: string;\n private readonly timeoutMs: number;\n private readonly maxRetries: number;\n private readonly fetchImpl: FetchLike;\n private readonly extraHeaders: Record<string, string>;\n private readonly apiKey?: string;\n private readonly tokenSource?: string | VerificationTokenProvider;\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = assertUsableBaseUrl(\n config.baseUrl,\n config.allowInsecureBaseUrl ?? false\n );\n\n if (!config.apiKey && !config.verificationToken) {\n throw new KycirisError(\n 'Provide either apiKey (server-side) or verificationToken (client-side) when creating the client.',\n { code: 'CONFIG_ERROR' }\n );\n }\n\n if (\n config.apiKey &&\n isUntrustedClient() &&\n !config.allowApiKeyInUntrustedClient\n ) {\n throw new KycirisError(\n 'A project API key must not be used from a browser or React Native app: it is readable by anyone who has the bundle and grants access to every identity in the project. Mint a verification token on your server (POST /verification/token) and pass it as verificationToken instead.',\n { code: 'CREDENTIAL_MISUSE' }\n );\n }\n\n this.apiKey = config.apiKey;\n this.tokenSource = config.verificationToken;\n this.apiVersion = (config.apiVersion ?? 'v1').replace(/^\\/+|\\/+$/g, '');\n this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n this.maxRetries = Math.max(0, config.maxRetries ?? DEFAULT_MAX_RETRIES);\n this.extraHeaders = { ...config.headers };\n\n const fetchImpl = config.fetch ?? (globalThis.fetch as FetchLike | undefined);\n if (!fetchImpl) {\n throw new KycirisError(\n 'No global fetch was found. Use Node 18+, or pass a fetch implementation as `fetch`.',\n { code: 'CONFIG_ERROR' }\n );\n }\n this.fetchImpl = fetchImpl;\n }\n\n /** True when the client holds a project API key. */\n hasApiKey(): boolean {\n return Boolean(this.apiKey);\n }\n\n /** True when the client holds (or can fetch) a verification token. */\n hasVerificationToken(): boolean {\n return Boolean(this.tokenSource);\n }\n\n buildUrl(path: string, query?: Record<string, unknown>): string {\n const basePath = this.baseUrl.pathname.replace(/\\/+$/, '');\n const url = new URL(this.baseUrl.toString());\n url.pathname = `${basePath}/${this.apiVersion}${path.startsWith('/') ? path : `/${path}`}`;\n\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined || value === null) continue;\n if (Array.isArray(value)) {\n // The gateway accepts a repeated param and a comma-separated list;\n // repeating is what every HTTP client emits natively.\n for (const entry of value) {\n if (entry !== undefined && entry !== null) {\n url.searchParams.append(key, String(entry));\n }\n }\n } else {\n url.searchParams.append(key, String(value));\n }\n }\n }\n\n return url.toString();\n }\n\n private async authHeaders(mode: AuthMode): Promise<Record<string, string>> {\n if (mode === 'none') return {};\n\n if (mode === 'api-key') {\n if (!this.apiKey) {\n throw new KycirisError(\n 'This endpoint requires the project API key, which is a server-side credential. A verification token is scoped to one end user and is refused here.',\n { code: 'MISSING_CREDENTIAL', status: 401 }\n );\n }\n return { 'X-API-Key': this.apiKey };\n }\n\n const token = await this.resolveToken();\n\n if (mode === 'token') {\n if (!token) {\n throw new KycirisError(\n 'This endpoint requires a verification token. Mint one with client.verifications.createToken(externalId) using the project API key.',\n { code: 'MISSING_CREDENTIAL', status: 401 }\n );\n }\n return { 'x-verification-token': token };\n }\n\n // 'any': the narrower credential wins, so a client configured with both\n // never sends the project key where an end-user token would do.\n if (token) return { 'x-verification-token': token };\n if (this.apiKey) return { 'X-API-Key': this.apiKey };\n\n throw new KycirisError('No credential is configured for this request.', {\n code: 'MISSING_CREDENTIAL',\n status: 401,\n });\n }\n\n private async resolveToken(): Promise<string | undefined> {\n if (!this.tokenSource) return undefined;\n if (typeof this.tokenSource === 'string') return this.tokenSource;\n const token = await this.tokenSource();\n if (typeof token !== 'string' || !token) {\n throw new KycirisError(\n 'The verificationToken provider returned no token.',\n { code: 'MISSING_CREDENTIAL', status: 401 }\n );\n }\n return token;\n }\n\n private async buildForm(\n form: Record<string, string | FileInput | undefined>,\n fileFields: string[]\n ): Promise<FormData> {\n if (typeof FormData === 'undefined') {\n throw new KycirisError(\n 'This runtime has no FormData, so files cannot be uploaded. Node 18+ is required.',\n { code: 'CONFIG_ERROR' }\n );\n }\n\n const formData = new FormData();\n for (const [field, value] of Object.entries(form)) {\n if (value === undefined) continue;\n if (fileFields.includes(field)) {\n const file = await prepareFile(value as FileInput, `${field}.jpg`);\n // `as never`: React Native's FormData takes a `{ uri }` object that the\n // DOM typings do not describe, and it is the only thing that works there.\n formData.append(field, file.value as never, file.filename);\n } else {\n formData.append(field, String(value));\n }\n }\n return formData;\n }\n\n /** Runs a request, retrying where the method and failure allow it. */\n async request<T>(options: RequestOptions): Promise<ApiResult<T>> {\n const method = options.method ?? 'GET';\n const url = this.buildUrl(options.path, options.query);\n const idempotent = options.retry ?? method === 'GET';\n\n // Built once, outside the retry loop: normalizing a file is CPU-bound work\n // on a multi-megabyte image and the result is immutable.\n const formData = options.form\n ? await this.buildForm(options.form, options.fileFields ?? [])\n : undefined;\n\n let attempt = 0;\n for (;;) {\n try {\n return await this.attempt<T>(options, method, url, formData);\n } catch (error) {\n const failure = error as KycirisError;\n const canRetry =\n attempt < this.maxRetries &&\n KycirisError.isKycirisError(failure) &&\n failure.retryable &&\n // A rate-limited request never ran, so repeating it is safe whatever\n // the method. Everything else is only repeated when the caller says\n // the call can be made twice.\n (idempotent || failure.status === 429);\n\n if (!canRetry) throw error;\n\n const delay = failure.status === 429 && failure.details\n ? ((failure.details as { retryAfterMs?: number }).retryAfterMs ??\n backoffDelay(attempt))\n : backoffDelay(attempt);\n\n await sleep(delay, options.signal);\n attempt += 1;\n }\n }\n }\n\n private async attempt<T>(\n options: RequestOptions,\n method: string,\n url: string,\n formData?: FormData\n ): Promise<ApiResult<T>> {\n // Checked before anything is set up: an AbortSignal that fired earlier\n // never fires again, so a listener alone would let the request go out.\n if (options.signal?.aborted) {\n throw new KycirisError('The request was aborted.', { code: 'ABORTED' });\n }\n\n const controller = new AbortController();\n const timeoutMs = options.timeoutMs ?? this.timeoutMs;\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n const onCallerAbort = () => controller.abort();\n options.signal?.addEventListener('abort', onCallerAbort, { once: true });\n\n try {\n const headers: Record<string, string> = {\n Accept: 'application/json',\n ...this.extraHeaders,\n ...(await this.authHeaders(options.auth ?? 'any')),\n };\n\n let body: BodyInit | undefined;\n if (formData) {\n // Content-Type is left to fetch, which has to add the multipart\n // boundary; setting it by hand produces a body the server cannot parse.\n body = formData;\n } else if (options.body !== undefined) {\n headers['Content-Type'] = 'application/json';\n body = JSON.stringify(options.body);\n }\n\n let response: Response;\n try {\n response = await this.fetchImpl(url, {\n method,\n headers,\n body,\n signal: controller.signal,\n });\n } catch (cause) {\n if (options.signal?.aborted) {\n throw new KycirisError('The request was aborted.', {\n code: 'ABORTED',\n cause,\n });\n }\n if (controller.signal.aborted) {\n throw new KycirisError(\n `The request to ${options.path} timed out after ${timeoutMs}ms.`,\n { code: 'TIMEOUT', retryable: true, cause }\n );\n }\n throw new KycirisError(\n `The request to ${options.path} could not reach the gateway. Check connectivity, the baseUrl, and (in a browser) that this origin is in the gateway's ALLOWED_ORIGINS.`,\n { code: 'NETWORK_ERROR', retryable: true, cause }\n );\n }\n\n const payload = await readBody(response);\n\n if (!response.ok) {\n throw toApiError(response, payload, options.path);\n }\n\n // A body-less success. Not only 204: the gateway's DELETE handlers return\n // void, and its response interceptor passes `undefined` straight through\n // rather than wrapping it — so a delete answers 200 with an empty body,\n // which is not an envelope and must not be treated as a malformed one.\n //\n // An empty body is the discriminator, not the status: a non-empty body\n // that is not an envelope still raises INVALID_RESPONSE, because that\n // means something other than the gateway answered.\n if (response.status === 204 || payload === undefined) {\n return {\n data: undefined as T,\n meta: {\n requestId: response.headers.get('x-request-id') ?? '',\n timestamp: new Date().toISOString(),\n version: '',\n },\n };\n }\n\n return unwrapEnvelope<T>(payload, options.path);\n } finally {\n clearTimeout(timer);\n options.signal?.removeEventListener('abort', onCallerAbort);\n }\n }\n\n /**\n * Streams a response body instead of parsing it — the media download\n * endpoint returns an image, not an envelope.\n */\n async requestRaw(options: RequestOptions): Promise<Response> {\n if (options.signal?.aborted) {\n throw new KycirisError('The request was aborted.', { code: 'ABORTED' });\n }\n\n const url = this.buildUrl(options.path, options.query);\n const controller = new AbortController();\n const timeoutMs = options.timeoutMs ?? this.timeoutMs;\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n const onCallerAbort = () => controller.abort();\n options.signal?.addEventListener('abort', onCallerAbort, { once: true });\n\n try {\n const headers: Record<string, string> = {\n ...this.extraHeaders,\n ...(await this.authHeaders(options.auth ?? 'any')),\n };\n\n let response: Response;\n try {\n response = await this.fetchImpl(url, {\n method: options.method ?? 'GET',\n headers,\n signal: controller.signal,\n });\n } catch (cause) {\n if (options.signal?.aborted) {\n throw new KycirisError('The request was aborted.', { code: 'ABORTED', cause });\n }\n if (controller.signal.aborted) {\n throw new KycirisError(\n `The request to ${options.path} timed out after ${timeoutMs}ms.`,\n { code: 'TIMEOUT', retryable: true, cause }\n );\n }\n throw new KycirisError(\n `The request to ${options.path} could not reach the gateway.`,\n { code: 'NETWORK_ERROR', retryable: true, cause }\n );\n }\n\n if (!response.ok) {\n throw toApiError(response, await readBody(response), options.path);\n }\n\n return response;\n } finally {\n clearTimeout(timer);\n options.signal?.removeEventListener('abort', onCallerAbort);\n }\n }\n}\n\nasync function readBody(response: Response): Promise<unknown> {\n const contentType = response.headers.get('content-type') ?? '';\n try {\n if (contentType.includes('application/json')) {\n return await response.json();\n }\n const text = await response.text();\n if (!text) return undefined;\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n } catch {\n return undefined;\n }\n}\n\n/**\n * Turns a non-2xx response into a KycirisError carrying the gateway's own\n * error code and requestId.\n *\n * Nothing from the request is attached — the headers hold the API key and the\n * verification token, and an error object is the thing most likely to be\n * logged whole.\n */\nfunction toApiError(\n response: Response,\n payload: unknown,\n path: string\n): KycirisError {\n const { code, message, details } = readErrorEnvelope(payload);\n const retryAfterMs = parseRetryAfter(response.headers.get('retry-after'));\n\n const fallback =\n response.status === 401\n ? 'The credential was rejected. Check the API key, or mint a fresh verification token — they expire.'\n : response.status === 403\n ? 'The gateway refused this request.'\n : `The gateway returned ${response.status} for ${path}.`;\n\n return new KycirisError(message || fallback, {\n code: code ?? statusFallbackCode(response.status),\n status: response.status,\n requestId:\n readRequestId(payload) ?? response.headers.get('x-request-id') ?? undefined,\n details:\n retryAfterMs !== undefined\n ? { ...(typeof details === 'object' && details ? details : { details }), retryAfterMs }\n : details,\n retryable: isRetryableStatus(response.status),\n });\n}\n\nfunction statusFallbackCode(status: number): string {\n switch (status) {\n case 400:\n case 422:\n return 'VALIDATION_ERROR';\n case 401:\n return 'UNAUTHORIZED';\n case 403:\n return 'FORBIDDEN';\n case 404:\n return 'NOT_FOUND';\n case 409:\n return 'RESOURCE_ALREADY_EXISTS';\n case 429:\n return 'RATE_LIMIT_EXCEEDED';\n default:\n return 'INTERNAL_SERVER_ERROR';\n }\n}\n","import type { HttpClient } from '../http/client';\nimport type { Analytics } from '../types';\n\n/** Monthly identity and verification counts, with month-over-month change. */\nexport class AnalyticsResource {\n constructor(private readonly http: HttpClient) {}\n\n async get(options: { signal?: AbortSignal } = {}): Promise<Analytics> {\n const result = await this.http.request<Analytics>({\n path: '/analytics',\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n}\n","import { KycirisError } from './errors';\n\nexport interface PollOptions {\n /** Delay between attempts, in ms. Defaults to 3000. */\n intervalMs?: number;\n /** Give up after this long, in ms. Defaults to 120000. */\n timeoutMs?: number;\n /** Cancels the poll; the promise rejects with code ABORTED. */\n signal?: AbortSignal;\n}\n\nexport interface PollCallbacks<T> {\n /** Called with every intermediate value, before the done check. */\n onUpdate?: (value: T) => void;\n}\n\nconst DEFAULT_INTERVAL_MS = 3_000;\nconst DEFAULT_TIMEOUT_MS = 120_000;\n\nfunction abortError(): KycirisError {\n return new KycirisError('Polling was aborted.', { code: 'ABORTED' });\n}\n\n/**\n * Calls `fetchOnce` until `isDone` accepts the result, the timeout elapses, or\n * the caller aborts.\n *\n * Written as a loop with an awaited delay rather than a self-scheduling\n * setTimeout so that a cancelled poll actually stops: the previous\n * implementation left a pending timer behind after rejecting, which in React\n * Native keeps the JS context awake and warns about a setState on an unmounted\n * component.\n *\n * The timeout is checked before sleeping as well as after, so a poll never\n * waits out one final interval it has no time left to use.\n */\nexport async function pollUntil<T>(\n fetchOnce: (signal?: AbortSignal) => Promise<T>,\n isDone: (value: T) => boolean,\n options: PollOptions & PollCallbacks<T> = {},\n description = 'the operation'\n): Promise<T> {\n const intervalMs = Math.max(0, options.intervalMs ?? DEFAULT_INTERVAL_MS);\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const deadline = Date.now() + timeoutMs;\n\n for (;;) {\n if (options.signal?.aborted) throw abortError();\n\n const value = await fetchOnce(options.signal);\n options.onUpdate?.(value);\n\n if (isDone(value)) return value;\n\n const remaining = deadline - Date.now();\n if (remaining <= 0) {\n throw new KycirisError(\n `Timed out after ${timeoutMs}ms waiting for ${description} to finish. It may still complete — read the status again later, or subscribe to the webhook instead of polling.`,\n { code: 'POLL_TIMEOUT', details: { lastValue: value } }\n );\n }\n\n await delay(Math.min(intervalMs, remaining), options.signal);\n }\n}\n\nfunction delay(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(abortError());\n return;\n }\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n function onAbort() {\n clearTimeout(timer);\n reject(abortError());\n }\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n","import type { FileInput } from '../files';\nimport type { HttpClient } from '../http/client';\nimport { toPage, type Page } from '../http/envelope';\nimport { pollUntil, type PollCallbacks, type PollOptions } from '../poll';\nimport type {\n DuplicateField,\n FaceCheck,\n Identity,\n IdentityFields,\n IdentitySummary,\n ListIdentitiesParams,\n VerificationListItem,\n} from '../types';\n\nexport interface DuplicateGroup {\n value: string;\n count: number;\n identities: IdentitySummary[];\n}\n\nexport interface DuplicatesByField {\n field: string;\n totalDuplicateGroups: number;\n totalDuplicateIdentities: number;\n duplicates: DuplicateGroup[];\n}\n\nexport interface DuplicatesByFields {\n fields: string[];\n results: Record<string, DuplicatesByField>;\n}\n\n/**\n * The identity records behind verifications — the person, as opposed to any\n * one attempt to verify them.\n *\n * Every endpoint here needs the project API key. A verification token is\n * scoped to a single end user's flow and is refused, which is deliberate: an\n * identity record holds the full extracted document data, and a client app has\n * no business reading the project's identities.\n */\nexport class IdentitiesResource {\n constructor(private readonly http: HttpClient) {}\n\n /** Registers an identity independently of any verification. */\n async create(\n fields: IdentityFields,\n options: { signal?: AbortSignal } = {}\n ): Promise<Identity> {\n const result = await this.http.request<Identity>({\n method: 'POST',\n path: '/identities',\n body: fields,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /** A page of identity summaries. Read one identity for the full record. */\n async list(\n params: ListIdentitiesParams = {},\n options: { signal?: AbortSignal } = {}\n ): Promise<Page<IdentitySummary>> {\n const result = await this.http.request<IdentitySummary[]>({\n path: '/identities',\n query: { ...params },\n auth: 'api-key',\n signal: options.signal,\n });\n return toPage(result);\n }\n\n /** The full record, including its verification history. */\n async get(id: string, options: { signal?: AbortSignal } = {}): Promise<Identity> {\n const result = await this.http.request<Identity>({\n path: `/identities/${encodeURIComponent(id)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /** This identity's verifications, without embeddings or storage paths. */\n async verifications(\n id: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<VerificationListItem[]> {\n const result = await this.http.request<VerificationListItem[]>({\n path: `/identities/${encodeURIComponent(id)}/verifications`,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data ?? [];\n }\n\n async update(\n id: string,\n fields: IdentityFields,\n options: { signal?: AbortSignal } = {}\n ): Promise<Identity> {\n const result = await this.http.request<Identity>({\n method: 'PUT',\n path: `/identities/${encodeURIComponent(id)}`,\n body: fields,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /** Deletes the identity, its verifications, and the stored images. */\n async delete(id: string, options: { signal?: AbortSignal } = {}): Promise<void> {\n await this.http.request<void>({\n method: 'DELETE',\n path: `/identities/${encodeURIComponent(id)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n }\n\n /**\n * Groups identities that share a value, to find duplicate registrations.\n *\n * Passing one field returns a single grouping; passing several returns one\n * per field, which is why the return type is a union.\n */\n async findDuplicates(\n params: { field?: DuplicateField | DuplicateField[]; id?: string } = {},\n options: { signal?: AbortSignal } = {}\n ): Promise<DuplicatesByField | DuplicatesByFields> {\n const result = await this.http.request<DuplicatesByField | DuplicatesByFields>({\n path: '/identities/duplicates',\n query: { field: params.field, id: params.id },\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /**\n * Folds duplicates into a primary identity, moving their verifications\n * across and deleting them. Requires the admin role on a user token; an API\n * key is a project credential and carries no role.\n */\n async merge(\n id: string,\n duplicateIds: string[],\n options: { signal?: AbortSignal } = {}\n ): Promise<unknown> {\n const result = await this.http.request<unknown>({\n method: 'POST',\n path: '/identities/merge',\n body: { id, duplicateIds },\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /**\n * Compares a fresh photo against the face already on file for an identity —\n * a re-authentication check, separate from the verification flow.\n *\n * Asynchronous: the returned check starts PENDING. Poll it with\n * `faceCheckStatus`, or use `waitForFaceCheck`.\n */\n async faceMatch(\n id: string,\n file: FileInput,\n options: { signal?: AbortSignal; timeoutMs?: number } = {}\n ): Promise<FaceCheck> {\n const result = await this.http.request<FaceCheck>({\n method: 'POST',\n path: `/identities/${encodeURIComponent(id)}/face-match`,\n form: { file },\n fileFields: ['file'],\n auth: 'api-key',\n signal: options.signal,\n timeoutMs: options.timeoutMs,\n });\n return result.data;\n }\n\n /** The result of a face-match check started with `faceMatch`. */\n async faceCheckStatus(\n id: string,\n faceCheckId: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<FaceCheck> {\n const result = await this.http.request<FaceCheck>({\n path: `/identities/${encodeURIComponent(id)}/face-match/status/${encodeURIComponent(faceCheckId)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /** Polls a face-match check until it is APPROVED or REJECTED. */\n async waitForFaceCheck(\n id: string,\n faceCheckId: string,\n options: PollOptions & PollCallbacks<FaceCheck> = {}\n ): Promise<FaceCheck> {\n return pollUntil<FaceCheck>(\n (signal) => this.faceCheckStatus(id, faceCheckId, { signal }),\n (check) => check.status === 'APPROVED' || check.status === 'REJECTED',\n options,\n `face check ${faceCheckId}`\n );\n }\n}\n","import type { HttpClient } from '../http/client';\nimport type { VerificationLevel, VerificationLevelDefinition } from '../types';\n\nexport interface CreateLevelParams {\n /** Unique within the project. */\n name: string;\n definition: VerificationLevelDefinition;\n isActive?: boolean;\n}\n\nexport interface UpdateLevelParams {\n name?: string;\n /** Replaces the required steps entirely. */\n definition?: VerificationLevelDefinition;\n isActive?: boolean;\n}\n\n/**\n * Verification levels: named, reusable policies saying which steps a\n * verification requires and which documents it accepts.\n *\n * Every verification names one at start time (`levelName`), and there is no\n * default: a project can verify nobody until it has at least one active level,\n * and a definition must include an IDENTITY_DOCUMENT step saying which\n * (country, documentType) pairs it accepts.\n *\n * API key only, and creating or changing one needs the admin role when acting\n * as a user. Deleting is a soft delete, so verifications that already ran keep\n * the rules they ran under.\n */\nexport class LevelsResource {\n constructor(private readonly http: HttpClient) {}\n\n async create(\n params: CreateLevelParams,\n options: { signal?: AbortSignal } = {}\n ): Promise<VerificationLevel> {\n const result = await this.http.request<VerificationLevel>({\n method: 'POST',\n path: '/verification-levels',\n body: params,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n async list(options: { signal?: AbortSignal } = {}): Promise<VerificationLevel[]> {\n const result = await this.http.request<VerificationLevel[]>({\n path: '/verification-levels',\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data ?? [];\n }\n\n async get(\n id: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<VerificationLevel> {\n const result = await this.http.request<VerificationLevel>({\n path: `/verification-levels/${encodeURIComponent(id)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n async update(\n id: string,\n params: UpdateLevelParams,\n options: { signal?: AbortSignal } = {}\n ): Promise<VerificationLevel> {\n const result = await this.http.request<VerificationLevel>({\n method: 'PUT',\n path: `/verification-levels/${encodeURIComponent(id)}`,\n body: params,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n async delete(id: string, options: { signal?: AbortSignal } = {}): Promise<void> {\n await this.http.request<void>({\n method: 'DELETE',\n path: `/verification-levels/${encodeURIComponent(id)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n }\n}\n","import type { HttpClient } from '../http/client';\nimport type { MediaResource } from '../types';\n\nexport interface DownloadToken {\n token: string;\n /** Lifetime in seconds. The gateway fixes it at 60. */\n expiresIn: number;\n}\n\n/**\n * Access to the images behind a verification: the selfie, both document pages,\n * and the face the OCR worker cropped out of the document.\n *\n * Downloads are two calls on purpose. The first, authenticated with the project\n * API key, issues a token for exactly one file; the second exchanges it for the\n * bytes. The token lives 60 seconds, is invalidated the first time it is used,\n * and every use is written to the gateway's media access log — so an image URL\n * that leaks into a browser history, a screenshot or a support ticket is worth\n * nothing by the time anyone finds it.\n */\nexport class MediaResourceApi {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Issues a single-use, 60-second token for one file of one verification.\n *\n * Useful on its own when the bytes should be fetched somewhere else — hand\n * the token to a browser and let it call the download URL directly, without\n * the API key ever leaving your server.\n */\n async createDownloadToken(\n verificationId: string,\n resource: MediaResource,\n options: { signal?: AbortSignal } = {}\n ): Promise<DownloadToken> {\n const result = await this.http.request<DownloadToken>({\n method: 'POST',\n path: `/media/token/${encodeURIComponent(verificationId)}`,\n body: { resource },\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /**\n * The URL that exchanges a download token for the file.\n *\n * Treat it as a credential: the token is the whole authorization, so the URL\n * grants the image to whoever holds it, once.\n */\n downloadUrl(token: string): string {\n return this.http.buildUrl('/media/download', { token });\n }\n\n /**\n * Fetches a file, taking care of both steps.\n *\n * Returns the raw Response so a caller can stream it (to disk, or straight\n * into an HTTP response) instead of holding an identity document in memory.\n */\n async download(\n verificationId: string,\n resource: MediaResource,\n options: { signal?: AbortSignal } = {}\n ): Promise<Response> {\n const { token } = await this.createDownloadToken(verificationId, resource, options);\n return this.http.requestRaw({\n path: '/media/download',\n query: { token },\n // The single-use token *is* the credential here; sending the API key as\n // well would put it on a URL-addressed request for no benefit.\n auth: 'none',\n signal: options.signal,\n });\n }\n\n /** Fetches a file and buffers it. Convenient; holds the image in memory. */\n async downloadBytes(\n verificationId: string,\n resource: MediaResource,\n options: { signal?: AbortSignal } = {}\n ): Promise<Uint8Array> {\n const response = await this.download(verificationId, resource, options);\n return new Uint8Array(await response.arrayBuffer());\n }\n}\n","/**\n * Domain types mirroring the KYCiris gateway's public contract.\n *\n * Everything here is derived from the gateway's DTOs and constants; where the\n * gateway is the authority for a set of values (document catalog, statuses,\n * webhook events) the list is reproduced verbatim rather than widened to\n * `string`, so a typo fails at compile time instead of at runtime with a 422.\n */\n\n// ---------------------------------------------------------------------------\n// Documents\n// ---------------------------------------------------------------------------\n\n/**\n * The (country, documentType) pairs the pipeline can actually process.\n *\n * Mirrors DOCUMENT_CATALOG in the gateway, which in turn mirrors the OCR\n * worker's handler registry — a pair is only real once something knows how to\n * read it. Starting a verification for a pair outside this list is rejected by\n * the gateway with VALIDATION_ERROR.\n */\nexport const DOCUMENT_CATALOG = [\n { country: 'AO', documentType: 'ID_CARD' },\n { country: 'AO', documentType: 'DRIVING_LICENSE' },\n { country: 'MZ', documentType: 'ID_CARD' },\n] as const;\n\nexport type DocumentCatalogEntry = (typeof DOCUMENT_CATALOG)[number];\n\n/** ISO 3166-1 alpha-2 codes present in the catalog. */\nexport type CatalogCountry = DocumentCatalogEntry['country'];\n\n/** Document type codes present in the catalog. */\nexport type DocumentType = DocumentCatalogEntry['documentType'];\n\n/** True when the gateway can process this pair. */\nexport function isSupportedDocumentPair(\n country: string,\n documentType: string\n): boolean {\n return DOCUMENT_CATALOG.some(\n (entry) => entry.country === country && entry.documentType === documentType\n );\n}\n\n/** The countries in the catalog, deduplicated. */\nexport function supportedCountries(): CatalogCountry[] {\n return Array.from(new Set(DOCUMENT_CATALOG.map((entry) => entry.country)));\n}\n\n/** The document types the catalog supports for `country`. */\nexport function supportedDocumentTypes(country: string): DocumentType[] {\n return DOCUMENT_CATALOG.filter((entry) => entry.country === country).map(\n (entry) => entry.documentType\n );\n}\n\n// ---------------------------------------------------------------------------\n// Verification lifecycle\n// ---------------------------------------------------------------------------\n\n/** The pipeline's state machine, as written by the gateway and its workers. */\nexport const VERIFICATION_STATUSES = [\n 'PENDING',\n 'PROCESSING',\n 'REVIEW',\n 'APPROVED',\n 'REJECTED',\n] as const;\n\nexport type VerificationStatus = (typeof VERIFICATION_STATUSES)[number];\n\n/**\n * What a verification *means* operationally, derived by the gateway from the\n * status and rejection code.\n *\n * The distinction that `status` alone cannot make: REJECTED is written both\n * when the rules genuinely said no and when our own OCR choked on a valid\n * document. Those want opposite handling — the first is an answer for the end\n * user, the second is a retry for us.\n */\nexport const VERIFICATION_OUTCOMES = [\n /** Passed. */\n 'APPROVED',\n /** A genuine business decision. Retrying cannot change it. */\n 'REJECTED',\n /** The pipeline broke. Not the user's fault; retry once fixed. */\n 'FAILED_TECHNICAL',\n /** Could be either — a human should look at the images. */\n 'NEEDS_REVIEW',\n] as const;\n\nexport type VerificationOutcome = (typeof VERIFICATION_OUTCOMES)[number];\n\n/** Statuses from which the pipeline will not move on its own. */\nexport const TERMINAL_VERIFICATION_STATUSES = ['APPROVED', 'REJECTED'] as const;\n\n/** True when the pipeline has reached a decision for this status. */\nexport function isTerminalStatus(status: string): boolean {\n return (TERMINAL_VERIFICATION_STATUSES as readonly string[]).includes(status);\n}\n\n/** A step the end user has to complete before the pipeline can decide. */\nexport type VerificationStep = 'document_front' | 'document_back' | 'selfie';\n\n/** The side of an identity document being uploaded. */\nexport type DocumentSide = 'front' | 'back';\n\n/** Files a verification can hold, as named by the gateway's media endpoints. */\nexport type MediaResource =\n | 'selfie'\n | 'document-front'\n | 'document-back'\n | 'document-face';\n\n// ---------------------------------------------------------------------------\n// Request / response payloads\n// ---------------------------------------------------------------------------\n\nexport interface StartVerificationParams {\n /** Must form a supported pair with `country` (see DOCUMENT_CATALOG). */\n documentType: DocumentType | (string & {});\n /** ISO 3166-1 alpha-2 country code. */\n country: CatalogCountry | (string & {});\n /** Link to an existing identity instead of creating a new one. */\n identityId?: string;\n /**\n * Your own reference for this end user.\n *\n * Ignored when the client authenticates with a verification token: that token\n * is already bound to one externalId, and the gateway treats the token's\n * value as authoritative so a token cannot create a verification under\n * someone else's reference.\n */\n externalId?: string;\n /**\n * Name of the verification level (policy) to run under. Required.\n *\n * The level is what says which documents the project accepts and whether a\n * selfie is needed, so the gateway has no verification without one: a start\n * that names no level, or names one that is not active on the project, is\n * rejected (422 / 404). Levels are created from your backend with\n * `client.levels.create()` -- a project can verify nobody until it has one.\n */\n levelName: string;\n}\n\nexport interface VerificationSession {\n verificationId: string;\n identityId?: string;\n status: VerificationStatus;\n}\n\n/** OCR output. Fields present depend on the document; unread fields are null. */\nexport interface OcrData {\n country?: string | null;\n documentType?: string | null;\n fullName?: string | null;\n idNumber?: string | null;\n birthDate?: string | null;\n validFrom?: string | null;\n validUntil?: string | null;\n gender?: string | null;\n height?: number | null;\n address?: string | null;\n mrz?: string | null;\n maritalStatus?: string | null;\n [field: string]: unknown;\n}\n\nexport interface VerificationStatusResponse {\n verificationId: string;\n status: VerificationStatus;\n /** Null while still PENDING/PROCESSING — no outcome exists yet. */\n outcome: VerificationOutcome | null;\n /** 0-1 similarity between selfie and document photo; null until computed. */\n faceMatchScore: number | null;\n /** Null until the document front has been processed. */\n ocrData: OcrData | null;\n /** A gateway ERROR_CODE naming why, when the pipeline stopped or refused. */\n rejectionType: string | null;\n rejectionReason: string | null;\n /** An operator's email, \"system\", or null. */\n decidedBy: string | null;\n decidedAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface UploadResult {\n message: string;\n status: VerificationStatus;\n}\n\n/** One row of the operations list. Deliberately free of OCR data and paths. */\nexport interface VerificationListItem {\n id: string;\n externalId: string | null;\n status: VerificationStatus;\n outcome: VerificationOutcome | null;\n /** True when it has sat in flight past the gateway's stall threshold. */\n stalled: boolean;\n country: string | null;\n documentType: string | null;\n faceMatchScore: number | null;\n rejectionType: string | null;\n rejectionReason: string | null;\n decidedBy: string | null;\n decidedAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ListVerificationsParams {\n page?: number;\n /** 1-100; the gateway rejects anything larger. */\n limit?: number;\n status?: VerificationStatus[];\n outcome?: VerificationOutcome;\n /** Only stalled (true) or only healthy (false). Omit for both. */\n stalled?: boolean;\n country?: string;\n documentType?: string;\n /** Exact match on your own reference. */\n externalId?: string;\n /** ISO 8601 instant. */\n createdAfter?: string;\n /** ISO 8601 instant. */\n createdBefore?: string;\n order?: 'ASC' | 'DESC';\n}\n\nexport interface VerificationSummary {\n byStatus: Partial<Record<VerificationStatus, number>>;\n byOutcome: Partial<Record<VerificationOutcome, number>>;\n needsAttention: {\n stalled: number;\n failedTechnical: number;\n needsReview: number;\n parkedMessages: number;\n };\n}\n\n/** What kind of thing one history entry records. */\nexport const PIPELINE_EVENT_KINDS = [\n /** The verification was created — the start of every timeline. */\n 'CREATED',\n /** The status moved; `fromStatus`/`toStatus` say where. */\n 'STATUS_CHANGED',\n /**\n * The pipeline was re-run from the uploaded files, clearing what had been\n * extracted. Not a STATUS_CHANGED: a re-run of an already-PROCESSING\n * verification would otherwise read \"PROCESSING -> PROCESSING\", which says\n * nothing while hiding the destructive part.\n */\n 'REPROCESSED',\n /** A queue message for it exhausted every retry and was stored. */\n 'JOB_PARKED',\n /** A parked message was handed back to its handler. */\n 'JOB_RESENT',\n /** A parked message was abandoned. Reversible — a resend may follow. */\n 'JOB_DISCARDED',\n] as const;\n\nexport type PipelineEventKind = (typeof PIPELINE_EVENT_KINDS)[number];\n\n/**\n * One entry in a verification's history, appended and never updated.\n *\n * The verification row keeps only the last decision, so this is the only place\n * the sequence survives. Entries that predate the history simply do not exist —\n * a verification from before it shows its creation and last decision and\n * nothing between.\n */\nexport interface PipelineEvent {\n id: string;\n kind: PipelineEventKind | (string & {});\n fromStatus: string | null;\n toStatus: string | null;\n /**\n * Who did it, as a label frozen at the time — an operator's email, or\n * \"system\". A snapshot, so it stays true after the person is renamed or\n * removed.\n */\n actorLabel: string;\n actorUserId: string | null;\n /** The one thing worth reading beside the transition. */\n detail: string | null;\n createdAt: string;\n [field: string]: unknown;\n}\n\nexport interface ReviewDecision {\n decision: 'APPROVED' | 'REJECTED';\n /** Stored when rejecting. */\n reason?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Verification levels\n// ---------------------------------------------------------------------------\n\nexport interface IdentityDocumentStep {\n step: 'IDENTITY_DOCUMENT';\n required: true;\n documents: { country: string; types: string[] }[];\n}\n\nexport interface SelfieStep {\n step: 'SELFIE';\n required: boolean;\n /** Accepted but not enforced by the gateway yet. */\n liveness?: boolean;\n}\n\nexport type VerificationLevelStep = IdentityDocumentStep | SelfieStep;\n\nexport interface VerificationLevelDefinition {\n requiredSteps: VerificationLevelStep[];\n}\n\nexport interface VerificationLevel {\n id: string;\n name: string;\n isActive: boolean;\n definition: VerificationLevelDefinition;\n createdAt: string;\n updatedAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// Identities\n// ---------------------------------------------------------------------------\n\nexport interface IdentityFields {\n mrz?: string;\n gender?: string;\n height?: number;\n address?: string;\n country?: string;\n fullName?: string;\n idNumber?: string;\n birthDate?: string;\n maritalStatus?: string;\n}\n\nexport interface IdentitySummary extends IdentityFields {\n id: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface Identity extends IdentitySummary {\n verifications?: VerificationListItem[];\n [field: string]: unknown;\n}\n\nexport interface ListIdentitiesParams {\n page?: number;\n limit?: number;\n /** Partial match. */\n fullName?: string;\n country?: string;\n idNumber?: string;\n}\n\n/** Fields the gateway can group duplicate identities by. */\nexport const DUPLICATE_FIELDS = [\n 'fullName',\n 'idNumber',\n 'mrz',\n 'gender',\n 'country',\n 'birthDate',\n] as const;\n\nexport type DuplicateField = (typeof DUPLICATE_FIELDS)[number];\n\nexport interface FaceCheck {\n id: string;\n status: 'PENDING' | 'APPROVED' | 'REJECTED';\n}\n\n// ---------------------------------------------------------------------------\n// OCR (standalone)\n// ---------------------------------------------------------------------------\n\nexport type OcrProcessStatus = 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED';\n\nexport interface OcrProcess {\n id: string;\n status: OcrProcessStatus;\n documentType: string;\n country: string;\n createdAt: string;\n}\n\nexport interface OcrProcessStatusResponse {\n id: string;\n status: OcrProcessStatus;\n /** Present once COMPLETED. */\n ocrResult?: OcrData;\n documentPath?: string;\n createdAt: string;\n updatedAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// Webhooks\n// ---------------------------------------------------------------------------\n\nexport const WEBHOOK_EVENT_TYPES = [\n 'VERIFICATION_STARTED',\n 'VERIFICATION_COMPLETED',\n 'VERIFICATION_APPROVED',\n 'VERIFICATION_REJECTED',\n 'VERIFICATION_REVIEW_REQUIRED',\n 'OCR_COMPLETED',\n 'OCR_FAILED',\n] as const;\n\nexport type WebhookEventType = (typeof WEBHOOK_EVENT_TYPES)[number];\n\n/**\n * Subscribes to every event, including ones added after the endpoint was\n * registered. Prefer it over listing all seven when the intent is \"mirror my\n * verification lifecycle\" — a literal list silently stops being complete.\n */\nexport const ALL_WEBHOOK_EVENTS = '*';\n\nexport type WebhookSubscription = WebhookEventType | typeof ALL_WEBHOOK_EVENTS;\n\nexport interface Webhook {\n id: string;\n url: string;\n eventTypes: WebhookSubscription[];\n isActive: boolean;\n headers?: Record<string, string> | null;\n maxRetries?: number | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CreateWebhookParams {\n /** Must be https:// with a public hostname — the gateway refuses anything else. */\n url: string;\n eventTypes: WebhookSubscription[];\n headers?: Record<string, string>;\n maxRetries?: number;\n}\n\nexport interface UpdateWebhookParams {\n url?: string;\n /** Replaces the current list entirely. */\n eventTypes?: WebhookSubscription[];\n isActive?: boolean;\n headers?: Record<string, string>;\n maxRetries?: number;\n}\n\n/**\n * The result of replaying a delivery.\n *\n * A failed send is a value, not an exception: the gateway records a FAILED row\n * for the attempt either way, so the caller almost always wants to show why\n * beside the delivery it belongs to rather than catch around it.\n */\nexport type WebhookResendResult =\n | { success: true }\n | { success: false; error: string };\n\nexport interface WebhookLogEntry {\n id: string;\n url: string;\n status: string;\n responseStatus?: number | null;\n responseBody?: string | null;\n payload?: Record<string, unknown>;\n headers?: Record<string, string> | null;\n retries?: number | null;\n createdAt: string;\n updatedAt: string;\n [field: string]: unknown;\n}\n\n// ---------------------------------------------------------------------------\n// Analytics\n// ---------------------------------------------------------------------------\n\nexport interface AnalyticsSeries {\n change_percentage: number;\n /** Keyed by month, e.g. \"2026-07\". */\n monthly: Record<string, number>;\n total: number;\n}\n\nexport interface Analytics {\n identity: AnalyticsSeries;\n verification: AnalyticsSeries;\n}\n","import type { FileInput } from '../files';\nimport type { HttpClient } from '../http/client';\nimport { pollUntil, type PollCallbacks, type PollOptions } from '../poll';\nimport {\n isSupportedDocumentPair,\n supportedDocumentTypes,\n type CatalogCountry,\n type DocumentType,\n type OcrProcess,\n type OcrProcessStatusResponse,\n} from '../types';\nimport { KycirisError } from '../errors';\n\nexport interface RunOcrParams {\n documentType: DocumentType | (string & {});\n country: CatalogCountry | (string & {});\n /** Your own reference, for correlating the result. */\n externalId?: string;\n}\n\n/**\n * Standalone document reading, with no verification attached.\n *\n * The same OCR pipeline the verification flow uses, addressed directly: upload\n * a document, get the structured fields back. Nothing is decided and no\n * identity is created — for that, run a verification.\n */\nexport class OcrResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Queues a document for extraction.\n *\n * Returns as soon as the job is accepted; the fields arrive later, via\n * `getStatus` or `waitForResult`.\n */\n async run(\n file: FileInput,\n params: RunOcrParams,\n options: { signal?: AbortSignal; timeoutMs?: number } = {}\n ): Promise<OcrProcess> {\n if (!isSupportedDocumentPair(params.country, params.documentType)) {\n const forCountry = supportedDocumentTypes(params.country);\n throw new KycirisError(\n forCountry.length\n ? `${params.country} supports ${forCountry.join(', ')}, not ${params.documentType}.`\n : `No documents are supported for country \"${params.country}\".`,\n { code: 'VALIDATION_ERROR' }\n );\n }\n\n const result = await this.http.request<OcrProcess>({\n method: 'POST',\n path: '/ocr',\n // The gateway names this field `document`, not `file`.\n form: {\n document: file,\n documentType: params.documentType,\n country: params.country,\n externalId: params.externalId,\n },\n fileFields: ['document'],\n signal: options.signal,\n timeoutMs: options.timeoutMs,\n });\n return result.data;\n }\n\n /** Status of a queued job, with the extracted fields once COMPLETED. */\n async getStatus(\n ocrId: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<OcrProcessStatusResponse> {\n const result = await this.http.request<OcrProcessStatusResponse>({\n path: `/ocr/${encodeURIComponent(ocrId)}/status`,\n signal: options.signal,\n });\n return result.data;\n }\n\n /** Polls until the job is COMPLETED or FAILED. */\n async waitForResult(\n ocrId: string,\n options: PollOptions & PollCallbacks<OcrProcessStatusResponse> = {}\n ): Promise<OcrProcessStatusResponse> {\n return pollUntil<OcrProcessStatusResponse>(\n (signal) => this.getStatus(ocrId, { signal }),\n (process) => process.status === 'COMPLETED' || process.status === 'FAILED',\n options,\n `OCR job ${ocrId}`\n );\n }\n}\n","import { KycirisError } from '../errors';\nimport { prepareFile, type FileInput } from '../files';\nimport type { HttpClient } from '../http/client';\nimport { toPage, type Page } from '../http/envelope';\nimport { pollUntil, type PollCallbacks, type PollOptions } from '../poll';\nimport { SessionStore, type StoredSession } from '../storage';\nimport {\n isSupportedDocumentPair,\n isTerminalStatus,\n supportedDocumentTypes,\n type DocumentSide,\n type ListVerificationsParams,\n type MediaResource,\n type PipelineEvent,\n type ReviewDecision,\n type StartVerificationParams,\n type UploadResult,\n type VerificationListItem,\n type VerificationSession,\n type VerificationStatusResponse,\n type VerificationStep,\n type VerificationSummary,\n} from '../types';\n\nexport interface VerificationToken {\n token: string;\n /** The lifetime the gateway chose, e.g. \"8h\". The caller does not pick it. */\n expiresIn: string;\n}\n\nexport interface AvailableMedia {\n available: MediaResource[];\n}\n\nexport interface UploadOptions {\n signal?: AbortSignal;\n timeoutMs?: number;\n}\n\nexport interface VerificationProgress {\n verificationId: string;\n status: VerificationStatusResponse['status'];\n outcome: VerificationStatusResponse['outcome'];\n uploaded: Record<VerificationStep, boolean>;\n /** The steps still to collect, in the order they should be asked for. */\n missingSteps: VerificationStep[];\n /** True when nothing is left to upload. */\n isComplete: boolean;\n}\n\nexport interface ProgressOptions {\n /**\n * Whether the flow asks for a selfie. Defaults to true, matching the\n * gateway's own default when no verification level is set.\n *\n * A client authenticated with a verification token cannot read the level it\n * is running under — `/verification-levels` needs the project API key — so\n * when a level makes the selfie optional, say so here.\n */\n selfieRequired?: boolean;\n signal?: AbortSignal;\n}\n\nexport interface UploadStepParams {\n step: VerificationStep;\n file: FileInput;\n /** Defaults to the stored session's verification. */\n verificationId?: string;\n /** See ProgressOptions.selfieRequired. */\n selfieRequired?: boolean;\n signal?: AbortSignal;\n timeoutMs?: number;\n}\n\nexport interface UploadStepResult extends UploadResult {\n /** True when the step was already uploaded and nothing was sent. */\n skipped: boolean;\n}\n\nexport interface WaitForResultOptions extends PollOptions, PollCallbacks<VerificationStatusResponse> {\n /**\n * Whether REVIEW ends the wait. Defaults to true.\n *\n * REVIEW means the automated pipeline has finished and handed the\n * verification to a person, which can take hours. Polling through it almost\n * always ends in POLL_TIMEOUT; subscribe to the VERIFICATION_APPROVED /\n * VERIFICATION_REJECTED webhooks for the human's decision instead.\n */\n stopOnReview?: boolean;\n}\n\n/**\n * The document steps every supported document needs.\n *\n * Both sides, for all three catalog pairs. That is not a simplification: the\n * gateway only queues OCR once both `documentFrontPath` and `documentBackPath`\n * exist, and the Angolan driving licence — the one single-card document —\n * reads its address off the back. Collecting only the front leaves the\n * verification sitting in PENDING with nothing running.\n */\nconst DOCUMENT_STEPS: VerificationStep[] = ['document_front', 'document_back'];\n\n/** Which media resource proves a step was uploaded. */\nconst STEP_MEDIA: Record<VerificationStep, MediaResource> = {\n document_front: 'document-front',\n document_back: 'document-back',\n selfie: 'selfie',\n};\n\n/**\n * The end-user verification flow, plus the review and operations endpoints\n * that sit behind the project API key.\n *\n * Everything up to and including `getStatus` works with either credential; the\n * list, summary, history and decision calls are API-key only and say so.\n */\nexport class VerificationsResource {\n constructor(\n private readonly http: HttpClient,\n private readonly session: SessionStore\n ) {}\n\n // -------------------------------------------------------------------------\n // Credentials\n // -------------------------------------------------------------------------\n\n /**\n * Mints a verification token for one end user.\n *\n * Call this on **your server**, with the project API key, and hand the token\n * to the client app. The token authorizes exactly the flow below (start,\n * upload, status) for the given `externalId` and nothing else, which is what\n * keeps the project-wide API key out of a bundle an end user can read.\n *\n * The gateway owns the lifetime (VERIFICATION_TOKEN_TTL, 8h by default) — a\n * client cannot ask for a longer one.\n *\n * @param externalId Your own reference for the end user\n */\n async createToken(\n externalId: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<VerificationToken> {\n const result = await this.http.request<VerificationToken>({\n method: 'POST',\n path: '/verification/token',\n body: { externalId },\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n // -------------------------------------------------------------------------\n // The end-user flow\n // -------------------------------------------------------------------------\n\n /**\n * Starts a verification and, when a storage adapter is configured, records\n * it so an interrupted flow can be resumed.\n *\n * The (country, documentType) pair and the level name are checked here before\n * the request goes out: the gateway rejects an unsupported pair with a 422\n * that names neither what is supported nor why, and a missing level with a\n * validation error that reads like a typo in your code rather than a policy\n * you have not created yet.\n */\n async start(\n params: StartVerificationParams,\n options: { signal?: AbortSignal } = {}\n ): Promise<VerificationSession> {\n if (typeof params.levelName !== 'string' || !params.levelName.trim()) {\n throw new KycirisError(\n 'levelName is required: a verification runs under a verification level, which says which documents are accepted and whether a selfie is needed. Create one from your backend with client.levels.create().',\n { code: 'VALIDATION_ERROR', details: { levelName: params.levelName ?? null } }\n );\n }\n\n if (!isSupportedDocumentPair(params.country, params.documentType)) {\n const forCountry = supportedDocumentTypes(params.country);\n throw new KycirisError(\n forCountry.length\n ? `${params.country} supports ${forCountry.join(', ')}, not ${params.documentType}.`\n : `No documents are supported for country \"${params.country}\".`,\n { code: 'VALIDATION_ERROR', details: { country: params.country, documentType: params.documentType } }\n );\n }\n\n const result = await this.http.request<VerificationSession>({\n method: 'POST',\n path: '/verification/start',\n body: params,\n signal: options.signal,\n });\n\n const started = result.data;\n if (started?.verificationId) {\n await this.session.save({\n verificationId: started.verificationId,\n identityId: started.identityId,\n externalId: params.externalId,\n documentType: params.documentType,\n country: params.country,\n levelName: params.levelName,\n startedAt: new Date().toISOString(),\n });\n }\n\n return started;\n }\n\n /** Uploads the end user's selfie. Triggers face matching once OCR has run. */\n async uploadSelfie(\n verificationId: string,\n file: FileInput,\n options: UploadOptions = {}\n ): Promise<UploadResult> {\n const result = await this.http.request<UploadResult>({\n method: 'POST',\n path: '/verification/upload/selfie',\n form: { verificationId, file },\n fileFields: ['file'],\n signal: options.signal,\n timeoutMs: options.timeoutMs,\n });\n return result.data;\n }\n\n /**\n * Uploads one side of the identity document.\n *\n * OCR is queued once both sides are present, so a flow that collects only\n * the front never starts processing.\n */\n async uploadDocument(\n verificationId: string,\n side: DocumentSide,\n file: FileInput,\n options: UploadOptions = {}\n ): Promise<UploadResult> {\n const result = await this.http.request<UploadResult>({\n method: 'POST',\n path: '/verification/upload/document',\n form: { verificationId, type: side, file },\n fileFields: ['file'],\n signal: options.signal,\n timeoutMs: options.timeoutMs,\n });\n return result.data;\n }\n\n /** Current status, face-match score and extracted document data. */\n async getStatus(\n verificationId: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<VerificationStatusResponse> {\n const result = await this.http.request<VerificationStatusResponse>({\n path: `/verification/status/${encodeURIComponent(verificationId)}`,\n signal: options.signal,\n });\n return result.data;\n }\n\n /**\n * Which files exist for a verification.\n *\n * This is the credential-safe way to tell what an end user has already\n * uploaded: it works with a verification token, whereas the identity record\n * that used to serve the same purpose is API-key only.\n */\n async listMedia(\n verificationId: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<MediaResource[]> {\n const result = await this.http.request<AvailableMedia>({\n path: `/verification/${encodeURIComponent(verificationId)}/media`,\n signal: options.signal,\n });\n return result.data?.available ?? [];\n }\n\n /**\n * Re-runs OCR and face matching from the files already uploaded.\n *\n * The remedy for a verification that failed technically (outcome\n * FAILED_TECHNICAL) or stalled. Clears the previous extraction and decision,\n * so it is not a read-only operation.\n *\n * Only the document front is required, which is why this also works for a\n * verification that never got as far as the selfie.\n */\n async reanalyze(\n verificationId: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<UploadResult> {\n const result = await this.http.request<UploadResult>({\n method: 'POST',\n path: `/verification/reanalyze/${encodeURIComponent(verificationId)}`,\n signal: options.signal,\n });\n return result.data;\n }\n\n // -------------------------------------------------------------------------\n // Resumable flow helpers\n // -------------------------------------------------------------------------\n\n /** The stored session, or null when there is none. */\n async getSession(): Promise<StoredSession | null> {\n return this.session.read();\n }\n\n /**\n * Forgets the stored session. Call it once a verification is finished, so\n * the next one starts clean.\n */\n async clearSession(): Promise<void> {\n return this.session.clear();\n }\n\n /**\n * What the end user has uploaded and what is still missing.\n *\n * Derived from the files that actually exist server-side rather than from\n * anything the client remembers, so it is correct after a reinstall, on a\n * second device, or when a previous attempt failed mid-upload.\n */\n async getProgress(\n verificationId?: string,\n options: ProgressOptions = {}\n ): Promise<VerificationProgress> {\n const id = await this.resolveVerificationId(verificationId);\n\n const [status, available] = await Promise.all([\n this.getStatus(id, { signal: options.signal }),\n this.listMedia(id, { signal: options.signal }),\n ]);\n\n const present = new Set(available);\n const required: VerificationStep[] = [\n ...DOCUMENT_STEPS,\n ...(options.selfieRequired === false ? [] : (['selfie'] as VerificationStep[])),\n ];\n\n const uploaded = {\n document_front: present.has('document-front'),\n document_back: present.has('document-back'),\n selfie: present.has('selfie'),\n } satisfies Record<VerificationStep, boolean>;\n\n const missingSteps = required.filter((step) => !present.has(STEP_MEDIA[step]));\n\n return {\n verificationId: id,\n status: status.status,\n outcome: status.outcome,\n uploaded,\n missingSteps,\n isComplete: missingSteps.length === 0,\n };\n }\n\n /**\n * Uploads one step, skipping it when the file is already there.\n *\n * The call a resumable UI should make: it never re-sends a step the end user\n * already completed, which matters most on a retry after a dropped\n * connection, where the upload may well have succeeded.\n */\n async uploadStep(params: UploadStepParams): Promise<UploadStepResult> {\n const verificationId = await this.resolveVerificationId(params.verificationId);\n\n // Checked before the progress read, so an unusable image costs no requests\n // at all. The result is passed on rather than the original, so the bytes\n // are decoded and sniffed once instead of twice.\n const prepared = await prepareFile(params.file, `${params.step}.jpg`);\n\n const progress = await this.getProgress(verificationId, {\n selfieRequired: params.selfieRequired,\n signal: params.signal,\n });\n\n if (progress.uploaded[params.step]) {\n return {\n message: `${params.step} was already uploaded`,\n status: progress.status,\n skipped: true,\n };\n }\n\n const uploadOptions: UploadOptions = {\n signal: params.signal,\n timeoutMs: params.timeoutMs,\n };\n\n const result =\n params.step === 'selfie'\n ? await this.uploadSelfie(verificationId, prepared, uploadOptions)\n : await this.uploadDocument(\n verificationId,\n params.step === 'document_front' ? 'front' : 'back',\n prepared,\n uploadOptions\n );\n\n return { ...result, skipped: false };\n }\n\n /**\n * Polls the status until the verification is decided.\n *\n * Stops at APPROVED, REJECTED and — unless `stopOnReview` is false — REVIEW.\n * For anything longer than a user is willing to watch a spinner, use the\n * webhooks: polling burns a request every few seconds and still gives up\n * after `timeoutMs`.\n */\n async waitForResult(\n verificationId?: string,\n options: WaitForResultOptions = {}\n ): Promise<VerificationStatusResponse> {\n const id = await this.resolveVerificationId(verificationId);\n const stopOnReview = options.stopOnReview ?? true;\n\n return pollUntil<VerificationStatusResponse>(\n (signal) => this.getStatus(id, { signal }),\n (status) =>\n isTerminalStatus(status.status) ||\n (stopOnReview && status.status === 'REVIEW'),\n options,\n `verification ${id}`\n );\n }\n\n private async resolveVerificationId(explicit?: string): Promise<string> {\n if (explicit) return explicit;\n const stored = await this.session.read();\n if (stored?.verificationId) return stored.verificationId;\n throw new KycirisError(\n this.session.enabled\n ? 'No verificationId was given and there is no stored session to resume. Start a verification first.'\n : 'No verificationId was given. Pass one, or configure `storage` so the SDK can remember the verification it started.',\n { code: 'SESSION_NOT_FOUND' }\n );\n }\n\n // -------------------------------------------------------------------------\n // Review and operations (project API key)\n // -------------------------------------------------------------------------\n\n /**\n * A page of the project's verifications, newest first.\n *\n * Carries no OCR data or storage paths by design — a 20-row page is not the\n * place for identity-document PII. Read one verification for those.\n */\n async list(\n params: ListVerificationsParams = {},\n options: { signal?: AbortSignal } = {}\n ): Promise<Page<VerificationListItem>> {\n const result = await this.http.request<VerificationListItem[]>({\n path: '/verification',\n query: { ...params },\n auth: 'api-key',\n signal: options.signal,\n });\n return toPage(result);\n }\n\n /** Counts per status and outcome, plus what needs an operator's attention. */\n async summary(options: { signal?: AbortSignal } = {}): Promise<VerificationSummary> {\n const result = await this.http.request<VerificationSummary>({\n path: '/verification/summary',\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /**\n * A verification's recorded history, oldest first.\n *\n * The verification row keeps only the last decision, so this is the only\n * place the sequence survives.\n */\n async events(\n verificationId: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<PipelineEvent[]> {\n const result = await this.http.request<PipelineEvent[]>({\n path: `/verification/events/${encodeURIComponent(verificationId)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data ?? [];\n }\n\n /** Moves a PENDING verification to REVIEW so a person can look at it. */\n async sendToReview(\n verificationId: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<{ verificationId: string; status: string; message?: string }> {\n const result = await this.http.request<{\n verificationId: string;\n status: string;\n message?: string;\n }>({\n method: 'PATCH',\n path: `/verification/review/${encodeURIComponent(verificationId)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /**\n * Records a reviewer's decision and fires the matching webhook.\n *\n * Repeating the decision a verification already has is refused with 409 —\n * that is the gateway making a second webhook impossible, not a transient\n * failure. Changing a decision (rejected in error, then approved) is allowed.\n */\n async decide(\n verificationId: string,\n decision: ReviewDecision,\n options: { signal?: AbortSignal } = {}\n ): Promise<{ verificationId: string; status: string }> {\n const result = await this.http.request<{ verificationId: string; status: string }>({\n method: 'PATCH',\n path: `/verification/decision/${encodeURIComponent(verificationId)}`,\n body: decision,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n}\n","import type { HttpClient } from '../http/client';\nimport { toPage, type Page } from '../http/envelope';\nimport type {\n CreateWebhookParams,\n UpdateWebhookParams,\n Webhook,\n WebhookLogEntry,\n WebhookResendResult,\n} from '../types';\n\n/**\n * Where the gateway sends verification events.\n *\n * Webhooks are the right way to learn a verification's outcome: polling costs\n * a request every few seconds and still gives up, while a REVIEW can sit with\n * a human for hours. Subscribe with `[\"*\"]` when the intent is \"mirror my\n * verification lifecycle\" — a literal list of today's events silently stops\n * being complete the day an eighth one exists.\n *\n * The URL must be https with a public hostname; the gateway refuses anything\n * else, localhost included.\n */\nexport class WebhooksResource {\n constructor(private readonly http: HttpClient) {}\n\n async create(\n params: CreateWebhookParams,\n options: { signal?: AbortSignal } = {}\n ): Promise<Webhook> {\n const result = await this.http.request<Webhook>({\n method: 'POST',\n path: '/webhooks',\n body: params,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n async list(options: { signal?: AbortSignal } = {}): Promise<Webhook[]> {\n const result = await this.http.request<Webhook[]>({\n path: '/webhooks',\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data ?? [];\n }\n\n async get(id: string, options: { signal?: AbortSignal } = {}): Promise<Webhook> {\n const result = await this.http.request<Webhook>({\n path: `/webhooks/${encodeURIComponent(id)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n async update(\n id: string,\n params: UpdateWebhookParams,\n options: { signal?: AbortSignal } = {}\n ): Promise<Webhook> {\n const result = await this.http.request<Webhook>({\n method: 'PUT',\n path: `/webhooks/${encodeURIComponent(id)}`,\n body: params,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n async delete(id: string, options: { signal?: AbortSignal } = {}): Promise<void> {\n await this.http.request<void>({\n method: 'DELETE',\n path: `/webhooks/${encodeURIComponent(id)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n }\n\n /**\n * Delivery attempts, newest first — what was sent, what came back, how many\n * retries it took. The place to look when an endpoint stops receiving events.\n */\n async logs(\n params: { page?: number; limit?: number } = {},\n options: { signal?: AbortSignal } = {}\n ): Promise<Page<WebhookLogEntry>> {\n const result = await this.http.request<WebhookLogEntry[]>({\n path: '/webhook-log',\n query: { ...params },\n auth: 'api-key',\n signal: options.signal,\n });\n return toPage(result);\n }\n\n /** One delivery attempt. */\n async log(\n id: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<WebhookLogEntry> {\n const result = await this.http.request<WebhookLogEntry>({\n path: `/webhook-log/${encodeURIComponent(id)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /**\n * Sends a recorded delivery again, to the endpoint it originally went to.\n *\n * Synchronous: the result says whether it arrived this time. A failure comes\n * back as `{ success: false, error }` rather than throwing, because the\n * gateway has already written a FAILED row either way and the caller usually\n * wants to show the reason beside the delivery it belongs to. A missing\n * delivery (404) or a deleted endpoint (409) still throw -- those are not\n * outcomes of the send.\n *\n * Not retried: a resend that timed out may well have arrived.\n */\n async resendLog(\n id: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<WebhookResendResult> {\n const result = await this.http.request<WebhookResendResult>({\n method: 'POST',\n path: `/webhook-log/${encodeURIComponent(id)}/resend`,\n auth: 'api-key',\n retry: false,\n signal: options.signal,\n });\n return result.data;\n }\n}\n","import type { DocumentType, CatalogCountry } from './types';\n\n/**\n * Pluggable key/value storage, so a verification that was interrupted can be\n * picked up again after the app is closed.\n *\n * Inject AsyncStorage on React Native, or an adapter around localStorage on\n * web. Methods may be synchronous or asynchronous; results are awaited either\n * way.\n */\nexport interface KycirisStorage {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<void>;\n removeItem(key: string): void | Promise<void>;\n}\n\n/** Versioned, so a future change of shape cannot read an old record wrongly. */\nexport const SESSION_STORAGE_KEY = 'kyciris:session:v1';\n\n/**\n * What the SDK remembers about an in-flight verification.\n *\n * Deliberately holds no credential. The verification token is a bearer\n * credential for one end user and persisting it would leave it in\n * AsyncStorage/localStorage long after the flow ended, readable by anything\n * else in the app; the host application decides where — and whether — to keep\n * it. Only identifiers live here, and all of them are already known to the\n * client that fetched them.\n */\nexport interface StoredSession {\n verificationId: string;\n identityId?: string;\n externalId?: string;\n documentType?: DocumentType | (string & {});\n country?: CatalogCountry | (string & {});\n levelName?: string;\n /** ISO 8601 instant the verification was started. */\n startedAt: string;\n}\n\nfunction isStoredSession(value: unknown): value is StoredSession {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as StoredSession).verificationId === 'string'\n );\n}\n\n/**\n * Reads and writes the resumable session.\n *\n * Every operation is best-effort: storage can be full, disabled (Safari private\n * browsing), or simply absent. Losing the ability to resume is a degraded flow;\n * throwing here would break a verification that is otherwise proceeding fine.\n */\nexport class SessionStore {\n constructor(private readonly storage?: KycirisStorage) {}\n\n /** True when a storage adapter was configured. */\n get enabled(): boolean {\n return Boolean(this.storage);\n }\n\n async save(session: StoredSession): Promise<void> {\n if (!this.storage) return;\n try {\n await this.storage.setItem(SESSION_STORAGE_KEY, JSON.stringify(session));\n } catch {\n // Best-effort; see the class comment.\n }\n }\n\n async read(): Promise<StoredSession | null> {\n if (!this.storage) return null;\n try {\n const raw = await this.storage.getItem(SESSION_STORAGE_KEY);\n if (!raw) return null;\n const parsed: unknown = JSON.parse(raw);\n // A record written by an older version, or corrupted, is discarded\n // rather than handed back half-formed.\n return isStoredSession(parsed) ? parsed : null;\n } catch {\n return null;\n }\n }\n\n async clear(): Promise<void> {\n if (!this.storage) return;\n try {\n await this.storage.removeItem(SESSION_STORAGE_KEY);\n } catch {\n // Best-effort; see the class comment.\n }\n }\n}\n\n/**\n * A storage adapter backed by a plain Map.\n *\n * For tests, and for a flow that should not outlive the process.\n */\nexport function createMemoryStorage(): KycirisStorage {\n const map = new Map<string, string>();\n return {\n getItem: (key) => map.get(key) ?? null,\n setItem: (key, value) => {\n map.set(key, value);\n },\n removeItem: (key) => {\n map.delete(key);\n },\n };\n}\n","import { HttpClient, type HttpClientConfig } from './http/client';\nimport { AnalyticsResource } from './resources/analytics';\nimport { IdentitiesResource } from './resources/identities';\nimport { LevelsResource } from './resources/levels';\nimport { MediaResourceApi } from './resources/media';\nimport { OcrResource } from './resources/ocr';\nimport { VerificationsResource } from './resources/verifications';\nimport { WebhooksResource } from './resources/webhooks';\nimport { SessionStore, type KycirisStorage } from './storage';\n\nexport interface KycirisClientConfig extends HttpClientConfig {\n /**\n * Where to remember an in-flight verification, so a flow interrupted by the\n * app closing can be resumed. AsyncStorage on React Native, an adapter around\n * localStorage on web. No credential is ever written to it.\n */\n storage?: KycirisStorage;\n}\n\n/**\n * The KYCiris API client.\n *\n * Two credentials, two audiences:\n *\n * - **`apiKey`** is the project's key. It reaches every endpoint, including\n * every identity in the project, and belongs on your server only.\n * - **`verificationToken`** is scoped to one end user and authorizes exactly\n * the verification flow. Mint it on your server with\n * `verifications.createToken(externalId)` and hand it to the client app.\n *\n * Constructing a client with `apiKey` inside a browser or React Native app\n * throws, because a key in a shipped bundle is a key the end user has.\n *\n * ```ts\n * // Your server\n * const server = createKycirisClient({ baseUrl, apiKey: process.env.KYCIRIS_API_KEY });\n * const { token } = await server.verifications.createToken('user-123');\n *\n * // Your app, with that token\n * const client = createKycirisClient({ baseUrl, verificationToken: token, storage });\n * const { verificationId } = await client.verifications.start({\n * country: 'AO',\n * documentType: 'ID_CARD',\n * });\n * ```\n */\nexport class KycirisClient {\n /** The end-user flow, plus review and operations reads. */\n readonly verifications: VerificationsResource;\n /** Identity records and re-authentication face checks. API key only. */\n readonly identities: IdentitiesResource;\n /** Verification levels (step policies). API key only. */\n readonly levels: LevelsResource;\n /** Single-use downloads of verification images. API key only. */\n readonly media: MediaResourceApi;\n /** Standalone document reading, outside the verification flow. */\n readonly ocr: OcrResource;\n /** Event subscriptions and their delivery log. API key only. */\n readonly webhooks: WebhooksResource;\n /** Monthly counts. API key only. */\n readonly analytics: AnalyticsResource;\n\n private readonly http: HttpClient;\n\n constructor(config: KycirisClientConfig) {\n this.http = new HttpClient(config);\n const session = new SessionStore(config.storage);\n\n this.verifications = new VerificationsResource(this.http, session);\n this.identities = new IdentitiesResource(this.http);\n this.levels = new LevelsResource(this.http);\n this.media = new MediaResourceApi(this.http);\n this.ocr = new OcrResource(this.http);\n this.webhooks = new WebhooksResource(this.http);\n this.analytics = new AnalyticsResource(this.http);\n }\n\n /**\n * Whether this client holds the project API key, and so can reach the\n * server-side endpoints.\n *\n * Worth checking in code that runs in both places, rather than letting a\n * MISSING_CREDENTIAL error be the way you find out.\n */\n get isServerSide(): boolean {\n return this.http.hasApiKey();\n }\n}\n\n/** Creates a KYCiris client. See {@link KycirisClient}. */\nexport function createKycirisClient(config: KycirisClientConfig): KycirisClient {\n return new KycirisClient(config);\n}\n","import type { KycirisClient } from './client';\nimport { KycirisError, isKycirisError } from './errors';\nimport type { FileInput } from './files';\nimport type {\n CatalogCountry,\n DocumentType,\n VerificationOutcome,\n VerificationStatus,\n VerificationStep,\n} from './types';\n\n/** Where the end user is in the flow. */\nexport type FlowPhase =\n /** Nothing started yet. */\n | 'idle'\n /** Creating the verification. */\n | 'starting'\n /** Waiting for the user to supply the current step's image. */\n | 'collecting'\n /** Uploading an image. */\n | 'uploading'\n /** Everything submitted; the pipeline is deciding. */\n | 'processing'\n /** A decision was reached, or a human was asked for one. */\n | 'finished'\n /** The flow stopped on an error. `error` says which. */\n | 'failed';\n\nexport interface FlowState {\n phase: FlowPhase;\n verificationId: string | null;\n /** The step to ask the user for now, or null when none is outstanding. */\n currentStep: VerificationStep | null;\n /** Every step still to collect, in order. */\n missingSteps: VerificationStep[];\n uploaded: Record<VerificationStep, boolean>;\n status: VerificationStatus | null;\n outcome: VerificationOutcome | null;\n /** Why the pipeline stopped, when it did. */\n rejectionReason: string | null;\n error: KycirisError | null;\n /** True while a request is in flight, for disabling a capture button. */\n busy: boolean;\n}\n\nexport interface FlowOptions {\n country: CatalogCountry | (string & {});\n documentType: DocumentType | (string & {});\n /** Verification level to run under. Required: the gateway has no default. */\n levelName: string;\n /** Your reference for the user. Ignored when a verification token is used. */\n externalId?: string;\n /**\n * Whether the level asks for a selfie. Defaults to true.\n *\n * A client holding a verification token cannot read its own level, so a\n * document-only level has to be declared here.\n */\n selfieRequired?: boolean;\n /** Poll for the decision once everything is uploaded. Defaults to true. */\n waitForDecision?: boolean;\n /** How long to poll before giving up, in ms. Defaults to 120000. */\n decisionTimeoutMs?: number;\n /** Called on every state change. */\n onStateChange?: (state: FlowState) => void;\n}\n\nconst EMPTY_UPLOADED: Record<VerificationStep, boolean> = {\n document_front: false,\n document_back: false,\n selfie: false,\n};\n\n/**\n * The end-user verification flow as a state machine, with no UI attached.\n *\n * The React Native and web components are both thin wrappers around this, so\n * the sequencing — which step comes next, what a resumed flow skips, when the\n * decision is polled for — is written and tested once.\n *\n * Every transition is observable through `subscribe`, and every method is safe\n * to call from a button handler: failures land in `state.error` rather than\n * rejecting, so a component never has to wrap calls in try/catch.\n *\n * ```ts\n * const flow = new VerificationFlow(client, { country: 'AO', documentType: 'ID_CARD' });\n * flow.subscribe(render);\n * await flow.start();\n * // then, per captured image:\n * await flow.submit(image);\n * ```\n */\nexport class VerificationFlow {\n private state: FlowState = {\n phase: 'idle',\n verificationId: null,\n currentStep: null,\n missingSteps: [],\n uploaded: { ...EMPTY_UPLOADED },\n status: null,\n outcome: null,\n rejectionReason: null,\n error: null,\n busy: false,\n };\n\n private listeners = new Set<(state: FlowState) => void>();\n private aborter: AbortController | null = null;\n\n constructor(\n private readonly client: KycirisClient,\n private readonly options: FlowOptions\n ) {\n if (options.onStateChange) this.listeners.add(options.onStateChange);\n }\n\n getState(): FlowState {\n return this.state;\n }\n\n /** Observes state changes. Returns an unsubscribe function. */\n subscribe(listener: (state: FlowState) => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /**\n * Starts a verification, or picks up the one already in storage.\n *\n * Resuming is the default because it is almost always what the user wants:\n * an app killed between the document and the selfie should carry on, not\n * ask for the document again. Pass `{ fresh: true }` to start over.\n */\n async start(options: { fresh?: boolean } = {}): Promise<FlowState> {\n return this.guard('starting', async (signal) => {\n if (options.fresh) {\n await this.client.verifications.clearSession();\n } else {\n const existing = await this.client.verifications.getSession();\n if (existing?.verificationId) {\n return this.loadProgress(existing.verificationId, signal);\n }\n }\n\n const session = await this.client.verifications.start(\n {\n country: this.options.country,\n documentType: this.options.documentType,\n levelName: this.options.levelName,\n externalId: this.options.externalId,\n },\n { signal }\n );\n\n return this.loadProgress(session.verificationId, signal);\n });\n }\n\n /**\n * Re-reads what the gateway holds.\n *\n * Worth calling when a component remounts, or after an upload whose response\n * never arrived: the file may well have landed, and this is what notices.\n */\n async refresh(): Promise<FlowState> {\n const verificationId = this.state.verificationId;\n if (!verificationId) return this.start();\n return this.guard(this.state.phase, (signal) =>\n this.loadProgress(verificationId, signal)\n );\n }\n\n /**\n * Uploads an image for the current step and advances.\n *\n * A step that turns out to be already uploaded is skipped rather than sent\n * again, so retrying after a dropped connection cannot duplicate work.\n */\n async submit(file: FileInput): Promise<FlowState> {\n const { verificationId, currentStep } = this.state;\n if (!verificationId) {\n return this.fail(\n new KycirisError('The flow has not been started yet.', {\n code: 'SESSION_NOT_FOUND',\n })\n );\n }\n if (!currentStep) {\n return this.fail(\n new KycirisError('There is no step waiting for an image.', {\n code: 'VALIDATION_ERROR',\n })\n );\n }\n\n return this.guard('uploading', async (signal) => {\n await this.client.verifications.uploadStep({\n step: currentStep,\n file,\n verificationId,\n selfieRequired: this.options.selfieRequired,\n signal,\n });\n return this.loadProgress(verificationId, signal);\n });\n }\n\n /**\n * Waits for the pipeline's decision.\n *\n * Called automatically once the last step is uploaded, unless\n * `waitForDecision` is false. Stops at REVIEW, which is a person's queue and\n * not something worth holding a spinner for.\n */\n async waitForDecision(): Promise<FlowState> {\n const verificationId = this.state.verificationId;\n if (!verificationId) {\n return this.fail(\n new KycirisError('The flow has not been started yet.', {\n code: 'SESSION_NOT_FOUND',\n })\n );\n }\n\n return this.guard('processing', async (signal) => {\n const status = await this.client.verifications.waitForResult(verificationId, {\n signal,\n timeoutMs: this.options.decisionTimeoutMs,\n });\n return {\n phase: 'finished' as FlowPhase,\n status: status.status,\n outcome: status.outcome,\n rejectionReason: status.rejectionReason,\n };\n });\n }\n\n /**\n * Cancels whatever is in flight.\n *\n * A component's unmount should call this, so a poll does not keep running\n * against a screen that is gone.\n */\n cancel(): void {\n this.aborter?.abort();\n this.aborter = null;\n if (this.state.busy) this.patch({ busy: false });\n }\n\n /** Cancels, forgets the stored session, and returns to `idle`. */\n async reset(): Promise<FlowState> {\n this.cancel();\n await this.client.verifications.clearSession();\n this.patch({\n phase: 'idle',\n verificationId: null,\n currentStep: null,\n missingSteps: [],\n uploaded: { ...EMPTY_UPLOADED },\n status: null,\n outcome: null,\n rejectionReason: null,\n error: null,\n busy: false,\n });\n return this.state;\n }\n\n // -------------------------------------------------------------------------\n\n /**\n * Reads progress and derives the next phase from it.\n *\n * Returns a patch rather than applying one, so `guard` stays the single\n * place that publishes a state change.\n */\n private async loadProgress(\n verificationId: string,\n signal?: AbortSignal\n ): Promise<Partial<FlowState>> {\n const progress = await this.client.verifications.getProgress(verificationId, {\n selfieRequired: this.options.selfieRequired,\n signal,\n });\n\n return {\n verificationId,\n currentStep: progress.missingSteps[0] ?? null,\n missingSteps: progress.missingSteps,\n uploaded: progress.uploaded,\n status: progress.status,\n outcome: progress.outcome,\n phase: progress.isComplete ? 'processing' : 'collecting',\n };\n }\n\n /**\n * Runs one transition: marks the flow busy, applies the resulting patch, and\n * turns any failure into `state.error` instead of a rejected promise.\n *\n * The awkward part it exists to contain is that reaching `processing` should\n * flow straight on into polling — but only when the caller asked for it, and\n * only once.\n */\n private async guard(\n phase: FlowPhase,\n run: (signal?: AbortSignal) => Promise<Partial<FlowState>>\n ): Promise<FlowState> {\n this.aborter?.abort();\n const aborter = new AbortController();\n this.aborter = aborter;\n\n this.patch({ phase, busy: true, error: null });\n\n try {\n const patch = await run(aborter.signal);\n this.patch({ ...patch, busy: false });\n\n const shouldWait =\n this.state.phase === 'processing' &&\n (this.options.waitForDecision ?? true) &&\n // Not a nested call: waitForDecision itself lands here with phase\n // 'processing' already set, and would otherwise recurse forever.\n phase !== 'processing';\n\n if (shouldWait) return this.waitForDecision();\n\n return this.state;\n } catch (error) {\n if (isKycirisError(error) && error.code === 'ABORTED') {\n this.patch({ busy: false });\n return this.state;\n }\n return this.fail(error);\n } finally {\n if (this.aborter === aborter) this.aborter = null;\n }\n }\n\n private fail(error: unknown): FlowState {\n const failure = isKycirisError(error)\n ? error\n : new KycirisError(\n error instanceof Error ? error.message : 'The verification failed.',\n { code: 'INTERNAL_SERVER_ERROR', cause: error }\n );\n this.patch({ phase: 'failed', busy: false, error: failure });\n return this.state;\n }\n\n private patch(patch: Partial<FlowState>): void {\n this.state = { ...this.state, ...patch };\n for (const listener of this.listeners) listener(this.state);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/files.ts","../src/http/envelope.ts","../src/http/client.ts","../src/resources/analytics.ts","../src/poll.ts","../src/resources/identities.ts","../src/resources/levels.ts","../src/resources/media.ts","../src/types.ts","../src/resources/ocr.ts","../src/resources/verifications.ts","../src/resources/webhooks.ts","../src/storage.ts","../src/client.ts","../src/flow.ts"],"names":["bytes","mimeType","delay","DEFAULT_TIMEOUT_MS"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Every error the SDK throws is a KycirisError, so a caller can branch on\n * `code` instead of parsing messages.\n *\n * Codes come from two places. Gateway codes are the `error.code` value in the\n * API's error envelope (`{ error: { code, message, details }, meta }`) and are\n * kept in step with the gateway's own ERROR_CODE enum. SDK codes are raised\n * client-side, before or instead of a request.\n */\n\n/**\n * Error codes produced by the gateway itself.\n *\n * Mirrors `ERROR_CODE` in kyc-gateway (src/common/enums/error-codes.ts). Codes\n * the SDK does not recognise are still surfaced verbatim on `KycirisError.code`\n * — the list is for autocomplete and exhaustiveness, not for filtering.\n */\nexport const GATEWAY_ERROR_CODES = [\n // OCR processing\n 'INVALID_OCR_DATA',\n 'OCR_EXTRACTION_ERROR',\n // Document validation\n 'DOCUMENT_EXPIRED',\n 'INVALID_DOCUMENT_QUALITY',\n // Face matching\n 'FACE_MISMATCH',\n 'LOW_FACE_MATCH_SCORE',\n 'NO_FACE',\n // Manual review\n 'MANUAL_REJECTION',\n // Worker terminal failures\n 'BAD_PAYLOAD',\n 'UNSUPPORTED_DOCUMENT',\n 'BAD_IMAGE',\n // Account status\n 'ACCOUNT_SUSPENDED',\n // Generic HTTP labels\n 'VALIDATION_ERROR',\n 'UNAUTHORIZED',\n 'FORBIDDEN',\n 'NOT_FOUND',\n 'RESOURCE_ALREADY_EXISTS',\n 'RATE_LIMIT_EXCEEDED',\n 'INTERNAL_SERVER_ERROR',\n] as const;\n\nexport type GatewayErrorCode = (typeof GATEWAY_ERROR_CODES)[number];\n\n/** Error codes raised by the SDK without (or before) a gateway response. */\nexport const SDK_ERROR_CODES = [\n /** The client was constructed with an unusable configuration. */\n 'CONFIG_ERROR',\n /** A project API key was about to be sent from a browser or React Native app. */\n 'CREDENTIAL_MISUSE',\n /** The endpoint needs a credential the client was not given. */\n 'MISSING_CREDENTIAL',\n /** The request never reached the gateway (DNS, TLS, offline, CORS). */\n 'NETWORK_ERROR',\n /** The request exceeded `timeoutMs`. */\n 'TIMEOUT',\n /** An AbortSignal supplied by the caller fired. */\n 'ABORTED',\n /** A 2xx response whose body was not the documented envelope. */\n 'INVALID_RESPONSE',\n /** A file argument could not be turned into an upload on this platform. */\n 'INVALID_FILE',\n /** Polling ran past its own timeout without reaching a final state. */\n 'POLL_TIMEOUT',\n /** No verification session was found in storage to resume from. */\n 'SESSION_NOT_FOUND',\n] as const;\n\nexport type SdkErrorCode = (typeof SDK_ERROR_CODES)[number];\n\n/** Any code that can land on a KycirisError. Open-ended by design. */\nexport type KycirisErrorCode = GatewayErrorCode | SdkErrorCode | (string & {});\n\nexport interface KycirisErrorInit {\n code: KycirisErrorCode;\n /** HTTP status, when the error came from a response. */\n status?: number;\n /** `meta.requestId` from the response envelope — quote it in bug reports. */\n requestId?: string;\n /** `error.details` from the envelope, e.g. per-field validation failures. */\n details?: unknown;\n /** Whether retrying the same request could plausibly succeed. */\n retryable?: boolean;\n /** The underlying error, when this one wraps a lower-level failure. */\n cause?: unknown;\n}\n\n/**\n * The single error type the SDK throws.\n *\n * It deliberately carries no request/response objects: those hold the\n * Authorization and X-API-Key headers, and an error is the thing most likely to\n * be logged verbatim or shipped to an error tracker.\n */\nexport class KycirisError extends Error {\n readonly name = 'KycirisError';\n readonly code: KycirisErrorCode;\n readonly status?: number;\n readonly requestId?: string;\n readonly details?: unknown;\n readonly retryable: boolean;\n\n constructor(message: string, init: KycirisErrorInit) {\n super(message);\n // Assigned rather than passed to `super`: the `cause` option is ES2022,\n // and the package is compiled for ES2020 so it still loads on older\n // runtimes. The property behaves identically either way.\n if (init.cause !== undefined) {\n (this as { cause?: unknown }).cause = init.cause;\n }\n this.code = init.code;\n this.status = init.status;\n this.requestId = init.requestId;\n this.details = init.details;\n this.retryable = init.retryable ?? false;\n\n // Restores the prototype chain when the package is consumed as compiled\n // ES5/CommonJS, where extending a builtin otherwise breaks `instanceof`.\n Object.setPrototypeOf(this, KycirisError.prototype);\n }\n\n /** True when this is a KycirisError, across bundle/realm boundaries. */\n static isKycirisError(value: unknown): value is KycirisError {\n return (\n value instanceof KycirisError ||\n (typeof value === 'object' &&\n value !== null &&\n (value as { name?: unknown }).name === 'KycirisError' &&\n typeof (value as { code?: unknown }).code === 'string')\n );\n }\n}\n\n/** Convenience guard, equivalent to `KycirisError.isKycirisError`. */\nexport function isKycirisError(value: unknown): value is KycirisError {\n return KycirisError.isKycirisError(value);\n}\n\n/**\n * HTTP statuses worth retrying: the request either never ran (429) or failed\n * for a reason that is plausibly momentary.\n */\nexport function isRetryableStatus(status: number): boolean {\n return status === 408 || status === 429 || (status >= 500 && status <= 599);\n}\n","import { KycirisError } from './errors';\n\n/**\n * The largest upload the gateway accepts (MAX_IMAGE_FILE_SIZE). Checked here\n * too, when the SDK can see the bytes, so an 8MB upload fails instantly\n * instead of after the whole body has gone over the wire.\n */\nexport const MAX_IMAGE_FILE_SIZE = 8 * 1024 * 1024;\n\n/** The only image types the gateway accepts, decided by magic bytes. */\nexport type ImageMimeType = 'image/jpeg' | 'image/png';\n\n/**\n * An image to upload, in whichever form the host platform produces.\n *\n * - `Blob` / `File` — browsers, and Node 18+ (`new Blob([bytes])`).\n * - `{ uri }` — React Native: a `file://`, `content://`, `ph://` or `data:` URI\n * from the camera or image picker.\n * - `{ data }` — raw bytes, e.g. `fs.readFileSync()` in Node.\n * - `string` — a `data:` URI, a bare base64 payload, or a React Native file URI.\n */\nexport type FileInput =\n | Blob\n | { uri: string; name?: string; type?: string }\n | { data: ArrayBuffer | ArrayBufferView; name?: string; type?: string }\n | string\n | NormalizedFile;\n\n/** A file ready to be appended to FormData on this platform. */\nexport interface NormalizedFile {\n /** Blob on web/Node, `{ uri, name, type }` on React Native. */\n value: unknown;\n filename: string;\n /** Sniffed from the bytes where possible, otherwise the caller's hint. */\n mimeType: string;\n}\n\n/**\n * Marks an already-normalized file, so `normalizeFile` can be idempotent.\n *\n * That matters because validating early and uploading later are two different\n * moments: `uploadStep` checks the image before spending a request on reading\n * progress, and without this the bytes would be decoded and sniffed a second\n * time on the way out — on a multi-megabyte photo, on a phone.\n *\n * Symbol.for, not a local symbol: two copies of the package in one bundle must\n * still recognise each other's files.\n */\nconst NORMALIZED = Symbol.for('kyciris.normalizedFile');\n\nfunction mark(file: NormalizedFile): NormalizedFile {\n Object.defineProperty(file, NORMALIZED, { value: true, enumerable: false });\n return file;\n}\n\n/** True when `value` has already been through {@link normalizeFile}. */\nexport function isNormalizedFile(value: unknown): value is NormalizedFile {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as Record<symbol, unknown>)[NORMALIZED] === true\n );\n}\n\n/**\n * React Native's FormData takes `{ uri, name, type }` and streams the file\n * itself; it has no filesystem access from JS to turn that URI into a Blob.\n * Everywhere else, Blob is the portable choice.\n */\nexport function isReactNative(): boolean {\n return (\n typeof navigator !== 'undefined' &&\n (navigator as { product?: string }).product === 'ReactNative'\n );\n}\n\nconst JPEG_MAGIC = [0xff, 0xd8, 0xff];\nconst PNG_MAGIC = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];\n\nfunction startsWith(bytes: Uint8Array, magic: number[]): boolean {\n if (bytes.length < magic.length) return false;\n return magic.every((byte, index) => bytes[index] === byte);\n}\n\n/**\n * The real image type, from the first bytes.\n *\n * The gateway sniffs the same way and ignores the declared Content-Type, so a\n * caller who mislabels a PNG as image/jpeg still succeeds — and one who\n * uploads a PDF renamed to .jpg still fails. Doing it here just moves that\n * answer earlier.\n */\nexport function detectImageMimeType(bytes: Uint8Array): ImageMimeType | null {\n if (bytes.length < 8) return null;\n if (startsWith(bytes, JPEG_MAGIC)) return 'image/jpeg';\n if (startsWith(bytes, PNG_MAGIC)) return 'image/png';\n return null;\n}\n\nconst BASE64_ALPHABET = /^[A-Za-z0-9+/]+={0,2}$/;\n\n/** Decodes base64 using whichever primitive the runtime provides. */\nexport function decodeBase64(input: string): Uint8Array {\n const normalized = input.replace(/\\s/g, '');\n\n // Node (and React Native, via its Buffer polyfill) — avoids atob's\n // char-by-char loop on multi-megabyte images.\n // Typed structurally rather than as Node's `BufferConstructor`: this package\n // has no dependencies and must typecheck in a browser or React Native project\n // that has never installed @types/node. Only the one overload used is named.\n const maybeBuffer = (globalThis as { Buffer?: { from(s: string, encoding: string): Uint8Array } })\n .Buffer;\n if (maybeBuffer) {\n const buffer = maybeBuffer.from(normalized, 'base64');\n return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n }\n\n if (typeof atob === 'function') {\n const binary = atob(normalized);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n }\n\n throw new KycirisError(\n 'This runtime has neither Buffer nor atob, so base64 image data cannot be decoded. Pass a Blob or raw bytes instead.',\n { code: 'INVALID_FILE' }\n );\n}\n\nfunction toBytes(data: ArrayBuffer | ArrayBufferView): Uint8Array {\n return data instanceof ArrayBuffer\n ? new Uint8Array(data)\n : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n}\n\n/** True for the URI schemes React Native's FormData can stream by itself. */\nfunction isPlatformUri(value: string): boolean {\n return /^(file|content|ph|assets-library):/i.test(value);\n}\n\nconst DATA_URI_RE = /^data:([^;,]*)(;[^,]*)?,(.*)$/s;\n\n/** Splits a `data:` URI into its declared type and decoded bytes. */\nfunction parseDataUri(value: string): { mimeType: string; bytes: Uint8Array } {\n const match = DATA_URI_RE.exec(value);\n if (!match) {\n throw new KycirisError('Malformed data: URI.', { code: 'INVALID_FILE' });\n }\n const [, declaredType, parameters, payload] = match;\n const isBase64 = (parameters ?? '').toLowerCase().includes('base64');\n\n let bytes: Uint8Array;\n if (isBase64) {\n bytes = decodeBase64(payload);\n } else {\n // decodeURIComponent throws a bare URIError on a malformed escape, which\n // would escape the SDK as something the caller cannot branch on.\n try {\n bytes = new TextEncoder().encode(decodeURIComponent(payload));\n } catch (cause) {\n throw new KycirisError(\n 'Malformed percent-encoding in a data: URI. Image data should be base64-encoded (data:image/jpeg;base64,...) — percent-encoding is UTF-8 and cannot carry arbitrary bytes.',\n { code: 'INVALID_FILE', cause }\n );\n }\n }\n\n return { mimeType: declaredType || 'application/octet-stream', bytes };\n}\n\nfunction assertBlobSize(blob: Blob, filename: string): void {\n if (blob.size === 0) {\n throw new KycirisError(`${filename} is empty.`, { code: 'INVALID_FILE' });\n }\n if (blob.size > MAX_IMAGE_FILE_SIZE) {\n throw new KycirisError(\n `${filename} is ${(blob.size / 1024 / 1024).toFixed(1)}MB; the gateway accepts at most ${MAX_IMAGE_FILE_SIZE / 1024 / 1024}MB. Re-encode at a lower quality before uploading.`,\n { code: 'INVALID_FILE' }\n );\n }\n}\n\nfunction assertUsableImage(bytes: Uint8Array, filename: string): ImageMimeType {\n if (bytes.length === 0) {\n throw new KycirisError(`${filename} is empty.`, { code: 'INVALID_FILE' });\n }\n if (bytes.length > MAX_IMAGE_FILE_SIZE) {\n throw new KycirisError(\n `${filename} is ${(bytes.length / 1024 / 1024).toFixed(1)}MB; the gateway accepts at most ${MAX_IMAGE_FILE_SIZE / 1024 / 1024}MB. Re-encode at a lower quality before uploading.`,\n { code: 'INVALID_FILE' }\n );\n }\n const mimeType = detectImageMimeType(bytes);\n if (!mimeType) {\n throw new KycirisError(\n `${filename} is not a JPEG or PNG image. The gateway decides the type from the file's own bytes, not its name or Content-Type.`,\n { code: 'INVALID_FILE' }\n );\n }\n return mimeType;\n}\n\nfunction bytesToValue(bytes: Uint8Array, mimeType: string, filename: string): NormalizedFile {\n if (isReactNative()) {\n // React Native's FormData cannot take a Blob reliably, but its networking\n // layer does read `data:` URIs — which is why the bytes go back out as one.\n const base64 = encodeBase64(bytes);\n return mark({\n value: { uri: `data:${mimeType};base64,${base64}`, name: filename, type: mimeType },\n filename,\n mimeType,\n });\n }\n\n if (typeof Blob === 'undefined') {\n throw new KycirisError(\n 'This runtime has no Blob, so image bytes cannot be turned into an upload. Node 18+ is required.',\n { code: 'INVALID_FILE' }\n );\n }\n\n // Copied into its own ArrayBuffer: `bytes` may be a view onto a pooled\n // Node Buffer, and Blob would otherwise capture the whole pool.\n const copy = new Uint8Array(bytes.byteLength);\n copy.set(bytes);\n return mark({ value: new Blob([copy], { type: mimeType }), filename, mimeType });\n}\n\n/** Encodes bytes as base64 using whichever primitive the runtime provides. */\nexport function encodeBase64(bytes: Uint8Array): string {\n // Structural, for the reason given in decodeBase64 above.\n const maybeBuffer = (\n globalThis as { Buffer?: { from(b: Uint8Array): { toString(encoding: string): string } } }\n ).Buffer;\n if (maybeBuffer) {\n return maybeBuffer.from(bytes).toString('base64');\n }\n if (typeof btoa === 'function') {\n let binary = '';\n // Chunked: `String.fromCharCode(...bytes)` blows the argument limit on a\n // multi-megabyte photo.\n const CHUNK = 0x8000;\n for (let i = 0; i < bytes.length; i += CHUNK) {\n binary += String.fromCharCode(...bytes.subarray(i, i + CHUNK));\n }\n return btoa(binary);\n }\n throw new KycirisError(\n 'This runtime has neither Buffer nor btoa, so image bytes cannot be base64-encoded.',\n { code: 'INVALID_FILE' }\n );\n}\n\n/**\n * Turns whatever the caller has into something FormData can carry on this\n * platform, validating the bytes first whenever they are visible.\n *\n * A React Native `file://` URI is the one case where they are not: the file\n * lives on disk and only the native layer reads it, so type and size are left\n * to the gateway to enforce.\n *\n * @param input The image, in any supported form\n * @param defaultName Filename to use when the input does not carry one\n */\nexport function normalizeFile(input: FileInput, defaultName: string): NormalizedFile {\n if (input == null) {\n throw new KycirisError(`No image was given for ${defaultName}.`, {\n code: 'INVALID_FILE',\n });\n }\n\n // Already validated and converted: hand it straight back rather than\n // decoding the same photo twice.\n if (isNormalizedFile(input)) return input;\n\n if (typeof Blob !== 'undefined' && input instanceof Blob) {\n assertBlobSize(input, defaultName);\n // Not sniffed here: reading a Blob is async and this function is not. Use\n // prepareFile (which the upload path does) to have the bytes checked.\n const filename = (input as File).name || defaultName;\n return mark({ value: input, filename, mimeType: input.type || 'image/jpeg' });\n }\n\n if (typeof input === 'string') {\n if (input.startsWith('data:')) {\n const { bytes } = parseDataUri(input);\n const mimeType = assertUsableImage(bytes, defaultName);\n return bytesToValue(bytes, mimeType, defaultName);\n }\n\n if (isPlatformUri(input)) {\n if (!isReactNative()) {\n throw new KycirisError(\n `${defaultName} was given as \"${input.slice(0, 12)}…\", a URI only React Native can read. Read the file yourself and pass a Blob or its bytes.`,\n { code: 'INVALID_FILE' }\n );\n }\n return mark({\n value: { uri: input, name: defaultName, type: 'image/jpeg' },\n filename: defaultName,\n mimeType: 'image/jpeg',\n });\n }\n\n const trimmed = input.replace(/\\s/g, '');\n if (!trimmed || !BASE64_ALPHABET.test(trimmed)) {\n throw new KycirisError(\n `${defaultName} was given as a string that is neither a data: URI, a file URI, nor base64.`,\n { code: 'INVALID_FILE' }\n );\n }\n const bytes = decodeBase64(trimmed);\n const mimeType = assertUsableImage(bytes, defaultName);\n return bytesToValue(bytes, mimeType, defaultName);\n }\n\n if ('uri' in input && typeof input.uri === 'string') {\n if (input.uri.startsWith('data:')) {\n const { bytes } = parseDataUri(input.uri);\n const mimeType = assertUsableImage(bytes, input.name ?? defaultName);\n return bytesToValue(bytes, mimeType, input.name ?? defaultName);\n }\n if (!isReactNative()) {\n throw new KycirisError(\n `${defaultName} was given as a { uri } object, which only React Native can read. Read the file yourself and pass a Blob or its bytes.`,\n { code: 'INVALID_FILE' }\n );\n }\n const filename = input.name ?? defaultName;\n const mimeType = input.type ?? 'image/jpeg';\n return mark({ value: { uri: input.uri, name: filename, type: mimeType }, filename, mimeType });\n }\n\n if ('data' in input && input.data) {\n const bytes = toBytes(input.data);\n const filename = input.name ?? defaultName;\n const mimeType = assertUsableImage(bytes, filename);\n return bytesToValue(bytes, mimeType, filename);\n }\n\n throw new KycirisError(\n `${defaultName} is not a Blob, a { uri } object, a { data } object, or a base64/data: string.`,\n { code: 'INVALID_FILE' }\n );\n}\n\n/**\n * The first bytes of a Blob, or null when this runtime cannot produce them.\n *\n * `Blob.prototype.arrayBuffer` is the direct route, but it is absent in Safari\n * before 14 and in jsdom, so FileReader — which every browser that has Blob at\n * all supports — is the fallback. Enough bytes for the longest magic number\n * (PNG's eight).\n */\nasync function readBlobHead(blob: Blob): Promise<Uint8Array | null> {\n const head = blob.slice(0, 8);\n\n if (typeof (head as Blob).arrayBuffer === 'function') {\n try {\n return new Uint8Array(await head.arrayBuffer());\n } catch {\n return null;\n }\n }\n\n if (typeof FileReader === 'undefined') return null;\n\n return new Promise<Uint8Array | null>((resolve) => {\n const reader = new FileReader();\n reader.onload = () =>\n resolve(reader.result instanceof ArrayBuffer ? new Uint8Array(reader.result) : null);\n // Never rejects: a file the SDK cannot inspect is passed on to the gateway,\n // which is the authority on it anyway.\n reader.onerror = () => resolve(null);\n reader.onabort = () => resolve(null);\n try {\n reader.readAsArrayBuffer(head);\n } catch {\n resolve(null);\n }\n });\n}\n\n/**\n * {@link normalizeFile}, but able to read a Blob's first bytes.\n *\n * This is what the upload path uses. A file chosen from an `<input>` arrives\n * as a Blob whose `type` is whatever the operating system guessed from the\n * extension, so a PDF renamed `.jpg` claims to be `image/jpeg` — and the\n * synchronous path has to take that on trust. Reading eight bytes settles it\n * before megabytes go over a phone connection, using the same magic-byte test\n * the gateway applies on arrival.\n *\n * Every other input form is already validated synchronously, so it is simply\n * delegated.\n */\nexport async function prepareFile(input: FileInput, defaultName: string): Promise<NormalizedFile> {\n if (isNormalizedFile(input)) return input;\n\n if (typeof Blob !== 'undefined' && input instanceof Blob) {\n assertBlobSize(input, defaultName);\n\n const filename = (input as File).name || defaultName;\n const head = await readBlobHead(input);\n\n // Unreadable head: keep the caller's declared type rather than refusing a\n // file that may well be fine. The gateway sniffs it on arrival either way,\n // so the cost is a later failure, not a wrong accept.\n if (!head) {\n return mark({ value: input, filename, mimeType: input.type || 'image/jpeg' });\n }\n\n const mimeType = detectImageMimeType(head);\n if (!mimeType) {\n throw new KycirisError(\n `${filename} is not a JPEG or PNG image. The gateway decides the type from the file's own bytes, not its name or Content-Type.`,\n { code: 'INVALID_FILE' }\n );\n }\n\n return mark({ value: input, filename, mimeType });\n }\n\n return normalizeFile(input, defaultName);\n}\n","import { KycirisError } from '../errors';\n\n/**\n * Metadata the gateway attaches to every response, success or error.\n *\n * `requestId` is also returned as the X-Request-Id header and is the value to\n * quote when reporting a problem — it correlates the call with the gateway's\n * own logs.\n */\nexport interface ApiMeta {\n requestId: string;\n timestamp: string;\n /** The gateway's API version, not the SDK's. */\n version: string;\n}\n\nexport interface PaginationMeta {\n page: number;\n limit: number;\n total: number;\n}\n\n/** A successful response, unwrapped. */\nexport interface ApiResult<T> {\n data: T;\n meta: ApiMeta;\n /** Present only on list endpoints. */\n pagination?: PaginationMeta;\n}\n\n/** A page of results: the rows, plus the pagination block that came with them. */\nexport interface Page<T> {\n items: T[];\n pagination: PaginationMeta;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n/** The meta block, if the body carries a well-formed one. */\nexport function readMeta(body: unknown): ApiMeta | undefined {\n if (!isRecord(body) || !isRecord(body.meta)) return undefined;\n const { requestId, timestamp, version } = body.meta;\n if (typeof requestId !== 'string') return undefined;\n return {\n requestId,\n timestamp: typeof timestamp === 'string' ? timestamp : '',\n version: typeof version === 'string' ? version : '',\n };\n}\n\n/**\n * `meta.requestId` alone, for error paths where the body may be anything at\n * all (an nginx error page, a truncated stream).\n */\nexport function readRequestId(body: unknown): string | undefined {\n return readMeta(body)?.requestId;\n}\n\n/**\n * Unwraps `{ data, meta, pagination? }` into an ApiResult.\n *\n * Throws INVALID_RESPONSE rather than returning undefined: a 2xx that is not\n * the documented envelope means something other than the gateway answered\n * (a proxy, a captive portal, the wrong baseUrl), and silently handing the\n * caller `undefined` turns that into a confusing failure much further away.\n */\nexport function unwrapEnvelope<T>(body: unknown, requestPath: string): ApiResult<T> {\n const meta = readMeta(body);\n if (!isRecord(body) || !('data' in body) || !meta) {\n throw new KycirisError(\n `The response to ${requestPath} was not a KYCiris API envelope. Check that baseUrl points at the gateway and that nothing is rewriting responses in between.`,\n { code: 'INVALID_RESPONSE' }\n );\n }\n\n const result: ApiResult<T> = { data: body.data as T, meta };\n\n if (isRecord(body.pagination)) {\n const { page, limit, total } = body.pagination;\n if (\n typeof page === 'number' &&\n typeof limit === 'number' &&\n typeof total === 'number'\n ) {\n result.pagination = { page, limit, total };\n }\n }\n\n return result;\n}\n\n/**\n * Turns an unwrapped list response into a Page.\n *\n * The gateway sends the rows as `data` and the counts as a sibling\n * `pagination` block; a caller wants them together. When the endpoint returned\n * no pagination block (or an unpaginated array), the totals are derived from\n * the rows so the shape stays uniform.\n */\nexport function toPage<T>(result: ApiResult<T[]>): Page<T> {\n const items = Array.isArray(result.data) ? result.data : [];\n return {\n items,\n pagination: result.pagination ?? {\n page: 1,\n limit: items.length,\n total: items.length,\n },\n };\n}\n\n/**\n * The message and code carried by an error envelope\n * (`{ error: { code, message, details }, meta }`).\n *\n * Falls back progressively, because an error response is exactly where a\n * non-gateway intermediary is most likely to have answered instead.\n */\nexport function readErrorEnvelope(body: unknown): {\n code?: string;\n message?: string;\n details?: unknown;\n} {\n if (!isRecord(body)) {\n return typeof body === 'string' && body.trim() ? { message: body.trim() } : {};\n }\n\n const error = isRecord(body.error) ? body.error : undefined;\n if (error) {\n return {\n code: typeof error.code === 'string' ? error.code : undefined,\n message: typeof error.message === 'string' ? error.message : undefined,\n details: error.details,\n };\n }\n\n // Nest's default shape, in case a handler bypasses the exception filter.\n const message = body.message;\n return {\n message: Array.isArray(message)\n ? message.join(', ')\n : typeof message === 'string'\n ? message\n : undefined,\n };\n}\n","import { KycirisError, isRetryableStatus } from '../errors';\nimport { prepareFile, type FileInput } from '../files';\nimport {\n readErrorEnvelope,\n readRequestId,\n unwrapEnvelope,\n type ApiResult,\n} from './envelope';\n\n/** Returns a verification token, refreshing it if the cached one has expired. */\nexport type VerificationTokenProvider = () => string | Promise<string>;\n\n/** The subset of `fetch` the SDK uses, so a custom implementation can stand in. */\nexport type FetchLike = (\n input: string,\n init?: RequestInit\n) => Promise<Response>;\n\n/** Which credential an endpoint accepts. */\nexport type AuthMode = 'api-key' | 'token' | 'any' | 'none';\n\nexport interface HttpClientConfig {\n /** Origin of the gateway, e.g. `https://api.kyciris.com`. */\n baseUrl: string;\n /**\n * Project API key. A project-wide credential — server-side only. Passing it\n * from a browser or React Native app throws CREDENTIAL_MISUSE.\n */\n apiKey?: string;\n /**\n * Verification token, scoped to one end user. This is the credential a\n * client app should hold: mint it on your server with\n * `client.verifications.createToken(externalId)` and hand it out.\n *\n * A function is called before each request, so a token can be refreshed\n * without rebuilding the client.\n */\n verificationToken?: string | VerificationTokenProvider;\n /** URI version segment. Defaults to `v1`. */\n apiVersion?: string;\n /** Per-attempt timeout in ms. Defaults to 30000. */\n timeoutMs?: number;\n /** Retries for a failed attempt. Defaults to 2 (three attempts in total). */\n maxRetries?: number;\n /** Custom fetch (tests, proxies, a Node agent). Defaults to global fetch. */\n fetch?: FetchLike;\n /** Extra headers on every request. Cannot override the auth headers. */\n headers?: Record<string, string>;\n /**\n * Allows an `http://` baseUrl to a non-loopback host.\n *\n * Off by default: the requests carry a project API key or a verification\n * token and the responses carry identity-document data, none of which may\n * cross a plaintext connection.\n */\n allowInsecureBaseUrl?: boolean;\n /**\n * Allows `apiKey` in a browser or React Native app.\n *\n * Only for a trusted first-party context (an internal operations console\n * behind a login). Anything shipped to end users must use a verification\n * token: an API key in a client bundle is extractable and grants the whole\n * project, every identity in it included.\n */\n allowApiKeyInUntrustedClient?: boolean;\n}\n\nexport interface RequestOptions {\n method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n /** Path below the version segment, e.g. `/verification/start`. */\n path: string;\n query?: Record<string, unknown>;\n /** JSON request body. Mutually exclusive with `form`. */\n body?: unknown;\n /** Multipart body. Values typed `FileInput` are normalized per platform. */\n form?: Record<string, string | FileInput | undefined>;\n /** Field names in `form` that hold a file. */\n fileFields?: string[];\n auth?: AuthMode;\n signal?: AbortSignal;\n /** Overrides the client's timeout for this call. */\n timeoutMs?: number;\n /**\n * Whether a failed attempt may be repeated.\n *\n * Defaults to true for GET and false for everything else: a POST that timed\n * out may well have been processed, and re-sending an upload would emit a\n * second pipeline event. A 429 is retried regardless of method, because the\n * gateway rejected it before doing any work.\n */\n retry?: boolean;\n}\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\nconst BASE_BACKOFF_MS = 300;\nconst MAX_BACKOFF_MS = 5_000;\n\n/** Hosts for which plaintext http is legitimate: a developer's own machine. */\nconst LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '::1', '[::1]', '0.0.0.0']);\n\n/**\n * True in a context where the bundle is delivered to an end user and anything\n * inside it is readable by them: a browser page or a React Native app.\n */\nexport function isUntrustedClient(): boolean {\n if (\n typeof navigator !== 'undefined' &&\n (navigator as { product?: string }).product === 'ReactNative'\n ) {\n return true;\n }\n\n if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {\n return true;\n }\n\n // A worker is a browser context with no `window`, so the check above misses\n // it -- and code shipped to a worker is just as readable as code shipped to\n // a page. `importScripts` is the classic marker; the global-scope name\n // covers module workers, which do not have it.\n const scope = globalThis as { importScripts?: unknown; constructor?: { name?: string } };\n if (typeof scope.importScripts === 'function') return true;\n return /WorkerGlobalScope$/.test(scope.constructor?.name ?? '');\n}\n\nfunction assertUsableBaseUrl(baseUrl: string, allowInsecure: boolean): URL {\n let url: URL;\n try {\n url = new URL(baseUrl);\n } catch {\n throw new KycirisError(\n `baseUrl \"${baseUrl}\" is not a valid URL. Expected something like https://api.kyciris.com.`,\n { code: 'CONFIG_ERROR' }\n );\n }\n\n if (url.protocol === 'https:') return url;\n\n if (url.protocol !== 'http:') {\n throw new KycirisError(`baseUrl must be http:// or https://, not ${url.protocol}`, {\n code: 'CONFIG_ERROR',\n });\n }\n\n if (LOOPBACK_HOSTS.has(url.hostname) || allowInsecure) return url;\n\n throw new KycirisError(\n `baseUrl \"${baseUrl}\" is plaintext http to a remote host. API keys, verification tokens and identity-document data would travel unencrypted. Use https, or set allowInsecureBaseUrl if this is a trusted private network.`,\n { code: 'CONFIG_ERROR' }\n );\n}\n\n/** `Retry-After` as milliseconds, whether it is a delay or an HTTP date. */\nfunction parseRetryAfter(header: string | null): number | undefined {\n if (!header) return undefined;\n const seconds = Number(header);\n if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1000;\n const date = Date.parse(header);\n if (!Number.isNaN(date)) return Math.max(0, date - Date.now());\n return undefined;\n}\n\n/** Exponential backoff with full jitter, so retries do not synchronise. */\nfunction backoffDelay(attempt: number): number {\n const ceiling = Math.min(MAX_BACKOFF_MS, BASE_BACKOFF_MS * 2 ** attempt);\n return Math.random() * ceiling;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new KycirisError('The request was aborted.', { code: 'ABORTED' }));\n return;\n }\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n function onAbort() {\n clearTimeout(timer);\n reject(new KycirisError('The request was aborted.', { code: 'ABORTED' }));\n }\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n\n/**\n * The gateway's HTTP transport: URL and auth assembly, timeouts, retries, and\n * translation of the `{ data, meta }` / `{ error, meta }` envelopes into\n * values and KycirisErrors.\n */\nexport class HttpClient {\n private readonly baseUrl: URL;\n private readonly apiVersion: string;\n private readonly timeoutMs: number;\n private readonly maxRetries: number;\n private readonly fetchImpl: FetchLike;\n private readonly extraHeaders: Record<string, string>;\n private readonly apiKey?: string;\n private readonly tokenSource?: string | VerificationTokenProvider;\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = assertUsableBaseUrl(\n config.baseUrl,\n config.allowInsecureBaseUrl ?? false\n );\n\n if (!config.apiKey && !config.verificationToken) {\n throw new KycirisError(\n 'Provide either apiKey (server-side) or verificationToken (client-side) when creating the client.',\n { code: 'CONFIG_ERROR' }\n );\n }\n\n if (\n config.apiKey &&\n isUntrustedClient() &&\n !config.allowApiKeyInUntrustedClient\n ) {\n throw new KycirisError(\n 'A project API key must not be used from a browser or React Native app: it is readable by anyone who has the bundle and grants access to every identity in the project. Mint a verification token on your server (POST /verification/token) and pass it as verificationToken instead.',\n { code: 'CREDENTIAL_MISUSE' }\n );\n }\n\n this.apiKey = config.apiKey;\n this.tokenSource = config.verificationToken;\n this.apiVersion = (config.apiVersion ?? 'v1').replace(/^\\/+|\\/+$/g, '');\n this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n this.maxRetries = Math.max(0, config.maxRetries ?? DEFAULT_MAX_RETRIES);\n this.extraHeaders = { ...config.headers };\n\n const fetchImpl = config.fetch ?? (globalThis.fetch as FetchLike | undefined);\n if (!fetchImpl) {\n throw new KycirisError(\n 'No global fetch was found. Use Node 18+, or pass a fetch implementation as `fetch`.',\n { code: 'CONFIG_ERROR' }\n );\n }\n this.fetchImpl = fetchImpl;\n }\n\n /** True when the client holds a project API key. */\n hasApiKey(): boolean {\n return Boolean(this.apiKey);\n }\n\n /** True when the client holds (or can fetch) a verification token. */\n hasVerificationToken(): boolean {\n return Boolean(this.tokenSource);\n }\n\n buildUrl(path: string, query?: Record<string, unknown>): string {\n const basePath = this.baseUrl.pathname.replace(/\\/+$/, '');\n const url = new URL(this.baseUrl.toString());\n url.pathname = `${basePath}/${this.apiVersion}${path.startsWith('/') ? path : `/${path}`}`;\n\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined || value === null) continue;\n if (Array.isArray(value)) {\n // The gateway accepts a repeated param and a comma-separated list;\n // repeating is what every HTTP client emits natively.\n for (const entry of value) {\n if (entry !== undefined && entry !== null) {\n url.searchParams.append(key, String(entry));\n }\n }\n } else {\n url.searchParams.append(key, String(value));\n }\n }\n }\n\n return url.toString();\n }\n\n private async authHeaders(mode: AuthMode): Promise<Record<string, string>> {\n if (mode === 'none') return {};\n\n if (mode === 'api-key') {\n if (!this.apiKey) {\n throw new KycirisError(\n 'This endpoint requires the project API key, which is a server-side credential. A verification token is scoped to one end user and is refused here.',\n { code: 'MISSING_CREDENTIAL', status: 401 }\n );\n }\n return { 'X-API-Key': this.apiKey };\n }\n\n const token = await this.resolveToken();\n\n if (mode === 'token') {\n if (!token) {\n throw new KycirisError(\n 'This endpoint requires a verification token. Mint one with client.verifications.createToken(externalId) using the project API key.',\n { code: 'MISSING_CREDENTIAL', status: 401 }\n );\n }\n return { 'x-verification-token': token };\n }\n\n // 'any': the narrower credential wins, so a client configured with both\n // never sends the project key where an end-user token would do.\n if (token) return { 'x-verification-token': token };\n if (this.apiKey) return { 'X-API-Key': this.apiKey };\n\n throw new KycirisError('No credential is configured for this request.', {\n code: 'MISSING_CREDENTIAL',\n status: 401,\n });\n }\n\n private async resolveToken(): Promise<string | undefined> {\n if (!this.tokenSource) return undefined;\n if (typeof this.tokenSource === 'string') return this.tokenSource;\n const token = await this.tokenSource();\n if (typeof token !== 'string' || !token) {\n throw new KycirisError(\n 'The verificationToken provider returned no token.',\n { code: 'MISSING_CREDENTIAL', status: 401 }\n );\n }\n return token;\n }\n\n private async buildForm(\n form: Record<string, string | FileInput | undefined>,\n fileFields: string[]\n ): Promise<FormData> {\n if (typeof FormData === 'undefined') {\n throw new KycirisError(\n 'This runtime has no FormData, so files cannot be uploaded. Node 18+ is required.',\n { code: 'CONFIG_ERROR' }\n );\n }\n\n const formData = new FormData();\n for (const [field, value] of Object.entries(form)) {\n if (value === undefined) continue;\n if (fileFields.includes(field)) {\n const file = await prepareFile(value as FileInput, `${field}.jpg`);\n // `as never`: React Native's FormData takes a `{ uri }` object that the\n // DOM typings do not describe, and it is the only thing that works there.\n formData.append(field, file.value as never, file.filename);\n } else {\n formData.append(field, String(value));\n }\n }\n return formData;\n }\n\n /** Runs a request, retrying where the method and failure allow it. */\n async request<T>(options: RequestOptions): Promise<ApiResult<T>> {\n const method = options.method ?? 'GET';\n const url = this.buildUrl(options.path, options.query);\n const idempotent = options.retry ?? method === 'GET';\n\n // Built once, outside the retry loop: normalizing a file is CPU-bound work\n // on a multi-megabyte image and the result is immutable.\n const formData = options.form\n ? await this.buildForm(options.form, options.fileFields ?? [])\n : undefined;\n\n let attempt = 0;\n for (;;) {\n try {\n return await this.attempt<T>(options, method, url, formData);\n } catch (error) {\n const failure = error as KycirisError;\n const canRetry =\n attempt < this.maxRetries &&\n KycirisError.isKycirisError(failure) &&\n failure.retryable &&\n // A rate-limited request never ran, so repeating it is safe whatever\n // the method. Everything else is only repeated when the caller says\n // the call can be made twice.\n (idempotent || failure.status === 429);\n\n if (!canRetry) throw error;\n\n const delay = failure.status === 429 && failure.details\n ? ((failure.details as { retryAfterMs?: number }).retryAfterMs ??\n backoffDelay(attempt))\n : backoffDelay(attempt);\n\n await sleep(delay, options.signal);\n attempt += 1;\n }\n }\n }\n\n private async attempt<T>(\n options: RequestOptions,\n method: string,\n url: string,\n formData?: FormData\n ): Promise<ApiResult<T>> {\n // Checked before anything is set up: an AbortSignal that fired earlier\n // never fires again, so a listener alone would let the request go out.\n if (options.signal?.aborted) {\n throw new KycirisError('The request was aborted.', { code: 'ABORTED' });\n }\n\n const controller = new AbortController();\n const timeoutMs = options.timeoutMs ?? this.timeoutMs;\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n const onCallerAbort = () => controller.abort();\n options.signal?.addEventListener('abort', onCallerAbort, { once: true });\n\n try {\n const headers: Record<string, string> = {\n Accept: 'application/json',\n ...this.extraHeaders,\n ...(await this.authHeaders(options.auth ?? 'any')),\n };\n\n let body: BodyInit | undefined;\n if (formData) {\n // Content-Type is left to fetch, which has to add the multipart\n // boundary; setting it by hand produces a body the server cannot parse.\n body = formData;\n } else if (options.body !== undefined) {\n headers['Content-Type'] = 'application/json';\n body = JSON.stringify(options.body);\n }\n\n let response: Response;\n try {\n response = await this.fetchImpl(url, {\n method,\n headers,\n body,\n signal: controller.signal,\n });\n } catch (cause) {\n if (options.signal?.aborted) {\n throw new KycirisError('The request was aborted.', {\n code: 'ABORTED',\n cause,\n });\n }\n if (controller.signal.aborted) {\n throw new KycirisError(\n `The request to ${options.path} timed out after ${timeoutMs}ms.`,\n { code: 'TIMEOUT', retryable: true, cause }\n );\n }\n throw new KycirisError(\n `The request to ${options.path} could not reach the gateway. Check connectivity, the baseUrl, and (in a browser) that this origin is in the gateway's ALLOWED_ORIGINS.`,\n { code: 'NETWORK_ERROR', retryable: true, cause }\n );\n }\n\n const payload = await readBody(response);\n\n if (!response.ok) {\n throw toApiError(response, payload, options.path);\n }\n\n // A body-less success. Not only 204: the gateway's DELETE handlers return\n // void, and its response interceptor passes `undefined` straight through\n // rather than wrapping it — so a delete answers 200 with an empty body,\n // which is not an envelope and must not be treated as a malformed one.\n //\n // An empty body is the discriminator, not the status: a non-empty body\n // that is not an envelope still raises INVALID_RESPONSE, because that\n // means something other than the gateway answered.\n if (response.status === 204 || payload === undefined) {\n return {\n data: undefined as T,\n meta: {\n requestId: response.headers.get('x-request-id') ?? '',\n timestamp: new Date().toISOString(),\n version: '',\n },\n };\n }\n\n return unwrapEnvelope<T>(payload, options.path);\n } finally {\n clearTimeout(timer);\n options.signal?.removeEventListener('abort', onCallerAbort);\n }\n }\n\n /**\n * Streams a response body instead of parsing it — the media download\n * endpoint returns an image, not an envelope.\n */\n async requestRaw(options: RequestOptions): Promise<Response> {\n if (options.signal?.aborted) {\n throw new KycirisError('The request was aborted.', { code: 'ABORTED' });\n }\n\n const url = this.buildUrl(options.path, options.query);\n const controller = new AbortController();\n const timeoutMs = options.timeoutMs ?? this.timeoutMs;\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n const onCallerAbort = () => controller.abort();\n options.signal?.addEventListener('abort', onCallerAbort, { once: true });\n\n try {\n const headers: Record<string, string> = {\n ...this.extraHeaders,\n ...(await this.authHeaders(options.auth ?? 'any')),\n };\n\n let response: Response;\n try {\n response = await this.fetchImpl(url, {\n method: options.method ?? 'GET',\n headers,\n signal: controller.signal,\n });\n } catch (cause) {\n if (options.signal?.aborted) {\n throw new KycirisError('The request was aborted.', { code: 'ABORTED', cause });\n }\n if (controller.signal.aborted) {\n throw new KycirisError(\n `The request to ${options.path} timed out after ${timeoutMs}ms.`,\n { code: 'TIMEOUT', retryable: true, cause }\n );\n }\n throw new KycirisError(\n `The request to ${options.path} could not reach the gateway.`,\n { code: 'NETWORK_ERROR', retryable: true, cause }\n );\n }\n\n if (!response.ok) {\n throw toApiError(response, await readBody(response), options.path);\n }\n\n return response;\n } finally {\n clearTimeout(timer);\n options.signal?.removeEventListener('abort', onCallerAbort);\n }\n }\n}\n\nasync function readBody(response: Response): Promise<unknown> {\n const contentType = response.headers.get('content-type') ?? '';\n try {\n if (contentType.includes('application/json')) {\n return await response.json();\n }\n const text = await response.text();\n if (!text) return undefined;\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n } catch {\n return undefined;\n }\n}\n\n/**\n * Turns a non-2xx response into a KycirisError carrying the gateway's own\n * error code and requestId.\n *\n * Nothing from the request is attached — the headers hold the API key and the\n * verification token, and an error object is the thing most likely to be\n * logged whole.\n */\nfunction toApiError(\n response: Response,\n payload: unknown,\n path: string\n): KycirisError {\n const { code, message, details } = readErrorEnvelope(payload);\n const retryAfterMs = parseRetryAfter(response.headers.get('retry-after'));\n\n const fallback =\n response.status === 401\n ? 'The credential was rejected. Check the API key, or mint a fresh verification token — they expire.'\n : response.status === 403\n ? 'The gateway refused this request.'\n : `The gateway returned ${response.status} for ${path}.`;\n\n return new KycirisError(message || fallback, {\n code: code ?? statusFallbackCode(response.status),\n status: response.status,\n requestId:\n readRequestId(payload) ?? response.headers.get('x-request-id') ?? undefined,\n details:\n retryAfterMs !== undefined\n ? { ...(typeof details === 'object' && details ? details : { details }), retryAfterMs }\n : details,\n retryable: isRetryableStatus(response.status),\n });\n}\n\nfunction statusFallbackCode(status: number): string {\n switch (status) {\n case 400:\n case 422:\n return 'VALIDATION_ERROR';\n case 401:\n return 'UNAUTHORIZED';\n case 403:\n return 'FORBIDDEN';\n case 404:\n return 'NOT_FOUND';\n case 409:\n return 'RESOURCE_ALREADY_EXISTS';\n case 429:\n return 'RATE_LIMIT_EXCEEDED';\n default:\n return 'INTERNAL_SERVER_ERROR';\n }\n}\n","import type { HttpClient } from '../http/client';\nimport type { Analytics } from '../types';\n\n/** Monthly identity and verification counts, with month-over-month change. */\nexport class AnalyticsResource {\n constructor(private readonly http: HttpClient) {}\n\n async get(options: { signal?: AbortSignal } = {}): Promise<Analytics> {\n const result = await this.http.request<Analytics>({\n path: '/analytics',\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n}\n","import { KycirisError } from './errors';\n\nexport interface PollOptions {\n /** Delay between attempts, in ms. Defaults to 3000. */\n intervalMs?: number;\n /** Give up after this long, in ms. Defaults to 120000. */\n timeoutMs?: number;\n /** Cancels the poll; the promise rejects with code ABORTED. */\n signal?: AbortSignal;\n}\n\nexport interface PollCallbacks<T> {\n /** Called with every intermediate value, before the done check. */\n onUpdate?: (value: T) => void;\n}\n\nconst DEFAULT_INTERVAL_MS = 3_000;\nconst DEFAULT_TIMEOUT_MS = 120_000;\n\nfunction abortError(): KycirisError {\n return new KycirisError('Polling was aborted.', { code: 'ABORTED' });\n}\n\n/**\n * Calls `fetchOnce` until `isDone` accepts the result, the timeout elapses, or\n * the caller aborts.\n *\n * Written as a loop with an awaited delay rather than a self-scheduling\n * setTimeout so that a cancelled poll actually stops: the previous\n * implementation left a pending timer behind after rejecting, which in React\n * Native keeps the JS context awake and warns about a setState on an unmounted\n * component.\n *\n * The timeout is checked before sleeping as well as after, so a poll never\n * waits out one final interval it has no time left to use.\n */\nexport async function pollUntil<T>(\n fetchOnce: (signal?: AbortSignal) => Promise<T>,\n isDone: (value: T) => boolean,\n options: PollOptions & PollCallbacks<T> = {},\n description = 'the operation'\n): Promise<T> {\n const intervalMs = Math.max(0, options.intervalMs ?? DEFAULT_INTERVAL_MS);\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const deadline = Date.now() + timeoutMs;\n\n for (;;) {\n if (options.signal?.aborted) throw abortError();\n\n const value = await fetchOnce(options.signal);\n options.onUpdate?.(value);\n\n if (isDone(value)) return value;\n\n const remaining = deadline - Date.now();\n if (remaining <= 0) {\n throw new KycirisError(\n `Timed out after ${timeoutMs}ms waiting for ${description} to finish. It may still complete — read the status again later, or subscribe to the webhook instead of polling.`,\n { code: 'POLL_TIMEOUT', details: { lastValue: value } }\n );\n }\n\n await delay(Math.min(intervalMs, remaining), options.signal);\n }\n}\n\nfunction delay(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(abortError());\n return;\n }\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n function onAbort() {\n clearTimeout(timer);\n reject(abortError());\n }\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n","import type { FileInput } from '../files';\nimport type { HttpClient } from '../http/client';\nimport { toPage, type Page } from '../http/envelope';\nimport { pollUntil, type PollCallbacks, type PollOptions } from '../poll';\nimport type {\n DuplicateField,\n FaceCheck,\n Identity,\n IdentityFields,\n IdentitySummary,\n ListIdentitiesParams,\n VerificationListItem,\n} from '../types';\n\nexport interface DuplicateGroup {\n value: string;\n count: number;\n identities: IdentitySummary[];\n}\n\nexport interface DuplicatesByField {\n field: string;\n totalDuplicateGroups: number;\n totalDuplicateIdentities: number;\n duplicates: DuplicateGroup[];\n}\n\nexport interface DuplicatesByFields {\n fields: string[];\n results: Record<string, DuplicatesByField>;\n}\n\n/**\n * The identity records behind verifications — the person, as opposed to any\n * one attempt to verify them.\n *\n * Every endpoint here needs the project API key. A verification token is\n * scoped to a single end user's flow and is refused, which is deliberate: an\n * identity record holds the full extracted document data, and a client app has\n * no business reading the project's identities.\n */\nexport class IdentitiesResource {\n constructor(private readonly http: HttpClient) {}\n\n /** Registers an identity independently of any verification. */\n async create(\n fields: IdentityFields,\n options: { signal?: AbortSignal } = {}\n ): Promise<Identity> {\n const result = await this.http.request<Identity>({\n method: 'POST',\n path: '/identities',\n body: fields,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /** A page of identity summaries. Read one identity for the full record. */\n async list(\n params: ListIdentitiesParams = {},\n options: { signal?: AbortSignal } = {}\n ): Promise<Page<IdentitySummary>> {\n const result = await this.http.request<IdentitySummary[]>({\n path: '/identities',\n query: { ...params },\n auth: 'api-key',\n signal: options.signal,\n });\n return toPage(result);\n }\n\n /** The full record, including its verification history. */\n async get(id: string, options: { signal?: AbortSignal } = {}): Promise<Identity> {\n const result = await this.http.request<Identity>({\n path: `/identities/${encodeURIComponent(id)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /** This identity's verifications, without embeddings or storage paths. */\n async verifications(\n id: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<VerificationListItem[]> {\n const result = await this.http.request<VerificationListItem[]>({\n path: `/identities/${encodeURIComponent(id)}/verifications`,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data ?? [];\n }\n\n async update(\n id: string,\n fields: IdentityFields,\n options: { signal?: AbortSignal } = {}\n ): Promise<Identity> {\n const result = await this.http.request<Identity>({\n method: 'PUT',\n path: `/identities/${encodeURIComponent(id)}`,\n body: fields,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /** Deletes the identity, its verifications, and the stored images. */\n async delete(id: string, options: { signal?: AbortSignal } = {}): Promise<void> {\n await this.http.request<void>({\n method: 'DELETE',\n path: `/identities/${encodeURIComponent(id)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n }\n\n /**\n * Groups identities that share a value, to find duplicate registrations.\n *\n * Passing one field returns a single grouping; passing several returns one\n * per field, which is why the return type is a union.\n */\n async findDuplicates(\n params: { field?: DuplicateField | DuplicateField[]; id?: string } = {},\n options: { signal?: AbortSignal } = {}\n ): Promise<DuplicatesByField | DuplicatesByFields> {\n const result = await this.http.request<DuplicatesByField | DuplicatesByFields>({\n path: '/identities/duplicates',\n query: { field: params.field, id: params.id },\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /**\n * Folds duplicates into a primary identity, moving their verifications\n * across and deleting them. Requires the admin role on a user token; an API\n * key is a project credential and carries no role.\n */\n async merge(\n id: string,\n duplicateIds: string[],\n options: { signal?: AbortSignal } = {}\n ): Promise<unknown> {\n const result = await this.http.request<unknown>({\n method: 'POST',\n path: '/identities/merge',\n body: { id, duplicateIds },\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /**\n * Compares a fresh photo against the face already on file for an identity —\n * a re-authentication check, separate from the verification flow.\n *\n * Asynchronous: the returned check starts PENDING. Poll it with\n * `faceCheckStatus`, or use `waitForFaceCheck`.\n */\n async faceMatch(\n id: string,\n file: FileInput,\n options: { signal?: AbortSignal; timeoutMs?: number } = {}\n ): Promise<FaceCheck> {\n const result = await this.http.request<FaceCheck>({\n method: 'POST',\n path: `/identities/${encodeURIComponent(id)}/face-match`,\n form: { file },\n fileFields: ['file'],\n auth: 'api-key',\n signal: options.signal,\n timeoutMs: options.timeoutMs,\n });\n return result.data;\n }\n\n /** The result of a face-match check started with `faceMatch`. */\n async faceCheckStatus(\n id: string,\n faceCheckId: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<FaceCheck> {\n const result = await this.http.request<FaceCheck>({\n path: `/identities/${encodeURIComponent(id)}/face-match/status/${encodeURIComponent(faceCheckId)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /** Polls a face-match check until it is APPROVED or REJECTED. */\n async waitForFaceCheck(\n id: string,\n faceCheckId: string,\n options: PollOptions & PollCallbacks<FaceCheck> = {}\n ): Promise<FaceCheck> {\n return pollUntil<FaceCheck>(\n (signal) => this.faceCheckStatus(id, faceCheckId, { signal }),\n (check) => check.status === 'APPROVED' || check.status === 'REJECTED',\n options,\n `face check ${faceCheckId}`\n );\n }\n}\n","import type { HttpClient } from '../http/client';\nimport type { VerificationLevel, VerificationLevelDefinition } from '../types';\n\nexport interface CreateLevelParams {\n /** Unique within the project. */\n name: string;\n definition: VerificationLevelDefinition;\n isActive?: boolean;\n}\n\nexport interface UpdateLevelParams {\n name?: string;\n /** Replaces the required steps entirely. */\n definition?: VerificationLevelDefinition;\n isActive?: boolean;\n}\n\n/**\n * Verification levels: named, reusable policies saying which steps a\n * verification requires and which documents it accepts.\n *\n * Every verification names one at start time (`levelName`), and there is no\n * default: a project can verify nobody until it has at least one active level,\n * and a definition must include an IDENTITY_DOCUMENT step saying which\n * (country, documentType) pairs it accepts.\n *\n * API key only, and creating or changing one needs the admin role when acting\n * as a user. Deleting is a soft delete, so verifications that already ran keep\n * the rules they ran under.\n */\nexport class LevelsResource {\n constructor(private readonly http: HttpClient) {}\n\n async create(\n params: CreateLevelParams,\n options: { signal?: AbortSignal } = {}\n ): Promise<VerificationLevel> {\n const result = await this.http.request<VerificationLevel>({\n method: 'POST',\n path: '/verification-levels',\n body: params,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n async list(options: { signal?: AbortSignal } = {}): Promise<VerificationLevel[]> {\n const result = await this.http.request<VerificationLevel[]>({\n path: '/verification-levels',\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data ?? [];\n }\n\n async get(\n id: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<VerificationLevel> {\n const result = await this.http.request<VerificationLevel>({\n path: `/verification-levels/${encodeURIComponent(id)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n async update(\n id: string,\n params: UpdateLevelParams,\n options: { signal?: AbortSignal } = {}\n ): Promise<VerificationLevel> {\n const result = await this.http.request<VerificationLevel>({\n method: 'PUT',\n path: `/verification-levels/${encodeURIComponent(id)}`,\n body: params,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n async delete(id: string, options: { signal?: AbortSignal } = {}): Promise<void> {\n await this.http.request<void>({\n method: 'DELETE',\n path: `/verification-levels/${encodeURIComponent(id)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n }\n}\n","import type { HttpClient } from '../http/client';\nimport type { MediaResource } from '../types';\n\nexport interface DownloadToken {\n token: string;\n /** Lifetime in seconds. The gateway fixes it at 60. */\n expiresIn: number;\n}\n\n/**\n * Access to the images behind a verification: the selfie, both document pages,\n * and the face the OCR worker cropped out of the document.\n *\n * Downloads are two calls on purpose. The first, authenticated with the project\n * API key, issues a token for exactly one file; the second exchanges it for the\n * bytes. The token lives 60 seconds, is invalidated the first time it is used,\n * and every use is written to the gateway's media access log — so an image URL\n * that leaks into a browser history, a screenshot or a support ticket is worth\n * nothing by the time anyone finds it.\n */\nexport class MediaResourceApi {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Issues a single-use, 60-second token for one file of one verification.\n *\n * Useful on its own when the bytes should be fetched somewhere else — hand\n * the token to a browser and let it call the download URL directly, without\n * the API key ever leaving your server.\n */\n async createDownloadToken(\n verificationId: string,\n resource: MediaResource,\n options: { signal?: AbortSignal } = {}\n ): Promise<DownloadToken> {\n const result = await this.http.request<DownloadToken>({\n method: 'POST',\n path: `/media/token/${encodeURIComponent(verificationId)}`,\n body: { resource },\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /**\n * The URL that exchanges a download token for the file.\n *\n * Treat it as a credential: the token is the whole authorization, so the URL\n * grants the image to whoever holds it, once.\n */\n downloadUrl(token: string): string {\n return this.http.buildUrl('/media/download', { token });\n }\n\n /**\n * Fetches a file, taking care of both steps.\n *\n * Returns the raw Response so a caller can stream it (to disk, or straight\n * into an HTTP response) instead of holding an identity document in memory.\n */\n async download(\n verificationId: string,\n resource: MediaResource,\n options: { signal?: AbortSignal } = {}\n ): Promise<Response> {\n const { token } = await this.createDownloadToken(verificationId, resource, options);\n return this.http.requestRaw({\n path: '/media/download',\n query: { token },\n // The single-use token *is* the credential here; sending the API key as\n // well would put it on a URL-addressed request for no benefit.\n auth: 'none',\n signal: options.signal,\n });\n }\n\n /** Fetches a file and buffers it. Convenient; holds the image in memory. */\n async downloadBytes(\n verificationId: string,\n resource: MediaResource,\n options: { signal?: AbortSignal } = {}\n ): Promise<Uint8Array> {\n const response = await this.download(verificationId, resource, options);\n return new Uint8Array(await response.arrayBuffer());\n }\n}\n","/**\n * Domain types mirroring the KYCiris gateway's public contract.\n *\n * Everything here is derived from the gateway's DTOs and constants; where the\n * gateway is the authority for a set of values (document catalog, statuses,\n * webhook events) the list is reproduced verbatim rather than widened to\n * `string`, so a typo fails at compile time instead of at runtime with a 422.\n */\n\n// ---------------------------------------------------------------------------\n// Documents\n// ---------------------------------------------------------------------------\n\n/**\n * The (country, documentType) pairs the pipeline can actually process.\n *\n * Mirrors DOCUMENT_CATALOG in the gateway, which in turn mirrors the OCR\n * worker's handler registry — a pair is only real once something knows how to\n * read it. Starting a verification for a pair outside this list is rejected by\n * the gateway with VALIDATION_ERROR.\n */\nexport const DOCUMENT_CATALOG = [\n { country: 'AO', documentType: 'ID_CARD' },\n { country: 'AO', documentType: 'DRIVING_LICENSE' },\n { country: 'MZ', documentType: 'ID_CARD' },\n] as const;\n\nexport type DocumentCatalogEntry = (typeof DOCUMENT_CATALOG)[number];\n\n/** ISO 3166-1 alpha-2 codes present in the catalog. */\nexport type CatalogCountry = DocumentCatalogEntry['country'];\n\n/** Document type codes present in the catalog. */\nexport type DocumentType = DocumentCatalogEntry['documentType'];\n\n/** True when the gateway can process this pair. */\nexport function isSupportedDocumentPair(\n country: string,\n documentType: string\n): boolean {\n return DOCUMENT_CATALOG.some(\n (entry) => entry.country === country && entry.documentType === documentType\n );\n}\n\n/** The countries in the catalog, deduplicated. */\nexport function supportedCountries(): CatalogCountry[] {\n return Array.from(new Set(DOCUMENT_CATALOG.map((entry) => entry.country)));\n}\n\n/** The document types the catalog supports for `country`. */\nexport function supportedDocumentTypes(country: string): DocumentType[] {\n return DOCUMENT_CATALOG.filter((entry) => entry.country === country).map(\n (entry) => entry.documentType\n );\n}\n\n// ---------------------------------------------------------------------------\n// Verification lifecycle\n// ---------------------------------------------------------------------------\n\n/** The pipeline's state machine, as written by the gateway and its workers. */\nexport const VERIFICATION_STATUSES = [\n 'PENDING',\n 'PROCESSING',\n 'REVIEW',\n 'APPROVED',\n 'REJECTED',\n] as const;\n\nexport type VerificationStatus = (typeof VERIFICATION_STATUSES)[number];\n\n/**\n * What a verification *means* operationally, derived by the gateway from the\n * status and rejection code.\n *\n * The distinction that `status` alone cannot make: REJECTED is written both\n * when the rules genuinely said no and when our own OCR choked on a valid\n * document. Those want opposite handling — the first is an answer for the end\n * user, the second is a retry for us.\n */\nexport const VERIFICATION_OUTCOMES = [\n /** Passed. */\n 'APPROVED',\n /** A genuine business decision. Retrying cannot change it. */\n 'REJECTED',\n /** The pipeline broke. Not the user's fault; retry once fixed. */\n 'FAILED_TECHNICAL',\n /** Could be either — a human should look at the images. */\n 'NEEDS_REVIEW',\n] as const;\n\nexport type VerificationOutcome = (typeof VERIFICATION_OUTCOMES)[number];\n\n/** Statuses from which the pipeline will not move on its own. */\nexport const TERMINAL_VERIFICATION_STATUSES = ['APPROVED', 'REJECTED'] as const;\n\n/** True when the pipeline has reached a decision for this status. */\nexport function isTerminalStatus(status: string): boolean {\n return (TERMINAL_VERIFICATION_STATUSES as readonly string[]).includes(status);\n}\n\n/** A step the end user has to complete before the pipeline can decide. */\nexport type VerificationStep = 'document_front' | 'document_back' | 'selfie';\n\n/** The side of an identity document being uploaded. */\nexport type DocumentSide = 'front' | 'back';\n\n/** Files a verification can hold, as named by the gateway's media endpoints. */\nexport type MediaResource =\n | 'selfie'\n | 'document-front'\n | 'document-back'\n | 'document-face';\n\n// ---------------------------------------------------------------------------\n// Request / response payloads\n// ---------------------------------------------------------------------------\n\nexport interface StartVerificationParams {\n /** Must form a supported pair with `country` (see DOCUMENT_CATALOG). */\n documentType: DocumentType | (string & {});\n /** ISO 3166-1 alpha-2 country code. */\n country: CatalogCountry | (string & {});\n /** Link to an existing identity instead of creating a new one. */\n identityId?: string;\n /**\n * Your own reference for this end user.\n *\n * Ignored when the client authenticates with a verification token: that token\n * is already bound to one externalId, and the gateway treats the token's\n * value as authoritative so a token cannot create a verification under\n * someone else's reference.\n */\n externalId?: string;\n /**\n * Name of the verification level (policy) to run under. Required.\n *\n * The level is what says which documents the project accepts and whether a\n * selfie is needed, so the gateway has no verification without one: a start\n * that names no level, or names one that is not active on the project, is\n * rejected (422 / 404). Levels are created from your backend with\n * `client.levels.create()` -- a project can verify nobody until it has one.\n */\n levelName: string;\n}\n\nexport interface VerificationSession {\n verificationId: string;\n identityId?: string;\n status: VerificationStatus;\n}\n\n/** OCR output. Fields present depend on the document; unread fields are null. */\nexport interface OcrData {\n country?: string | null;\n documentType?: string | null;\n fullName?: string | null;\n idNumber?: string | null;\n birthDate?: string | null;\n validFrom?: string | null;\n validUntil?: string | null;\n gender?: string | null;\n height?: number | null;\n address?: string | null;\n mrz?: string | null;\n maritalStatus?: string | null;\n [field: string]: unknown;\n}\n\n/**\n * What an applicant still owes, and the verdict about the person.\n *\n * A level may require more than one document, which makes \"this document is\n * approved\" and \"this person is verified\" different statements. Only the second\n * one is what an integration actually wants to act on.\n */\nexport type ApplicantAnswer = 'GREEN' | 'RED';\n\n/**\n * Whether presenting the document again could change the answer.\n *\n * `RETRY` is a bad photo, or a failure on the gateway's side -- ask the user to\n * try again. `FINAL` is a decision the rules would reach again, so asking them\n * to retry only wastes their time.\n */\nexport type ApplicantRejectType = 'RETRY' | 'FINAL';\n\nexport type RequirementStatus = 'APPROVED' | 'REVIEW' | 'REJECTED' | 'PENDING';\n\nexport interface ApplicantRequirement {\n /** One of the document types the level asks for. */\n documentType: string;\n status: RequirementStatus;\n /** The verification that settled it, when one has. */\n verificationId: string | null;\n rejectionType: string | null;\n}\n\nexport interface ApplicantStatus {\n identityId: string;\n externalId: string;\n /** Decides which of the level's document lists applies. */\n country: string | null;\n levelName: string;\n /** Every required document approved. */\n complete: boolean;\n /** Null while nothing has been decided, which must not read as a refusal. */\n answer: ApplicantAnswer | null;\n rejectType: ApplicantRejectType | null;\n rejectLabels: string[];\n requirements: ApplicantRequirement[];\n /** Document types with nothing approved yet: what to ask the user for next. */\n outstanding: string[];\n selfie: {\n required: boolean;\n /** Captured once per applicant and reused for every document. */\n captured: boolean;\n capturedAt: string | null;\n };\n}\n\nexport interface GetApplicantParams {\n /**\n * The applicant's id in your own system. Required when the client holds an\n * API key; ignored when it holds a verification token, which already names\n * one end-user.\n */\n externalId?: string;\n /**\n * Only needed before the applicant's first verification exists, when there is\n * no level to read from their history.\n */\n levelName?: string;\n}\n\nexport interface VerificationStatusResponse {\n verificationId: string;\n status: VerificationStatus;\n /** Null while still PENDING/PROCESSING — no outcome exists yet. */\n outcome: VerificationOutcome | null;\n /** 0-1 similarity between selfie and document photo; null until computed. */\n faceMatchScore: number | null;\n /** Null until the document front has been processed. */\n ocrData: OcrData | null;\n /** A gateway ERROR_CODE naming why, when the pipeline stopped or refused. */\n rejectionType: string | null;\n rejectionReason: string | null;\n /** An operator's email, \"system\", or null. */\n decidedBy: string | null;\n decidedAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface UploadResult {\n message: string;\n status: VerificationStatus;\n}\n\n/** One row of the operations list. Deliberately free of OCR data and paths. */\nexport interface VerificationListItem {\n id: string;\n externalId: string | null;\n status: VerificationStatus;\n outcome: VerificationOutcome | null;\n /** True when it has sat in flight past the gateway's stall threshold. */\n stalled: boolean;\n country: string | null;\n documentType: string | null;\n faceMatchScore: number | null;\n rejectionType: string | null;\n rejectionReason: string | null;\n decidedBy: string | null;\n decidedAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ListVerificationsParams {\n page?: number;\n /** 1-100; the gateway rejects anything larger. */\n limit?: number;\n status?: VerificationStatus[];\n outcome?: VerificationOutcome;\n /** Only stalled (true) or only healthy (false). Omit for both. */\n stalled?: boolean;\n country?: string;\n documentType?: string;\n /** Exact match on your own reference. */\n externalId?: string;\n /** ISO 8601 instant. */\n createdAfter?: string;\n /** ISO 8601 instant. */\n createdBefore?: string;\n order?: 'ASC' | 'DESC';\n}\n\nexport interface VerificationSummary {\n byStatus: Partial<Record<VerificationStatus, number>>;\n byOutcome: Partial<Record<VerificationOutcome, number>>;\n needsAttention: {\n stalled: number;\n failedTechnical: number;\n needsReview: number;\n parkedMessages: number;\n };\n}\n\n/** What kind of thing one history entry records. */\nexport const PIPELINE_EVENT_KINDS = [\n /** The verification was created — the start of every timeline. */\n 'CREATED',\n /** The status moved; `fromStatus`/`toStatus` say where. */\n 'STATUS_CHANGED',\n /**\n * The pipeline was re-run from the uploaded files, clearing what had been\n * extracted. Not a STATUS_CHANGED: a re-run of an already-PROCESSING\n * verification would otherwise read \"PROCESSING -> PROCESSING\", which says\n * nothing while hiding the destructive part.\n */\n 'REPROCESSED',\n /** A queue message for it exhausted every retry and was stored. */\n 'JOB_PARKED',\n /** A parked message was handed back to its handler. */\n 'JOB_RESENT',\n /** A parked message was abandoned. Reversible — a resend may follow. */\n 'JOB_DISCARDED',\n] as const;\n\nexport type PipelineEventKind = (typeof PIPELINE_EVENT_KINDS)[number];\n\n/**\n * One entry in a verification's history, appended and never updated.\n *\n * The verification row keeps only the last decision, so this is the only place\n * the sequence survives. Entries that predate the history simply do not exist —\n * a verification from before it shows its creation and last decision and\n * nothing between.\n */\nexport interface PipelineEvent {\n id: string;\n kind: PipelineEventKind | (string & {});\n fromStatus: string | null;\n toStatus: string | null;\n /**\n * Who did it, as a label frozen at the time — an operator's email, or\n * \"system\". A snapshot, so it stays true after the person is renamed or\n * removed.\n */\n actorLabel: string;\n actorUserId: string | null;\n /** The one thing worth reading beside the transition. */\n detail: string | null;\n createdAt: string;\n [field: string]: unknown;\n}\n\nexport interface ReviewDecision {\n decision: 'APPROVED' | 'REJECTED';\n /** Stored when rejecting. */\n reason?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Verification levels\n// ---------------------------------------------------------------------------\n\nexport interface IdentityDocumentStep {\n step: 'IDENTITY_DOCUMENT';\n required: true;\n documents: { country: string; types: string[] }[];\n}\n\nexport interface SelfieStep {\n step: 'SELFIE';\n required: boolean;\n /** Accepted but not enforced by the gateway yet. */\n liveness?: boolean;\n}\n\nexport type VerificationLevelStep = IdentityDocumentStep | SelfieStep;\n\nexport interface VerificationLevelDefinition {\n requiredSteps: VerificationLevelStep[];\n}\n\nexport interface VerificationLevel {\n id: string;\n name: string;\n isActive: boolean;\n definition: VerificationLevelDefinition;\n createdAt: string;\n updatedAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// Identities\n// ---------------------------------------------------------------------------\n\nexport interface IdentityFields {\n mrz?: string;\n gender?: string;\n height?: number;\n address?: string;\n country?: string;\n fullName?: string;\n idNumber?: string;\n birthDate?: string;\n maritalStatus?: string;\n}\n\nexport interface IdentitySummary extends IdentityFields {\n id: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface Identity extends IdentitySummary {\n verifications?: VerificationListItem[];\n [field: string]: unknown;\n}\n\nexport interface ListIdentitiesParams {\n page?: number;\n limit?: number;\n /** Partial match. */\n fullName?: string;\n country?: string;\n idNumber?: string;\n}\n\n/** Fields the gateway can group duplicate identities by. */\nexport const DUPLICATE_FIELDS = [\n 'fullName',\n 'idNumber',\n 'mrz',\n 'gender',\n 'country',\n 'birthDate',\n] as const;\n\nexport type DuplicateField = (typeof DUPLICATE_FIELDS)[number];\n\nexport interface FaceCheck {\n id: string;\n status: 'PENDING' | 'APPROVED' | 'REJECTED';\n}\n\n// ---------------------------------------------------------------------------\n// OCR (standalone)\n// ---------------------------------------------------------------------------\n\nexport type OcrProcessStatus = 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED';\n\nexport interface OcrProcess {\n id: string;\n status: OcrProcessStatus;\n documentType: string;\n country: string;\n createdAt: string;\n}\n\nexport interface OcrProcessStatusResponse {\n id: string;\n status: OcrProcessStatus;\n /** Present once COMPLETED. */\n ocrResult?: OcrData;\n documentPath?: string;\n createdAt: string;\n updatedAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// Webhooks\n// ---------------------------------------------------------------------------\n\nexport const WEBHOOK_EVENT_TYPES = [\n 'VERIFICATION_STARTED',\n 'VERIFICATION_COMPLETED',\n 'VERIFICATION_APPROVED',\n 'VERIFICATION_REJECTED',\n 'VERIFICATION_REVIEW_REQUIRED',\n 'OCR_COMPLETED',\n 'OCR_FAILED',\n] as const;\n\nexport type WebhookEventType = (typeof WEBHOOK_EVENT_TYPES)[number];\n\n/**\n * Subscribes to every event, including ones added after the endpoint was\n * registered. Prefer it over listing all seven when the intent is \"mirror my\n * verification lifecycle\" — a literal list silently stops being complete.\n */\nexport const ALL_WEBHOOK_EVENTS = '*';\n\nexport type WebhookSubscription = WebhookEventType | typeof ALL_WEBHOOK_EVENTS;\n\nexport interface Webhook {\n id: string;\n url: string;\n eventTypes: WebhookSubscription[];\n isActive: boolean;\n headers?: Record<string, string> | null;\n maxRetries?: number | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CreateWebhookParams {\n /** Must be https:// with a public hostname — the gateway refuses anything else. */\n url: string;\n eventTypes: WebhookSubscription[];\n headers?: Record<string, string>;\n maxRetries?: number;\n}\n\nexport interface UpdateWebhookParams {\n url?: string;\n /** Replaces the current list entirely. */\n eventTypes?: WebhookSubscription[];\n isActive?: boolean;\n headers?: Record<string, string>;\n maxRetries?: number;\n}\n\n/**\n * The result of replaying a delivery.\n *\n * A failed send is a value, not an exception: the gateway records a FAILED row\n * for the attempt either way, so the caller almost always wants to show why\n * beside the delivery it belongs to rather than catch around it.\n */\nexport type WebhookResendResult =\n | { success: true }\n | { success: false; error: string };\n\nexport interface WebhookLogEntry {\n id: string;\n url: string;\n status: string;\n responseStatus?: number | null;\n responseBody?: string | null;\n payload?: Record<string, unknown>;\n headers?: Record<string, string> | null;\n retries?: number | null;\n createdAt: string;\n updatedAt: string;\n [field: string]: unknown;\n}\n\n// ---------------------------------------------------------------------------\n// Analytics\n// ---------------------------------------------------------------------------\n\nexport interface AnalyticsSeries {\n change_percentage: number;\n /** Keyed by month, e.g. \"2026-07\". */\n monthly: Record<string, number>;\n total: number;\n}\n\nexport interface Analytics {\n identity: AnalyticsSeries;\n verification: AnalyticsSeries;\n}\n","import type { FileInput } from '../files';\nimport type { HttpClient } from '../http/client';\nimport { pollUntil, type PollCallbacks, type PollOptions } from '../poll';\nimport {\n isSupportedDocumentPair,\n supportedDocumentTypes,\n type CatalogCountry,\n type DocumentType,\n type OcrProcess,\n type OcrProcessStatusResponse,\n} from '../types';\nimport { KycirisError } from '../errors';\n\nexport interface RunOcrParams {\n documentType: DocumentType | (string & {});\n country: CatalogCountry | (string & {});\n /** Your own reference, for correlating the result. */\n externalId?: string;\n}\n\n/**\n * Standalone document reading, with no verification attached.\n *\n * The same OCR pipeline the verification flow uses, addressed directly: upload\n * a document, get the structured fields back. Nothing is decided and no\n * identity is created — for that, run a verification.\n */\nexport class OcrResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Queues a document for extraction.\n *\n * Returns as soon as the job is accepted; the fields arrive later, via\n * `getStatus` or `waitForResult`.\n */\n async run(\n file: FileInput,\n params: RunOcrParams,\n options: { signal?: AbortSignal; timeoutMs?: number } = {}\n ): Promise<OcrProcess> {\n if (!isSupportedDocumentPair(params.country, params.documentType)) {\n const forCountry = supportedDocumentTypes(params.country);\n throw new KycirisError(\n forCountry.length\n ? `${params.country} supports ${forCountry.join(', ')}, not ${params.documentType}.`\n : `No documents are supported for country \"${params.country}\".`,\n { code: 'VALIDATION_ERROR' }\n );\n }\n\n const result = await this.http.request<OcrProcess>({\n method: 'POST',\n path: '/ocr',\n // The gateway names this field `document`, not `file`.\n form: {\n document: file,\n documentType: params.documentType,\n country: params.country,\n externalId: params.externalId,\n },\n fileFields: ['document'],\n signal: options.signal,\n timeoutMs: options.timeoutMs,\n });\n return result.data;\n }\n\n /** Status of a queued job, with the extracted fields once COMPLETED. */\n async getStatus(\n ocrId: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<OcrProcessStatusResponse> {\n const result = await this.http.request<OcrProcessStatusResponse>({\n path: `/ocr/${encodeURIComponent(ocrId)}/status`,\n signal: options.signal,\n });\n return result.data;\n }\n\n /** Polls until the job is COMPLETED or FAILED. */\n async waitForResult(\n ocrId: string,\n options: PollOptions & PollCallbacks<OcrProcessStatusResponse> = {}\n ): Promise<OcrProcessStatusResponse> {\n return pollUntil<OcrProcessStatusResponse>(\n (signal) => this.getStatus(ocrId, { signal }),\n (process) => process.status === 'COMPLETED' || process.status === 'FAILED',\n options,\n `OCR job ${ocrId}`\n );\n }\n}\n","import { KycirisError } from '../errors';\nimport { prepareFile, type FileInput } from '../files';\nimport type { HttpClient } from '../http/client';\nimport { toPage, type Page } from '../http/envelope';\nimport { pollUntil, type PollCallbacks, type PollOptions } from '../poll';\nimport { SessionStore, type StoredSession } from '../storage';\nimport {\n isSupportedDocumentPair,\n isTerminalStatus,\n supportedDocumentTypes,\n type DocumentSide,\n type ListVerificationsParams,\n type MediaResource,\n type PipelineEvent,\n type ReviewDecision,\n type StartVerificationParams,\n type UploadResult,\n type VerificationListItem,\n type VerificationSession,\n type ApplicantStatus,\n type GetApplicantParams,\n type VerificationStatusResponse,\n type VerificationStep,\n type VerificationSummary,\n} from '../types';\n\nexport interface VerificationToken {\n token: string;\n /** The lifetime the gateway chose, e.g. \"8h\". The caller does not pick it. */\n expiresIn: string;\n}\n\nexport interface AvailableMedia {\n available: MediaResource[];\n}\n\nexport interface UploadOptions {\n signal?: AbortSignal;\n timeoutMs?: number;\n}\n\nexport interface VerificationProgress {\n verificationId: string;\n status: VerificationStatusResponse['status'];\n outcome: VerificationStatusResponse['outcome'];\n uploaded: Record<VerificationStep, boolean>;\n /** The steps still to collect, in the order they should be asked for. */\n missingSteps: VerificationStep[];\n /** True when nothing is left to upload. */\n isComplete: boolean;\n}\n\nexport interface ProgressOptions {\n /**\n * Whether the flow asks for a selfie. Defaults to true, matching the\n * gateway's own default when no verification level is set.\n *\n * A client authenticated with a verification token cannot read the level it\n * is running under — `/verification-levels` needs the project API key — so\n * when a level makes the selfie optional, say so here.\n */\n selfieRequired?: boolean;\n signal?: AbortSignal;\n}\n\nexport interface UploadStepParams {\n step: VerificationStep;\n file: FileInput;\n /** Defaults to the stored session's verification. */\n verificationId?: string;\n /** See ProgressOptions.selfieRequired. */\n selfieRequired?: boolean;\n signal?: AbortSignal;\n timeoutMs?: number;\n}\n\nexport interface UploadStepResult extends UploadResult {\n /** True when the step was already uploaded and nothing was sent. */\n skipped: boolean;\n}\n\nexport interface WaitForResultOptions extends PollOptions, PollCallbacks<VerificationStatusResponse> {\n /**\n * Whether REVIEW ends the wait. Defaults to true.\n *\n * REVIEW means the automated pipeline has finished and handed the\n * verification to a person, which can take hours. Polling through it almost\n * always ends in POLL_TIMEOUT; subscribe to the VERIFICATION_APPROVED /\n * VERIFICATION_REJECTED webhooks for the human's decision instead.\n */\n stopOnReview?: boolean;\n}\n\n/**\n * The document steps every supported document needs.\n *\n * Both sides, for all three catalog pairs. That is not a simplification: the\n * gateway only queues OCR once both `documentFrontPath` and `documentBackPath`\n * exist, and the Angolan driving licence — the one single-card document —\n * reads its address off the back. Collecting only the front leaves the\n * verification sitting in PENDING with nothing running.\n */\nconst DOCUMENT_STEPS: VerificationStep[] = ['document_front', 'document_back'];\n\n/** Which media resource proves a step was uploaded. */\nconst STEP_MEDIA: Record<VerificationStep, MediaResource> = {\n document_front: 'document-front',\n document_back: 'document-back',\n selfie: 'selfie',\n};\n\n/**\n * The end-user verification flow, plus the review and operations endpoints\n * that sit behind the project API key.\n *\n * Everything up to and including `getStatus` works with either credential; the\n * list, summary, history and decision calls are API-key only and say so.\n */\nexport class VerificationsResource {\n constructor(\n private readonly http: HttpClient,\n private readonly session: SessionStore\n ) {}\n\n // -------------------------------------------------------------------------\n // Credentials\n // -------------------------------------------------------------------------\n\n /**\n * Mints a verification token for one end user.\n *\n * Call this on **your server**, with the project API key, and hand the token\n * to the client app. The token authorizes exactly the flow below (start,\n * upload, status) for the given `externalId` and nothing else, which is what\n * keeps the project-wide API key out of a bundle an end user can read.\n *\n * The gateway owns the lifetime (VERIFICATION_TOKEN_TTL, 8h by default) — a\n * client cannot ask for a longer one.\n *\n * @param externalId Your own reference for the end user\n */\n async createToken(\n externalId: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<VerificationToken> {\n const result = await this.http.request<VerificationToken>({\n method: 'POST',\n path: '/verification/token',\n body: { externalId },\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n // -------------------------------------------------------------------------\n // The end-user flow\n // -------------------------------------------------------------------------\n\n /**\n * Starts a verification and, when a storage adapter is configured, records\n * it so an interrupted flow can be resumed.\n *\n * The (country, documentType) pair and the level name are checked here before\n * the request goes out: the gateway rejects an unsupported pair with a 422\n * that names neither what is supported nor why, and a missing level with a\n * validation error that reads like a typo in your code rather than a policy\n * you have not created yet.\n */\n async start(\n params: StartVerificationParams,\n options: { signal?: AbortSignal } = {}\n ): Promise<VerificationSession> {\n if (typeof params.levelName !== 'string' || !params.levelName.trim()) {\n throw new KycirisError(\n 'levelName is required: a verification runs under a verification level, which says which documents are accepted and whether a selfie is needed. Create one from your backend with client.levels.create().',\n { code: 'VALIDATION_ERROR', details: { levelName: params.levelName ?? null } }\n );\n }\n\n if (!isSupportedDocumentPair(params.country, params.documentType)) {\n const forCountry = supportedDocumentTypes(params.country);\n throw new KycirisError(\n forCountry.length\n ? `${params.country} supports ${forCountry.join(', ')}, not ${params.documentType}.`\n : `No documents are supported for country \"${params.country}\".`,\n { code: 'VALIDATION_ERROR', details: { country: params.country, documentType: params.documentType } }\n );\n }\n\n const result = await this.http.request<VerificationSession>({\n method: 'POST',\n path: '/verification/start',\n body: params,\n signal: options.signal,\n });\n\n const started = result.data;\n if (started?.verificationId) {\n await this.session.save({\n verificationId: started.verificationId,\n identityId: started.identityId,\n externalId: params.externalId,\n documentType: params.documentType,\n country: params.country,\n levelName: params.levelName,\n startedAt: new Date().toISOString(),\n });\n }\n\n return started;\n }\n\n /** Uploads the end user's selfie. Triggers face matching once OCR has run. */\n async uploadSelfie(\n verificationId: string,\n file: FileInput,\n options: UploadOptions = {}\n ): Promise<UploadResult> {\n const result = await this.http.request<UploadResult>({\n method: 'POST',\n path: '/verification/upload/selfie',\n form: { verificationId, file },\n fileFields: ['file'],\n signal: options.signal,\n timeoutMs: options.timeoutMs,\n });\n return result.data;\n }\n\n /**\n * Uploads one side of the identity document.\n *\n * OCR is queued once both sides are present, so a flow that collects only\n * the front never starts processing.\n */\n async uploadDocument(\n verificationId: string,\n side: DocumentSide,\n file: FileInput,\n options: UploadOptions = {}\n ): Promise<UploadResult> {\n const result = await this.http.request<UploadResult>({\n method: 'POST',\n path: '/verification/upload/document',\n form: { verificationId, type: side, file },\n fileFields: ['file'],\n signal: options.signal,\n timeoutMs: options.timeoutMs,\n });\n return result.data;\n }\n\n /** Current status, face-match score and extracted document data. */\n async getStatus(\n verificationId: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<VerificationStatusResponse> {\n const result = await this.http.request<VerificationStatusResponse>({\n path: `/verification/status/${encodeURIComponent(verificationId)}`,\n signal: options.signal,\n });\n return result.data;\n }\n\n /**\n * What the applicant still owes, and the verdict about the person.\n *\n * `getStatus` answers for one document. On a level asking for two, its\n * APPROVED is not the answer an integration wants -- the applicant may still\n * owe the other. This is the call that says which, through `outstanding`.\n *\n * Works with a verification token, which reports that token's own end-user\n * and ignores `externalId`, so an app needs no API key to drive a multi-\n * document flow.\n */\n async applicant(\n params: GetApplicantParams = {},\n options: { signal?: AbortSignal } = {}\n ): Promise<ApplicantStatus> {\n const result = await this.http.request<ApplicantStatus>({\n path: '/verification/applicant',\n query: { ...params },\n signal: options.signal,\n });\n return result.data;\n }\n\n /**\n * Which files exist for a verification.\n *\n * This is the credential-safe way to tell what an end user has already\n * uploaded: it works with a verification token, whereas the identity record\n * that used to serve the same purpose is API-key only.\n */\n async listMedia(\n verificationId: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<MediaResource[]> {\n const result = await this.http.request<AvailableMedia>({\n path: `/verification/${encodeURIComponent(verificationId)}/media`,\n signal: options.signal,\n });\n return result.data?.available ?? [];\n }\n\n /**\n * Re-runs OCR and face matching from the files already uploaded.\n *\n * The remedy for a verification that failed technically (outcome\n * FAILED_TECHNICAL) or stalled. Clears the previous extraction and decision,\n * so it is not a read-only operation.\n *\n * Only the document front is required, which is why this also works for a\n * verification that never got as far as the selfie.\n */\n async reanalyze(\n verificationId: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<UploadResult> {\n const result = await this.http.request<UploadResult>({\n method: 'POST',\n path: `/verification/reanalyze/${encodeURIComponent(verificationId)}`,\n signal: options.signal,\n });\n return result.data;\n }\n\n // -------------------------------------------------------------------------\n // Resumable flow helpers\n // -------------------------------------------------------------------------\n\n /** The stored session, or null when there is none. */\n async getSession(): Promise<StoredSession | null> {\n return this.session.read();\n }\n\n /**\n * Forgets the stored session. Call it once a verification is finished, so\n * the next one starts clean.\n */\n async clearSession(): Promise<void> {\n return this.session.clear();\n }\n\n /**\n * What the end user has uploaded and what is still missing.\n *\n * Derived from the files that actually exist server-side rather than from\n * anything the client remembers, so it is correct after a reinstall, on a\n * second device, or when a previous attempt failed mid-upload.\n */\n async getProgress(\n verificationId?: string,\n options: ProgressOptions = {}\n ): Promise<VerificationProgress> {\n const id = await this.resolveVerificationId(verificationId);\n\n const [status, available] = await Promise.all([\n this.getStatus(id, { signal: options.signal }),\n this.listMedia(id, { signal: options.signal }),\n ]);\n\n const present = new Set(available);\n const required: VerificationStep[] = [\n ...DOCUMENT_STEPS,\n ...(options.selfieRequired === false ? [] : (['selfie'] as VerificationStep[])),\n ];\n\n const uploaded = {\n document_front: present.has('document-front'),\n document_back: present.has('document-back'),\n selfie: present.has('selfie'),\n } satisfies Record<VerificationStep, boolean>;\n\n const missingSteps = required.filter((step) => !present.has(STEP_MEDIA[step]));\n\n return {\n verificationId: id,\n status: status.status,\n outcome: status.outcome,\n uploaded,\n missingSteps,\n isComplete: missingSteps.length === 0,\n };\n }\n\n /**\n * Uploads one step, skipping it when the file is already there.\n *\n * The call a resumable UI should make: it never re-sends a step the end user\n * already completed, which matters most on a retry after a dropped\n * connection, where the upload may well have succeeded.\n */\n async uploadStep(params: UploadStepParams): Promise<UploadStepResult> {\n const verificationId = await this.resolveVerificationId(params.verificationId);\n\n // Checked before the progress read, so an unusable image costs no requests\n // at all. The result is passed on rather than the original, so the bytes\n // are decoded and sniffed once instead of twice.\n const prepared = await prepareFile(params.file, `${params.step}.jpg`);\n\n const progress = await this.getProgress(verificationId, {\n selfieRequired: params.selfieRequired,\n signal: params.signal,\n });\n\n if (progress.uploaded[params.step]) {\n return {\n message: `${params.step} was already uploaded`,\n status: progress.status,\n skipped: true,\n };\n }\n\n const uploadOptions: UploadOptions = {\n signal: params.signal,\n timeoutMs: params.timeoutMs,\n };\n\n const result =\n params.step === 'selfie'\n ? await this.uploadSelfie(verificationId, prepared, uploadOptions)\n : await this.uploadDocument(\n verificationId,\n params.step === 'document_front' ? 'front' : 'back',\n prepared,\n uploadOptions\n );\n\n return { ...result, skipped: false };\n }\n\n /**\n * Polls the status until the verification is decided.\n *\n * Stops at APPROVED, REJECTED and — unless `stopOnReview` is false — REVIEW.\n * For anything longer than a user is willing to watch a spinner, use the\n * webhooks: polling burns a request every few seconds and still gives up\n * after `timeoutMs`.\n */\n async waitForResult(\n verificationId?: string,\n options: WaitForResultOptions = {}\n ): Promise<VerificationStatusResponse> {\n const id = await this.resolveVerificationId(verificationId);\n const stopOnReview = options.stopOnReview ?? true;\n\n return pollUntil<VerificationStatusResponse>(\n (signal) => this.getStatus(id, { signal }),\n (status) =>\n isTerminalStatus(status.status) ||\n (stopOnReview && status.status === 'REVIEW'),\n options,\n `verification ${id}`\n );\n }\n\n private async resolveVerificationId(explicit?: string): Promise<string> {\n if (explicit) return explicit;\n const stored = await this.session.read();\n if (stored?.verificationId) return stored.verificationId;\n throw new KycirisError(\n this.session.enabled\n ? 'No verificationId was given and there is no stored session to resume. Start a verification first.'\n : 'No verificationId was given. Pass one, or configure `storage` so the SDK can remember the verification it started.',\n { code: 'SESSION_NOT_FOUND' }\n );\n }\n\n // -------------------------------------------------------------------------\n // Review and operations (project API key)\n // -------------------------------------------------------------------------\n\n /**\n * A page of the project's verifications, newest first.\n *\n * Carries no OCR data or storage paths by design — a 20-row page is not the\n * place for identity-document PII. Read one verification for those.\n */\n async list(\n params: ListVerificationsParams = {},\n options: { signal?: AbortSignal } = {}\n ): Promise<Page<VerificationListItem>> {\n const result = await this.http.request<VerificationListItem[]>({\n path: '/verification',\n query: { ...params },\n auth: 'api-key',\n signal: options.signal,\n });\n return toPage(result);\n }\n\n /** Counts per status and outcome, plus what needs an operator's attention. */\n async summary(options: { signal?: AbortSignal } = {}): Promise<VerificationSummary> {\n const result = await this.http.request<VerificationSummary>({\n path: '/verification/summary',\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /**\n * A verification's recorded history, oldest first.\n *\n * The verification row keeps only the last decision, so this is the only\n * place the sequence survives.\n */\n async events(\n verificationId: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<PipelineEvent[]> {\n const result = await this.http.request<PipelineEvent[]>({\n path: `/verification/events/${encodeURIComponent(verificationId)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data ?? [];\n }\n\n /** Moves a PENDING verification to REVIEW so a person can look at it. */\n async sendToReview(\n verificationId: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<{ verificationId: string; status: string; message?: string }> {\n const result = await this.http.request<{\n verificationId: string;\n status: string;\n message?: string;\n }>({\n method: 'PATCH',\n path: `/verification/review/${encodeURIComponent(verificationId)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /**\n * Records a reviewer's decision and fires the matching webhook.\n *\n * Repeating the decision a verification already has is refused with 409 —\n * that is the gateway making a second webhook impossible, not a transient\n * failure. Changing a decision (rejected in error, then approved) is allowed.\n */\n async decide(\n verificationId: string,\n decision: ReviewDecision,\n options: { signal?: AbortSignal } = {}\n ): Promise<{ verificationId: string; status: string }> {\n const result = await this.http.request<{ verificationId: string; status: string }>({\n method: 'PATCH',\n path: `/verification/decision/${encodeURIComponent(verificationId)}`,\n body: decision,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n}\n","import type { HttpClient } from '../http/client';\nimport { toPage, type Page } from '../http/envelope';\nimport type {\n CreateWebhookParams,\n UpdateWebhookParams,\n Webhook,\n WebhookLogEntry,\n WebhookResendResult,\n} from '../types';\n\n/**\n * Where the gateway sends verification events.\n *\n * Webhooks are the right way to learn a verification's outcome: polling costs\n * a request every few seconds and still gives up, while a REVIEW can sit with\n * a human for hours. Subscribe with `[\"*\"]` when the intent is \"mirror my\n * verification lifecycle\" — a literal list of today's events silently stops\n * being complete the day an eighth one exists.\n *\n * The URL must be https with a public hostname; the gateway refuses anything\n * else, localhost included.\n */\nexport class WebhooksResource {\n constructor(private readonly http: HttpClient) {}\n\n async create(\n params: CreateWebhookParams,\n options: { signal?: AbortSignal } = {}\n ): Promise<Webhook> {\n const result = await this.http.request<Webhook>({\n method: 'POST',\n path: '/webhooks',\n body: params,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n async list(options: { signal?: AbortSignal } = {}): Promise<Webhook[]> {\n const result = await this.http.request<Webhook[]>({\n path: '/webhooks',\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data ?? [];\n }\n\n async get(id: string, options: { signal?: AbortSignal } = {}): Promise<Webhook> {\n const result = await this.http.request<Webhook>({\n path: `/webhooks/${encodeURIComponent(id)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n async update(\n id: string,\n params: UpdateWebhookParams,\n options: { signal?: AbortSignal } = {}\n ): Promise<Webhook> {\n const result = await this.http.request<Webhook>({\n method: 'PUT',\n path: `/webhooks/${encodeURIComponent(id)}`,\n body: params,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n async delete(id: string, options: { signal?: AbortSignal } = {}): Promise<void> {\n await this.http.request<void>({\n method: 'DELETE',\n path: `/webhooks/${encodeURIComponent(id)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n }\n\n /**\n * Delivery attempts, newest first — what was sent, what came back, how many\n * retries it took. The place to look when an endpoint stops receiving events.\n */\n async logs(\n params: { page?: number; limit?: number } = {},\n options: { signal?: AbortSignal } = {}\n ): Promise<Page<WebhookLogEntry>> {\n const result = await this.http.request<WebhookLogEntry[]>({\n path: '/webhook-log',\n query: { ...params },\n auth: 'api-key',\n signal: options.signal,\n });\n return toPage(result);\n }\n\n /** One delivery attempt. */\n async log(\n id: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<WebhookLogEntry> {\n const result = await this.http.request<WebhookLogEntry>({\n path: `/webhook-log/${encodeURIComponent(id)}`,\n auth: 'api-key',\n signal: options.signal,\n });\n return result.data;\n }\n\n /**\n * Sends a recorded delivery again, to the endpoint it originally went to.\n *\n * Synchronous: the result says whether it arrived this time. A failure comes\n * back as `{ success: false, error }` rather than throwing, because the\n * gateway has already written a FAILED row either way and the caller usually\n * wants to show the reason beside the delivery it belongs to. A missing\n * delivery (404) or a deleted endpoint (409) still throw -- those are not\n * outcomes of the send.\n *\n * Not retried: a resend that timed out may well have arrived.\n */\n async resendLog(\n id: string,\n options: { signal?: AbortSignal } = {}\n ): Promise<WebhookResendResult> {\n const result = await this.http.request<WebhookResendResult>({\n method: 'POST',\n path: `/webhook-log/${encodeURIComponent(id)}/resend`,\n auth: 'api-key',\n retry: false,\n signal: options.signal,\n });\n return result.data;\n }\n}\n","import type { DocumentType, CatalogCountry } from './types';\n\n/**\n * Pluggable key/value storage, so a verification that was interrupted can be\n * picked up again after the app is closed.\n *\n * Inject AsyncStorage on React Native, or an adapter around localStorage on\n * web. Methods may be synchronous or asynchronous; results are awaited either\n * way.\n */\nexport interface KycirisStorage {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<void>;\n removeItem(key: string): void | Promise<void>;\n}\n\n/** Versioned, so a future change of shape cannot read an old record wrongly. */\nexport const SESSION_STORAGE_KEY = 'kyciris:session:v1';\n\n/**\n * What the SDK remembers about an in-flight verification.\n *\n * Deliberately holds no credential. The verification token is a bearer\n * credential for one end user and persisting it would leave it in\n * AsyncStorage/localStorage long after the flow ended, readable by anything\n * else in the app; the host application decides where — and whether — to keep\n * it. Only identifiers live here, and all of them are already known to the\n * client that fetched them.\n */\nexport interface StoredSession {\n verificationId: string;\n identityId?: string;\n externalId?: string;\n documentType?: DocumentType | (string & {});\n country?: CatalogCountry | (string & {});\n levelName?: string;\n /** ISO 8601 instant the verification was started. */\n startedAt: string;\n}\n\nfunction isStoredSession(value: unknown): value is StoredSession {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as StoredSession).verificationId === 'string'\n );\n}\n\n/**\n * Reads and writes the resumable session.\n *\n * Every operation is best-effort: storage can be full, disabled (Safari private\n * browsing), or simply absent. Losing the ability to resume is a degraded flow;\n * throwing here would break a verification that is otherwise proceeding fine.\n */\nexport class SessionStore {\n constructor(private readonly storage?: KycirisStorage) {}\n\n /** True when a storage adapter was configured. */\n get enabled(): boolean {\n return Boolean(this.storage);\n }\n\n async save(session: StoredSession): Promise<void> {\n if (!this.storage) return;\n try {\n await this.storage.setItem(SESSION_STORAGE_KEY, JSON.stringify(session));\n } catch {\n // Best-effort; see the class comment.\n }\n }\n\n async read(): Promise<StoredSession | null> {\n if (!this.storage) return null;\n try {\n const raw = await this.storage.getItem(SESSION_STORAGE_KEY);\n if (!raw) return null;\n const parsed: unknown = JSON.parse(raw);\n // A record written by an older version, or corrupted, is discarded\n // rather than handed back half-formed.\n return isStoredSession(parsed) ? parsed : null;\n } catch {\n return null;\n }\n }\n\n async clear(): Promise<void> {\n if (!this.storage) return;\n try {\n await this.storage.removeItem(SESSION_STORAGE_KEY);\n } catch {\n // Best-effort; see the class comment.\n }\n }\n}\n\n/**\n * A storage adapter backed by a plain Map.\n *\n * For tests, and for a flow that should not outlive the process.\n */\nexport function createMemoryStorage(): KycirisStorage {\n const map = new Map<string, string>();\n return {\n getItem: (key) => map.get(key) ?? null,\n setItem: (key, value) => {\n map.set(key, value);\n },\n removeItem: (key) => {\n map.delete(key);\n },\n };\n}\n","import { HttpClient, type HttpClientConfig } from './http/client';\nimport { AnalyticsResource } from './resources/analytics';\nimport { IdentitiesResource } from './resources/identities';\nimport { LevelsResource } from './resources/levels';\nimport { MediaResourceApi } from './resources/media';\nimport { OcrResource } from './resources/ocr';\nimport { VerificationsResource } from './resources/verifications';\nimport { WebhooksResource } from './resources/webhooks';\nimport { SessionStore, type KycirisStorage } from './storage';\n\nexport interface KycirisClientConfig extends HttpClientConfig {\n /**\n * Where to remember an in-flight verification, so a flow interrupted by the\n * app closing can be resumed. AsyncStorage on React Native, an adapter around\n * localStorage on web. No credential is ever written to it.\n */\n storage?: KycirisStorage;\n}\n\n/**\n * The KYCiris API client.\n *\n * Two credentials, two audiences:\n *\n * - **`apiKey`** is the project's key. It reaches every endpoint, including\n * every identity in the project, and belongs on your server only.\n * - **`verificationToken`** is scoped to one end user and authorizes exactly\n * the verification flow. Mint it on your server with\n * `verifications.createToken(externalId)` and hand it to the client app.\n *\n * Constructing a client with `apiKey` inside a browser or React Native app\n * throws, because a key in a shipped bundle is a key the end user has.\n *\n * ```ts\n * // Your server\n * const server = createKycirisClient({ baseUrl, apiKey: process.env.KYCIRIS_API_KEY });\n * const { token } = await server.verifications.createToken('user-123');\n *\n * // Your app, with that token\n * const client = createKycirisClient({ baseUrl, verificationToken: token, storage });\n * const { verificationId } = await client.verifications.start({\n * country: 'AO',\n * documentType: 'ID_CARD',\n * });\n * ```\n */\nexport class KycirisClient {\n /** The end-user flow, plus review and operations reads. */\n readonly verifications: VerificationsResource;\n /** Identity records and re-authentication face checks. API key only. */\n readonly identities: IdentitiesResource;\n /** Verification levels (step policies). API key only. */\n readonly levels: LevelsResource;\n /** Single-use downloads of verification images. API key only. */\n readonly media: MediaResourceApi;\n /** Standalone document reading, outside the verification flow. */\n readonly ocr: OcrResource;\n /** Event subscriptions and their delivery log. API key only. */\n readonly webhooks: WebhooksResource;\n /** Monthly counts. API key only. */\n readonly analytics: AnalyticsResource;\n\n private readonly http: HttpClient;\n\n constructor(config: KycirisClientConfig) {\n this.http = new HttpClient(config);\n const session = new SessionStore(config.storage);\n\n this.verifications = new VerificationsResource(this.http, session);\n this.identities = new IdentitiesResource(this.http);\n this.levels = new LevelsResource(this.http);\n this.media = new MediaResourceApi(this.http);\n this.ocr = new OcrResource(this.http);\n this.webhooks = new WebhooksResource(this.http);\n this.analytics = new AnalyticsResource(this.http);\n }\n\n /**\n * Whether this client holds the project API key, and so can reach the\n * server-side endpoints.\n *\n * Worth checking in code that runs in both places, rather than letting a\n * MISSING_CREDENTIAL error be the way you find out.\n */\n get isServerSide(): boolean {\n return this.http.hasApiKey();\n }\n}\n\n/** Creates a KYCiris client. See {@link KycirisClient}. */\nexport function createKycirisClient(config: KycirisClientConfig): KycirisClient {\n return new KycirisClient(config);\n}\n","import type { KycirisClient } from './client';\nimport { KycirisError, isKycirisError } from './errors';\nimport type { FileInput } from './files';\nimport type {\n CatalogCountry,\n DocumentType,\n VerificationOutcome,\n VerificationStatus,\n VerificationStep,\n} from './types';\n\n/** Where the end user is in the flow. */\nexport type FlowPhase =\n /** Nothing started yet. */\n | 'idle'\n /** Creating the verification. */\n | 'starting'\n /** Waiting for the user to supply the current step's image. */\n | 'collecting'\n /** Uploading an image. */\n | 'uploading'\n /** Everything submitted; the pipeline is deciding. */\n | 'processing'\n /** A decision was reached, or a human was asked for one. */\n | 'finished'\n /** The flow stopped on an error. `error` says which. */\n | 'failed';\n\nexport interface FlowState {\n phase: FlowPhase;\n verificationId: string | null;\n /** The step to ask the user for now, or null when none is outstanding. */\n currentStep: VerificationStep | null;\n /** Every step still to collect, in order. */\n missingSteps: VerificationStep[];\n uploaded: Record<VerificationStep, boolean>;\n status: VerificationStatus | null;\n outcome: VerificationOutcome | null;\n /** Why the pipeline stopped, when it did. */\n rejectionReason: string | null;\n error: KycirisError | null;\n /** True while a request is in flight, for disabling a capture button. */\n busy: boolean;\n}\n\nexport interface FlowOptions {\n country: CatalogCountry | (string & {});\n documentType: DocumentType | (string & {});\n /** Verification level to run under. Required: the gateway has no default. */\n levelName: string;\n /** Your reference for the user. Ignored when a verification token is used. */\n externalId?: string;\n /**\n * Whether the level asks for a selfie. Defaults to true.\n *\n * A client holding a verification token cannot read its own level, so a\n * document-only level has to be declared here.\n */\n selfieRequired?: boolean;\n /** Poll for the decision once everything is uploaded. Defaults to true. */\n waitForDecision?: boolean;\n /** How long to poll before giving up, in ms. Defaults to 120000. */\n decisionTimeoutMs?: number;\n /** Called on every state change. */\n onStateChange?: (state: FlowState) => void;\n}\n\nconst EMPTY_UPLOADED: Record<VerificationStep, boolean> = {\n document_front: false,\n document_back: false,\n selfie: false,\n};\n\n/**\n * The end-user verification flow as a state machine, with no UI attached.\n *\n * The React Native and web components are both thin wrappers around this, so\n * the sequencing — which step comes next, what a resumed flow skips, when the\n * decision is polled for — is written and tested once.\n *\n * Every transition is observable through `subscribe`, and every method is safe\n * to call from a button handler: failures land in `state.error` rather than\n * rejecting, so a component never has to wrap calls in try/catch.\n *\n * ```ts\n * const flow = new VerificationFlow(client, { country: 'AO', documentType: 'ID_CARD' });\n * flow.subscribe(render);\n * await flow.start();\n * // then, per captured image:\n * await flow.submit(image);\n * ```\n */\nexport class VerificationFlow {\n private state: FlowState = {\n phase: 'idle',\n verificationId: null,\n currentStep: null,\n missingSteps: [],\n uploaded: { ...EMPTY_UPLOADED },\n status: null,\n outcome: null,\n rejectionReason: null,\n error: null,\n busy: false,\n };\n\n private listeners = new Set<(state: FlowState) => void>();\n private aborter: AbortController | null = null;\n\n constructor(\n private readonly client: KycirisClient,\n private readonly options: FlowOptions\n ) {\n if (options.onStateChange) this.listeners.add(options.onStateChange);\n }\n\n getState(): FlowState {\n return this.state;\n }\n\n /** Observes state changes. Returns an unsubscribe function. */\n subscribe(listener: (state: FlowState) => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /**\n * Starts a verification, or picks up the one already in storage.\n *\n * Resuming is the default because it is almost always what the user wants:\n * an app killed between the document and the selfie should carry on, not\n * ask for the document again. Pass `{ fresh: true }` to start over.\n */\n async start(options: { fresh?: boolean } = {}): Promise<FlowState> {\n return this.guard('starting', async (signal) => {\n if (options.fresh) {\n await this.client.verifications.clearSession();\n } else {\n const existing = await this.client.verifications.getSession();\n if (existing?.verificationId) {\n return this.loadProgress(existing.verificationId, signal);\n }\n }\n\n const session = await this.client.verifications.start(\n {\n country: this.options.country,\n documentType: this.options.documentType,\n levelName: this.options.levelName,\n externalId: this.options.externalId,\n },\n { signal }\n );\n\n return this.loadProgress(session.verificationId, signal);\n });\n }\n\n /**\n * Re-reads what the gateway holds.\n *\n * Worth calling when a component remounts, or after an upload whose response\n * never arrived: the file may well have landed, and this is what notices.\n */\n async refresh(): Promise<FlowState> {\n const verificationId = this.state.verificationId;\n if (!verificationId) return this.start();\n return this.guard(this.state.phase, (signal) =>\n this.loadProgress(verificationId, signal)\n );\n }\n\n /**\n * Uploads an image for the current step and advances.\n *\n * A step that turns out to be already uploaded is skipped rather than sent\n * again, so retrying after a dropped connection cannot duplicate work.\n */\n async submit(file: FileInput): Promise<FlowState> {\n const { verificationId, currentStep } = this.state;\n if (!verificationId) {\n return this.fail(\n new KycirisError('The flow has not been started yet.', {\n code: 'SESSION_NOT_FOUND',\n })\n );\n }\n if (!currentStep) {\n return this.fail(\n new KycirisError('There is no step waiting for an image.', {\n code: 'VALIDATION_ERROR',\n })\n );\n }\n\n return this.guard('uploading', async (signal) => {\n await this.client.verifications.uploadStep({\n step: currentStep,\n file,\n verificationId,\n selfieRequired: this.options.selfieRequired,\n signal,\n });\n return this.loadProgress(verificationId, signal);\n });\n }\n\n /**\n * Waits for the pipeline's decision.\n *\n * Called automatically once the last step is uploaded, unless\n * `waitForDecision` is false. Stops at REVIEW, which is a person's queue and\n * not something worth holding a spinner for.\n */\n async waitForDecision(): Promise<FlowState> {\n const verificationId = this.state.verificationId;\n if (!verificationId) {\n return this.fail(\n new KycirisError('The flow has not been started yet.', {\n code: 'SESSION_NOT_FOUND',\n })\n );\n }\n\n return this.guard('processing', async (signal) => {\n const status = await this.client.verifications.waitForResult(verificationId, {\n signal,\n timeoutMs: this.options.decisionTimeoutMs,\n });\n return {\n phase: 'finished' as FlowPhase,\n status: status.status,\n outcome: status.outcome,\n rejectionReason: status.rejectionReason,\n };\n });\n }\n\n /**\n * Cancels whatever is in flight.\n *\n * A component's unmount should call this, so a poll does not keep running\n * against a screen that is gone.\n */\n cancel(): void {\n this.aborter?.abort();\n this.aborter = null;\n if (this.state.busy) this.patch({ busy: false });\n }\n\n /** Cancels, forgets the stored session, and returns to `idle`. */\n async reset(): Promise<FlowState> {\n this.cancel();\n await this.client.verifications.clearSession();\n this.patch({\n phase: 'idle',\n verificationId: null,\n currentStep: null,\n missingSteps: [],\n uploaded: { ...EMPTY_UPLOADED },\n status: null,\n outcome: null,\n rejectionReason: null,\n error: null,\n busy: false,\n });\n return this.state;\n }\n\n // -------------------------------------------------------------------------\n\n /**\n * Reads progress and derives the next phase from it.\n *\n * Returns a patch rather than applying one, so `guard` stays the single\n * place that publishes a state change.\n */\n private async loadProgress(\n verificationId: string,\n signal?: AbortSignal\n ): Promise<Partial<FlowState>> {\n const progress = await this.client.verifications.getProgress(verificationId, {\n selfieRequired: this.options.selfieRequired,\n signal,\n });\n\n return {\n verificationId,\n currentStep: progress.missingSteps[0] ?? null,\n missingSteps: progress.missingSteps,\n uploaded: progress.uploaded,\n status: progress.status,\n outcome: progress.outcome,\n phase: progress.isComplete ? 'processing' : 'collecting',\n };\n }\n\n /**\n * Runs one transition: marks the flow busy, applies the resulting patch, and\n * turns any failure into `state.error` instead of a rejected promise.\n *\n * The awkward part it exists to contain is that reaching `processing` should\n * flow straight on into polling — but only when the caller asked for it, and\n * only once.\n */\n private async guard(\n phase: FlowPhase,\n run: (signal?: AbortSignal) => Promise<Partial<FlowState>>\n ): Promise<FlowState> {\n this.aborter?.abort();\n const aborter = new AbortController();\n this.aborter = aborter;\n\n this.patch({ phase, busy: true, error: null });\n\n try {\n const patch = await run(aborter.signal);\n this.patch({ ...patch, busy: false });\n\n const shouldWait =\n this.state.phase === 'processing' &&\n (this.options.waitForDecision ?? true) &&\n // Not a nested call: waitForDecision itself lands here with phase\n // 'processing' already set, and would otherwise recurse forever.\n phase !== 'processing';\n\n if (shouldWait) return this.waitForDecision();\n\n return this.state;\n } catch (error) {\n if (isKycirisError(error) && error.code === 'ABORTED') {\n this.patch({ busy: false });\n return this.state;\n }\n return this.fail(error);\n } finally {\n if (this.aborter === aborter) this.aborter = null;\n }\n }\n\n private fail(error: unknown): FlowState {\n const failure = isKycirisError(error)\n ? error\n : new KycirisError(\n error instanceof Error ? error.message : 'The verification failed.',\n { code: 'INTERNAL_SERVER_ERROR', cause: error }\n );\n this.patch({ phase: 'failed', busy: false, error: failure });\n return this.state;\n }\n\n private patch(patch: Partial<FlowState>): void {\n this.state = { ...this.state, ...patch };\n for (const listener of this.listeners) listener(this.state);\n }\n}\n"]}
|